diff options
author | Mike Erwin <significant.bit@gmail.com> | 2016-09-22 13:11:40 +0300 |
---|---|---|
committer | Mike Erwin <significant.bit@gmail.com> | 2016-09-22 13:11:40 +0300 |
commit | 0e7c3dfe75cb16158eb5df0520f32b7b7f0921f0 (patch) | |
tree | 2ac960ef8dddc358b79fc9dbdaddd683c317e4b8 | |
parent | 825150605e36547a6216228deabf79153ae2ae00 (diff) |
OpenGL: matrix code from viewport-fx
Bringing over whole files from rB194998766c65
-rw-r--r-- | source/blender/gpu/GPU_matrix.h | 106 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_matrix.c | 468 |
2 files changed, 574 insertions, 0 deletions
diff --git a/source/blender/gpu/GPU_matrix.h b/source/blender/gpu/GPU_matrix.h new file mode 100644 index 00000000000..9d61084af30 --- /dev/null +++ b/source/blender/gpu/GPU_matrix.h @@ -0,0 +1,106 @@ +#ifndef _GPU_MATRIX_H_ +#define _GPU_MATRIX_H_ + +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2012 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Alexandr Kuznetsov, Jason Wilkins + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file source/blender/gpu/GPU_matrix.h + * \ingroup gpu + */ + +#include "GPU_glew.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum eGPUMatrixMode { + GPU_MODELVIEW_MATRIX = 0, + GPU_PROJECTION_MATRIX = 1, + GPU_TEXTURE_MATRIX = 2 +} eGPUMatrixMode; + +void gpuPushMatrix(eGPUMatrixMode stack); +void gpuPopMatrix(eGPUMatrixMode stack); + +void gpuLoadMatrix(eGPUMatrixMode stack, const float m[16]); +void gpuLoadMatrixd(eGPUMatrixMode stack, const double m[16]); +const float *gpuGetMatrix(eGPUMatrixMode stack, float m[16]); +void gpuGetMatrixd(eGPUMatrixMode stack, double m[16]); + +void gpuLoadIdentity(eGPUMatrixMode stack); + +void gpuMultMatrix(eGPUMatrixMode stack, const float m[16]); +void gpuMultMatrixd(eGPUMatrixMode stack, const double m[16]); + +void gpuTranslate(eGPUMatrixMode stack, float x, float y, float z); +void gpuScale(eGPUMatrixMode stack, GLfloat x, GLfloat y, GLfloat z); +void gpuRotateVector(eGPUMatrixMode stack, GLfloat deg, GLfloat vector[3]); +void gpuRotateAxis(eGPUMatrixMode stack, GLfloat deg, char axis); +void gpuRotateRight(eGPUMatrixMode stack, char type); + +void gpuOrtho(eGPUMatrixMode stack, GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat nearVal, GLfloat farVal); +void gpuFrustum(eGPUMatrixMode stack, GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat nearVal, GLfloat farVal); + +void gpuLoadOrtho(eGPUMatrixMode stack, GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat nearVal, GLfloat farVal); +void gpuLoadFrustum(eGPUMatrixMode stack, GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat nearVal, GLfloat farVal); + +void gpuLookAt(eGPUMatrixMode stack, GLfloat eyeX, GLfloat eyeY, GLfloat eyeZ, GLfloat centerX, GLfloat centerY, GLfloat centerZ, GLfloat upX, GLfloat upY, GLfloat upZ); + +void gpuProject(const GLfloat obj[3], const GLfloat model[16], const GLfloat proj[16], const GLint view[4], GLfloat win[3]); +GLboolean gpuUnProject(const GLfloat win[3], const GLfloat model[16], const GLfloat proj[16], const GLint view[4], GLfloat obj[3]); + +void gpu_commit_matrix(void); + +void GPU_feedback_vertex_3fv(GLenum type, GLfloat x, GLfloat y, GLfloat z, GLfloat out[3]); +void GPU_feedback_vertex_4fv(GLenum type, GLfloat x, GLfloat y, GLfloat z, GLfloat w, GLfloat out[4]); +void GPU_feedback_vertex_4dv(GLenum type, GLdouble x, GLdouble y, GLdouble z, GLdouble w, GLdouble out[4]); + +#if defined(GLEW_ES_ONLY) + +/* ES 2.0 doesn't define these symbolic constants, but the matrix stack replacement library emulates them + * (GL core has deprecated matrix stacks, but it should still be in the header) */ + +#ifndef GL_MODELVIEW_MATRIX +#define GL_MODELVIEW_MATRIX 0x0BA6 +#endif + +#ifndef GL_PROJECTION_MATRIX +#define GL_PROJECTION_MATRIX 0x0BA7 +#endif + +#ifndef GL_TEXTURE_MATRIX +#define GL_TEXTURE_MATRIX 0x0BA8 +#endif + +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* GPU_MATRIX_H */ diff --git a/source/blender/gpu/intern/gpu_matrix.c b/source/blender/gpu/intern/gpu_matrix.c new file mode 100644 index 00000000000..29b8c0235de --- /dev/null +++ b/source/blender/gpu/intern/gpu_matrix.c @@ -0,0 +1,468 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the ipmlied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2012 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Alexandr Kuznetsov, Jason Wilkins + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file source/blender/gpu/intern/gpu_matrix.c + * \ingroup gpu + */ + +#if WITH_GL_PROFILE_COMPAT +#define GPU_MANGLE_DEPRECATED 0 /* Allow use of deprecated OpenGL functions in this file */ +#endif + +#include "BLI_sys_types.h" + +#include "GPU_common.h" +#include "GPU_debug.h" +#include "GPU_extensions.h" +#include "GPU_matrix.h" + +/* internal */ +#include "intern/gpu_private.h" + +/* external */ + +#include "BLI_math_matrix.h" +#include "BLI_math_rotation.h" +#include "BLI_math_vector.h" + +#include "MEM_guardedalloc.h" + + + +typedef GLfloat GPU_matrix[4][4]; + +typedef struct GPU_matrix_stack +{ + GLsizei size; + GLsizei pos; + GPU_matrix *dynstack; +} GPU_matrix_stack; + + +static GPU_matrix_stack mstacks[3]; + +/* Check if we have a good matrix */ +#ifdef WITH_GPU_SAFETY + +static void checkmat(GLfloat *m) +{ + GLint i; + + for (i = 0; i < 16; i++) { +#if _MSC_VER + BLI_assert(_finite(m[i])); +#else + BLI_assert(!isinf(m[i])); +#endif + } +} + +#define CHECKMAT(m) checkmat((GLfloat*)m) + +#else + +#define CHECKMAT(m) + +#endif + +static void ms_init(GPU_matrix_stack* ms, GLint initsize) +{ + BLI_assert(initsize > 0); + + ms->size = initsize; + ms->pos = 0; + ms->dynstack = (GPU_matrix*)MEM_mallocN(ms->size * sizeof(*(ms->dynstack)), "MatrixStack"); +} + +static void ms_free(GPU_matrix_stack *ms) +{ + ms->size = 0; + ms->pos = 0; + MEM_freeN(ms->dynstack); + ms->dynstack = NULL; +} + +void gpu_matrix_init(void) +{ + ms_init(&mstacks[GPU_TEXTURE_MATRIX], 16); + ms_init(&mstacks[GPU_PROJECTION_MATRIX], 16); + ms_init(&mstacks[GPU_MODELVIEW_MATRIX], 32); +} + +void gpu_matrix_exit(void) +{ + ms_free(&mstacks[GPU_TEXTURE_MATRIX]); + ms_free(&mstacks[GPU_PROJECTION_MATRIX]); + ms_free(&mstacks[GPU_MODELVIEW_MATRIX]); +} + +void gpu_commit_matrix(void) +{ + const struct GPUcommon *common = gpu_get_common(); + + GPU_ASSERT_NO_GL_ERRORS("gpu_commit_matrix start"); + + if (common) { + int i; + + float (*m)[4] = (float (*)[4])gpuGetMatrix(GPU_MODELVIEW_MATRIX, NULL); + float (*p)[4] = (float (*)[4])gpuGetMatrix(GPU_PROJECTION_MATRIX, NULL); + + if (common->modelview_matrix != -1) + glUniformMatrix4fv(common->modelview_matrix, 1, GL_FALSE, m[0]); + + if (common->normal_matrix != -1) { + float n[3][3]; + copy_m3_m4(n, m); + invert_m3(n); + transpose_m3(n); + glUniformMatrix3fv(common->normal_matrix, 1, GL_FALSE, n[0]); + } + + if (common->modelview_matrix_inverse != -1) { + float i[4][4]; + invert_m4_m4(i, m); + glUniformMatrix4fv(common->modelview_matrix_inverse, 1, GL_FALSE, i[0]); + } + + if (common->modelview_projection_matrix != -1) { + float pm[4][4]; + mul_m4_m4m4(pm, p, m); + glUniformMatrix4fv(common->modelview_projection_matrix, 1, GL_FALSE, pm[0]); + } + + if (common->projection_matrix != -1) + glUniformMatrix4fv(common->projection_matrix, 1, GL_FALSE, p[0]); + + for (i = 0; i < GPU_MAX_COMMON_TEXCOORDS; i++) { + if (common->texture_matrix[i] != -1) { + GPU_set_common_active_texture(i); + glUniformMatrix4fv(common->texture_matrix[i], 1, GL_FALSE, gpuGetMatrix(GPU_TEXTURE_MATRIX, NULL)); + } + } + + GPU_set_common_active_texture(0); + + GPU_ASSERT_NO_GL_ERRORS("gpu_commit_matrix end"); + + return; + } + +#if defined(WITH_GL_PROFILE_COMPAT) + glMatrixMode(GL_TEXTURE); + glLoadMatrixf(gpuGetMatrix(GPU_TEXTURE_MATRIX, NULL)); + + glMatrixMode(GL_PROJECTION); + glLoadMatrixf(gpuGetMatrix(GPU_PROJECTION_MATRIX, NULL)); + + glMatrixMode(GL_MODELVIEW); + glLoadMatrixf(gpuGetMatrix(GPU_MODELVIEW_MATRIX, NULL)); +#endif + + GPU_ASSERT_NO_GL_ERRORS("gpu_commit_matrix end"); +} + +void gpuPushMatrix(eGPUMatrixMode stack) +{ + GPU_matrix_stack *ms_current = mstacks + stack; + GLsizei new_pos = ms_current->pos + 1; + + BLI_assert(new_pos < ms_current->size); + + if (new_pos < ms_current->size) { + ms_current->pos++; + + gpuLoadMatrix(stack, ms_current->dynstack[ms_current->pos - 1][0]); + } +} + +void gpuPopMatrix(eGPUMatrixMode stack) +{ + GPU_matrix_stack *ms_current = mstacks + stack; + BLI_assert(ms_current->pos != 0); + + if (ms_current->pos != 0) { + ms_current->pos--; + + CHECKMAT(ms_current); + } +} + +void gpuLoadMatrix(eGPUMatrixMode stack, const float *m) +{ + GPU_matrix_stack *ms_current = mstacks + stack; + copy_m4_m4(ms_current->dynstack[ms_current->pos], (GLfloat (*)[4])m); + + CHECKMAT(ms_current); +} + +void gpuLoadMatrixd(eGPUMatrixMode stack, const double *md) +{ + GPU_matrix_stack *ms_current = mstacks + stack; + float mf[16]; + int i; + + for (i = 0; i < 16; i++) { + mf[i] = md[i]; + } + + copy_m4_m4(ms_current->dynstack[ms_current->pos], (float (*)[4])mf); + + CHECKMAT(ms_current); +} + + +const GLfloat *gpuGetMatrix(eGPUMatrixMode stack, GLfloat *m) +{ + GPU_matrix_stack *ms_select = mstacks + stack; + + if (m) { + copy_m4_m4((GLfloat (*)[4])m, ms_select->dynstack[ms_select->pos]); + return m; + } + else { + return (GLfloat*)(ms_select->dynstack[ms_select->pos]); + } +} + +void gpuGetMatrixd(eGPUMatrixMode stack, double m[16]) +{ + GPU_matrix_stack *ms_select = mstacks + stack; + + if (m) { + int i; + float *f = ms_select->dynstack[ms_select->pos][0]; + for (i = 0; i < 16; i++) { + m[i] = f[i]; + /* copy_m3_m3d(); should use something like */ + } + } +} + +void gpuLoadIdentity(eGPUMatrixMode stack) +{ + GPU_matrix_stack *ms_current = mstacks + stack; + unit_m4(ms_current->dynstack[ms_current->pos]); + + CHECKMAT(ms_current); +} + +void gpuTranslate(eGPUMatrixMode stack, float x, float y, float z) +{ + GPU_matrix_stack *ms_current = mstacks + stack; + translate_m4(ms_current->dynstack[ms_current->pos], x, y, z); + + CHECKMAT(ms_current); +} + +void gpuScale(eGPUMatrixMode stack, GLfloat x, GLfloat y, GLfloat z) +{ + GPU_matrix_stack *ms_current = mstacks + stack; + scale_m4(ms_current->dynstack[ms_current->pos], x, y, z); + + CHECKMAT(ms_current); +} + +void gpuMultMatrix(eGPUMatrixMode stack, const float *m) +{ + GPU_matrix_stack *ms_current = mstacks + stack; + GPU_matrix cm; + + copy_m4_m4(cm, ms_current->dynstack[ms_current->pos]); + mult_m4_m4m4_q(ms_current->dynstack[ms_current->pos], cm, (GLfloat (*)[4])m); + + CHECKMAT(ms_current); +} + +void gpuMultMatrixd(eGPUMatrixMode stack, const double *m) +{ + GLfloat mf[16]; + GLint i; + + for (i = 0; i < 16; i++) { + mf[i] = m[i]; + } + + gpuMultMatrix(stack, mf); +} + +void gpuRotateVector(eGPUMatrixMode stack, GLfloat deg, GLfloat vector[3]) +{ + GPU_matrix_stack *ms_current = mstacks + stack; + float rm[3][3]; + GPU_matrix cm; + + axis_angle_to_mat3(rm, vector, DEG2RADF(deg)); + + copy_m4_m4(cm, ms_current->dynstack[ms_current->pos]); + mult_m4_m3m4_q(ms_current->dynstack[ms_current->pos], cm, rm); + + CHECKMAT(ms_current); +} + +void gpuRotateAxis(eGPUMatrixMode stack, GLfloat deg, char axis) +{ + GPU_matrix_stack *ms_current = mstacks + stack; + rotate_m4(ms_current->dynstack[ms_current->pos], axis, DEG2RADF(deg)); + + CHECKMAT(ms_current); +} + +void gpuRotateRight(eGPUMatrixMode stack, char type) +{ + GPU_matrix_stack *ms_current = mstacks + stack; + rotate_m4_right(ms_current->dynstack[ms_current->pos], type); + + CHECKMAT(ms_current); +} + +void gpuLoadOrtho(eGPUMatrixMode stack, GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat nearVal, GLfloat farVal) +{ + GPU_matrix_stack *ms_current = mstacks + stack; + mat4_ortho_set(ms_current->dynstack[ms_current->pos], left, right, bottom, top, nearVal, farVal); + + CHECKMAT(ms_current); +} + +void gpuOrtho(eGPUMatrixMode stack, GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat nearVal, GLfloat farVal) +{ + GPU_matrix om; + + mat4_ortho_set(om, left, right, bottom, top, nearVal, farVal); + + gpuMultMatrix(stack, om[0]); +} + +void gpuFrustum(eGPUMatrixMode stack, GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat nearVal, GLfloat farVal) +{ + GPU_matrix fm; + + mat4_frustum_set(fm, left, right, bottom, top, nearVal, farVal); + + gpuMultMatrix(stack, fm[0]); +} + +void gpuLoadFrustum(eGPUMatrixMode stack, GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat nearVal, GLfloat farVal) +{ + GPU_matrix_stack *ms_current = mstacks + stack; + mat4_frustum_set(ms_current->dynstack[ms_current->pos], left, right, bottom, top, nearVal, farVal); + + CHECKMAT(ms_current); +} + +void gpuLookAt(eGPUMatrixMode stack, GLfloat eyeX, GLfloat eyeY, GLfloat eyeZ, GLfloat centerX, GLfloat centerY, GLfloat centerZ, GLfloat upX, GLfloat upY, GLfloat upZ) +{ + GPU_matrix cm; + GLfloat lookdir[3]; + GLfloat camup[3] = {upX, upY, upZ}; + + lookdir[0] = centerX - eyeX; + lookdir[1] = centerY - eyeY; + lookdir[2] = centerZ - eyeZ; + + mat4_look_from_origin(cm, lookdir, camup); + + gpuMultMatrix(stack, cm[0]); + gpuTranslate(stack, -eyeX, -eyeY, -eyeZ); +} + +void gpuProject(const GLfloat obj[3], const GLfloat model[16], const GLfloat proj[16], const GLint view[4], GLfloat win[3]) +{ + float v[4]; + + mul_v4_m4v3(v, (float(*)[4])model, obj); + mul_m4_v4((float(*)[4])proj, v); + + win[0] = view[0] + (view[2] * (v[0] + 1)) * 0.5f; + win[1] = view[1] + (view[3] * (v[1] + 1)) * 0.5f; + win[2] = (v[2] + 1) * 0.5f; +} + +GLboolean gpuUnProject(const GLfloat win[3], const GLfloat model[16], const GLfloat proj[16], const GLint view[4], GLfloat obj[3]) +{ + GLfloat pm[4][4]; + GLfloat in[4]; + GLfloat out[4]; + + mul_m4_m4m4(pm, (float(*)[4])proj, (float(*)[4])model); + + if (!invert_m4(pm)) { + return GL_FALSE; + } + + in[0] = win[0]; + in[1] = win[1]; + in[2] = win[2]; + in[3] = 1; + + /* Map x and y from window coordinates */ + in[0] = (in[0] - view[0]) / view[2]; + in[1] = (in[1] - view[1]) / view[3]; + + /* Map to range -1 to 1 */ + in[0] = 2 * in[0] - 1; + in[1] = 2 * in[1] - 1; + in[2] = 2 * in[2] - 1; + + mul_v4_m4v3(out, pm, in); + + if (out[3] == 0.0f) { + return GL_FALSE; + } + else { + out[0] /= out[3]; + out[1] /= out[3]; + out[2] /= out[3]; + + obj[0] = out[0]; + obj[1] = out[1]; + obj[2] = out[2]; + + return GL_TRUE; + } +} + +void GPU_feedback_vertex_3fv(GLenum type, GLfloat x, GLfloat y, GLfloat z, GLfloat out[3]) +{ + GPU_matrix *m = (GPU_matrix*)gpuGetMatrix(type, NULL); + float in[3] = {x, y, z}; + mul_v3_m4v3(out, m[0], in); +} + +void GPU_feedback_vertex_4fv(GLenum type, GLfloat x, GLfloat y, GLfloat z, GLfloat w, GLfloat out[3]) +{ + GPU_matrix *m = (GPU_matrix*)gpuGetMatrix(type, NULL); + float in[4] = {x, y, z, w}; + mul_v4_m4v4(out, m[0], in); +} + +void GPU_feedback_vertex_4dv(GLenum type, GLdouble x, GLdouble y, GLdouble z, GLdouble w, GLdouble out[3]) +{ + GPU_matrix *m = (GPU_matrix*)gpuGetMatrix(type, NULL); + double in[4] = {x, y, z, w}; + mul_v4d_m4v4d(out, m[0], in); +} |