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:
authorMike Erwin <significant.bit@gmail.com>2016-09-22 13:11:40 +0300
committerMike Erwin <significant.bit@gmail.com>2016-09-22 13:11:40 +0300
commit0e7c3dfe75cb16158eb5df0520f32b7b7f0921f0 (patch)
tree2ac960ef8dddc358b79fc9dbdaddd683c317e4b8
parent825150605e36547a6216228deabf79153ae2ae00 (diff)
OpenGL: matrix code from viewport-fx
Bringing over whole files from rB194998766c65
-rw-r--r--source/blender/gpu/GPU_matrix.h106
-rw-r--r--source/blender/gpu/intern/gpu_matrix.c468
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);
+}