Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/gpu/intern/gpu_matrix.c')
-rw-r--r--source/blender/gpu/intern/gpu_matrix.c550
1 files changed, 550 insertions, 0 deletions
diff --git a/source/blender/gpu/intern/gpu_matrix.c b/source/blender/gpu/intern/gpu_matrix.c
new file mode 100644
index 00000000000..dab468e6733
--- /dev/null
+++ b/source/blender/gpu/intern/gpu_matrix.c
@@ -0,0 +1,550 @@
+/*
+ * ***** 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
+
+/* my interface */
+#include "intern/gpu_matrix_intern.h"
+
+/* my library */
+#include "GPU_common.h"
+#include "GPU_extensions.h"
+#include "GPU_safety.h"
+
+/* internal */
+#include "intern/gpu_common_intern.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 ms_modelview;
+static GPU_matrix_stack ms_projection;
+static GPU_matrix_stack ms_texture;
+
+static GPU_matrix_stack* ms_current;
+static GLenum ms_current_mode;
+
+
+
+#define current_matrix() (ms_current->dynstack[ms_current->pos])
+
+
+
+/* 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
+ GPU_ASSERT(_finite(m[i]));
+#else
+ GPU_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(&ms_texture, 16);
+ ms_init(&ms_projection, 16);
+ ms_init(&ms_modelview, 32);
+
+ gpuMatrixMode(GL_TEXTURE);
+ gpuLoadIdentity();
+
+ gpuMatrixMode(GL_PROJECTION);
+ gpuLoadIdentity();
+
+ gpuMatrixMode(GL_MODELVIEW);
+ gpuLoadIdentity();
+}
+
+void gpu_matrix_exit(void)
+{
+ ms_free(&ms_modelview);
+ ms_free(&ms_projection);
+ ms_free(&ms_texture);
+
+ ms_current_mode = 0;
+ ms_current = NULL;
+}
+
+
+
+void gpu_commit_matrix(void)
+{
+ const struct GPUcommon* common = gpu_get_common();
+
+ GPU_CHECK_NO_ERROR();
+
+ if (common) {
+ int i;
+
+ GLfloat (*m)[4] = (GLfloat (*)[4])gpuGetMatrix(GL_MODELVIEW_MATRIX, NULL);
+ GLfloat (*p)[4] = (GLfloat (*)[4])gpuGetMatrix(GL_PROJECTION_MATRIX, NULL);
+
+ if (common->modelview_matrix != -1)
+ glUniformMatrix4fv(common->modelview_matrix, 1, GL_FALSE, m[0]);
+
+ if (common->normal_matrix != -1) {
+ GLfloat 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) {
+ GLfloat i[4][4];
+ invert_m4_m4(i, m);
+ glUniformMatrix4fv(common->modelview_matrix_inverse, 1, GL_FALSE, i[0]);
+ }
+
+ if (common->modelview_projection_matrix != -1) {
+ GLfloat 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(GL_TEXTURE_MATRIX, NULL));
+ }
+ }
+
+ GPU_set_common_active_texture(0);
+
+ GPU_CHECK_NO_ERROR();
+
+ return;
+ }
+
+#if defined(WITH_GL_PROFILE_COMPAT)
+ glMatrixMode(GL_TEXTURE);
+ glLoadMatrixf(gpuGetMatrix(GL_TEXTURE_MATRIX, NULL));
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadMatrixf(gpuGetMatrix(GL_PROJECTION_MATRIX, NULL));
+
+ glMatrixMode(GL_MODELVIEW);
+ glLoadMatrixf(gpuGetMatrix(GL_MODELVIEW_MATRIX, NULL));
+#endif
+
+ GPU_CHECK_NO_ERROR();
+}
+
+
+
+void gpuPushMatrix(void)
+{
+ GLsizei new_pos = ms_current->pos + 1;
+
+ GPU_ASSERT(new_pos < ms_current->size);
+
+ if (new_pos < ms_current->size) {
+ ms_current->pos++;
+
+ gpuLoadMatrix((GLfloat*)ms_current->dynstack[ms_current->pos-1]);
+ }
+}
+
+
+
+void gpuPopMatrix(void)
+{
+ GPU_ASSERT(ms_current->pos != 0);
+
+ if (ms_current->pos != 0) {
+ ms_current->pos--;
+
+ CHECKMAT(ms_current);
+ }
+}
+
+
+
+void gpuMatrixMode(GLenum mode)
+{
+ GPU_ASSERT(ELEM3(mode, GL_MODELVIEW, GL_PROJECTION, GL_TEXTURE));
+
+ ms_current_mode = mode;
+
+ switch(mode) {
+ case GL_MODELVIEW:
+ ms_current = &ms_modelview;
+ break;
+ case GL_PROJECTION:
+ ms_current = &ms_projection;
+ break;
+ case GL_TEXTURE:
+ ms_current = &ms_texture;
+ break;
+ default:
+ /* ignore */
+ break;
+ }
+}
+
+
+
+GLenum gpuGetMatrixMode(void)
+{
+ return ms_current_mode;
+}
+
+
+
+void gpuLoadMatrix(const GLfloat* m)
+{
+ copy_m4_m4(current_matrix(), (GLfloat (*)[4])m);
+
+ CHECKMAT(ms_current);
+}
+
+
+
+const GLfloat* gpuGetMatrix(GLenum type, GLfloat *m)
+{
+ GPU_matrix_stack* ms_select;
+
+ GPU_ASSERT(ELEM3(type, GL_MODELVIEW_MATRIX, GL_PROJECTION_MATRIX, GL_TEXTURE_MATRIX));
+
+ switch(type) {
+ case GL_MODELVIEW_MATRIX:
+ ms_select = &ms_modelview;
+ break;
+ case GL_PROJECTION_MATRIX:
+ ms_select = &ms_projection;
+ break;
+ case GL_TEXTURE_MATRIX:
+ ms_select = &ms_texture;
+ break;
+ default:
+ return NULL;
+ }
+
+ 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 gpuLoadIdentity(void)
+{
+ unit_m4(current_matrix());
+
+ CHECKMAT(ms_current);
+}
+
+
+
+void gpuTranslate(GLfloat x, GLfloat y, GLfloat z)
+{
+ translate_m4(current_matrix(), x, y, z);
+
+ CHECKMAT(ms_current);
+}
+
+
+
+void gpuScale(GLfloat x, GLfloat y, GLfloat z)
+{
+ scale_m4(current_matrix(), x, y, z);
+
+ CHECKMAT(ms_current);
+}
+
+
+
+void gpuMultMatrix(const GLfloat *m)
+{
+ GPU_matrix cm;
+
+ copy_m4_m4(cm, current_matrix());
+ mul_m4_m4m4_q(current_matrix(), cm, (GLfloat (*)[4])m);
+
+ CHECKMAT(ms_current);
+}
+
+
+
+void gpuMultMatrixd(const double *m)
+{
+ GLfloat mf[16];
+ GLint i;
+
+ for(i = 0; i < 16; i++) {
+ mf[i] = m[i];
+ }
+
+ gpuMultMatrix(mf);
+}
+
+
+
+void gpuRotateVector(GLfloat deg, GLfloat vector[3])
+{
+ float rm[3][3];
+ GPU_matrix cm;
+
+ axis_angle_to_mat3(rm, vector, DEG2RADF(deg));
+
+ copy_m4_m4(cm, current_matrix());
+ mul_m4_m3m4_q(current_matrix(), cm, rm);
+
+ CHECKMAT(ms_current);
+}
+
+
+
+void gpuRotateAxis(GLfloat deg, char axis)
+{
+ rotate_m4(current_matrix(), axis, DEG2RADF(deg));
+
+ CHECKMAT(ms_current);
+}
+
+
+
+void gpuRotateRight(char type)
+{
+ rotate_m4_right(current_matrix(), type);
+
+ CHECKMAT(ms_current);
+}
+
+
+
+void gpuLoadOrtho(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat nearVal, GLfloat farVal)
+{
+ mat4_ortho_set(current_matrix(), left, right, bottom, top, nearVal, farVal);
+
+ CHECKMAT(ms_current);
+}
+
+
+
+void gpuOrtho(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((GLfloat*)om);
+}
+
+
+
+void gpuFrustum(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((GLfloat*) fm);
+}
+
+
+
+void gpuLoadFrustum(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat nearVal, GLfloat farVal)
+{
+ mat4_frustum_set(current_matrix(), left, right, bottom, top, nearVal, farVal);
+
+ CHECKMAT(ms_current);
+}
+
+
+
+void gpuLookAt(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((GLfloat*) cm);
+ gpuTranslate(-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.0) {
+ 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);
+}