2016-09-22 12:11:40 +02:00
|
|
|
/*
|
|
|
|
* ***** 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.
|
|
|
|
*
|
2016-09-25 19:29:45 +02:00
|
|
|
* Contributor(s): Alexandr Kuznetsov, Jason Wilkins, Mike Erwin
|
2016-09-22 12:11:40 +02:00
|
|
|
*
|
|
|
|
* ***** END GPL LICENSE BLOCK *****
|
|
|
|
*/
|
|
|
|
|
|
|
|
/** \file source/blender/gpu/intern/gpu_matrix.c
|
|
|
|
* \ingroup gpu
|
|
|
|
*/
|
|
|
|
|
2017-03-21 17:27:17 -04:00
|
|
|
#define SUPPRESS_GENERIC_MATRIX_API
|
2016-09-22 12:11:40 +02:00
|
|
|
#include "GPU_matrix.h"
|
|
|
|
|
|
|
|
#include "BLI_math_matrix.h"
|
|
|
|
#include "BLI_math_rotation.h"
|
|
|
|
#include "BLI_math_vector.h"
|
|
|
|
|
|
|
|
|
2016-10-11 14:44:12 -04:00
|
|
|
#define DEBUG_MATRIX_BIND 0
|
|
|
|
|
2016-09-25 19:29:45 +02:00
|
|
|
#define MATRIX_STACK_DEPTH 32
|
|
|
|
|
|
|
|
typedef float Mat4[4][4];
|
|
|
|
typedef float Mat3[3][3];
|
2016-09-22 12:11:40 +02:00
|
|
|
|
2016-09-25 19:29:45 +02:00
|
|
|
typedef struct {
|
|
|
|
Mat4 ModelViewStack3D[MATRIX_STACK_DEPTH];
|
|
|
|
Mat4 ProjectionMatrix3D;
|
2016-09-22 12:11:40 +02:00
|
|
|
|
2017-04-13 04:00:19 -04:00
|
|
|
#if MATRIX_2D_4x4
|
|
|
|
Mat4 ModelViewStack2D[MATRIX_STACK_DEPTH];
|
|
|
|
Mat4 ProjectionMatrix2D;
|
|
|
|
#else
|
2016-09-25 19:29:45 +02:00
|
|
|
Mat3 ModelViewStack2D[MATRIX_STACK_DEPTH];
|
|
|
|
Mat3 ProjectionMatrix2D;
|
2017-04-13 04:00:19 -04:00
|
|
|
#endif
|
2016-09-22 12:11:40 +02:00
|
|
|
|
2016-09-25 19:29:45 +02:00
|
|
|
MatrixMode mode;
|
|
|
|
unsigned top; /* of current stack (would have to replicate if gpuResume2D/3D are implemented) */
|
2016-10-20 14:17:54 -04:00
|
|
|
|
|
|
|
bool dirty;
|
|
|
|
|
2016-09-25 19:29:45 +02:00
|
|
|
/* TODO: cache of derived matrices (Normal, MVP, inverse MVP, etc)
|
|
|
|
* generate as needed for shaders, invalidate when original matrices change
|
|
|
|
*
|
|
|
|
* TODO: separate Model from View transform? Batches/objects have model,
|
|
|
|
* camera/eye has view & projection
|
|
|
|
*/
|
|
|
|
} MatrixState;
|
|
|
|
|
|
|
|
static MatrixState state; /* TODO(merwin): make part of GPUContext, alongside immediate mode & state tracker */
|
|
|
|
|
|
|
|
#define ModelView3D state.ModelViewStack3D[state.top]
|
|
|
|
#define ModelView2D state.ModelViewStack2D[state.top]
|
|
|
|
#define Projection3D state.ProjectionMatrix3D
|
|
|
|
#define Projection2D state.ProjectionMatrix2D
|
|
|
|
|
2017-02-09 02:28:55 +11:00
|
|
|
void gpuMatrixInit(void)
|
2016-09-22 12:11:40 +02:00
|
|
|
{
|
2016-09-25 19:29:45 +02:00
|
|
|
memset(&state, 0, sizeof(MatrixState));
|
|
|
|
}
|
2016-09-22 12:11:40 +02:00
|
|
|
|
2017-02-09 02:28:55 +11:00
|
|
|
void gpuMatrixBegin2D(void)
|
2016-09-25 19:29:45 +02:00
|
|
|
{
|
|
|
|
state.mode = MATRIX_MODE_2D;
|
|
|
|
state.top = 0;
|
2017-04-13 04:00:19 -04:00
|
|
|
#if MATRIX_2D_4x4
|
|
|
|
unit_m4(ModelView2D);
|
|
|
|
unit_m4(Projection2D);
|
|
|
|
#else
|
2016-09-25 19:29:45 +02:00
|
|
|
unit_m3(ModelView2D);
|
2017-03-26 21:12:39 -04:00
|
|
|
unit_m3(Projection2D);
|
2017-04-13 04:00:19 -04:00
|
|
|
#endif
|
2016-09-25 19:29:45 +02:00
|
|
|
}
|
|
|
|
|
2017-02-09 02:28:55 +11:00
|
|
|
void gpuMatrixBegin3D(void)
|
2016-09-25 19:29:45 +02:00
|
|
|
{
|
|
|
|
state.mode = MATRIX_MODE_3D;
|
|
|
|
state.top = 0;
|
|
|
|
unit_m4(ModelView3D);
|
2017-03-26 21:12:39 -04:00
|
|
|
unit_m4(Projection3D);
|
2016-09-25 19:29:45 +02:00
|
|
|
}
|
|
|
|
|
2017-02-09 02:28:55 +11:00
|
|
|
void gpuMatrixEnd(void)
|
2016-09-25 19:29:45 +02:00
|
|
|
{
|
|
|
|
state.mode = MATRIX_MODE_INACTIVE;
|
|
|
|
}
|
2016-09-22 12:11:40 +02:00
|
|
|
|
|
|
|
|
|
|
|
#ifdef WITH_GPU_SAFETY
|
|
|
|
|
2016-09-25 19:29:45 +02:00
|
|
|
/* Check if matrix is numerically good */
|
|
|
|
static void checkmat(cosnt float *m)
|
2016-09-22 12:11:40 +02:00
|
|
|
{
|
2017-04-13 04:00:19 -04:00
|
|
|
#if MATRIX_2D_4x4
|
|
|
|
const int n = 16;
|
|
|
|
#else
|
2016-09-25 19:29:45 +02:00
|
|
|
const int n = state.mode == MATRIX_MODE_3D ? 16 : 9;
|
2017-04-13 04:00:19 -04:00
|
|
|
#endif
|
2016-09-25 19:29:45 +02:00
|
|
|
for (int i = 0; i < n; i++) {
|
2016-09-22 12:11:40 +02:00
|
|
|
#if _MSC_VER
|
|
|
|
BLI_assert(_finite(m[i]));
|
|
|
|
#else
|
|
|
|
BLI_assert(!isinf(m[i]));
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-09-25 19:29:45 +02:00
|
|
|
#define CHECKMAT(m) checkmat((const float*)m)
|
2016-09-22 12:11:40 +02:00
|
|
|
|
|
|
|
#else
|
|
|
|
|
|
|
|
#define CHECKMAT(m)
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
2017-02-09 02:28:55 +11:00
|
|
|
void gpuPushMatrix(void)
|
2016-09-25 19:29:45 +02:00
|
|
|
{
|
2017-03-20 17:19:21 -04:00
|
|
|
#if SUPPORT_LEGACY_MATRIX
|
|
|
|
if (state.mode == MATRIX_MODE_INACTIVE) {
|
|
|
|
glPushMatrix();
|
2017-03-21 00:25:47 -04:00
|
|
|
state.dirty = true;
|
2017-03-20 17:19:21 -04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2016-09-25 19:29:45 +02:00
|
|
|
BLI_assert(state.mode != MATRIX_MODE_INACTIVE);
|
|
|
|
BLI_assert(state.top < MATRIX_STACK_DEPTH);
|
|
|
|
state.top++;
|
|
|
|
if (state.mode == MATRIX_MODE_3D)
|
|
|
|
copy_m4_m4(ModelView3D, state.ModelViewStack3D[state.top - 1]);
|
|
|
|
else
|
2017-04-13 04:00:19 -04:00
|
|
|
#if MATRIX_2D_4x4
|
|
|
|
copy_m4_m4(ModelView2D, state.ModelViewStack2D[state.top - 1]);
|
|
|
|
#else
|
2016-09-25 19:29:45 +02:00
|
|
|
copy_m3_m3(ModelView2D, state.ModelViewStack2D[state.top - 1]);
|
2017-04-13 04:00:19 -04:00
|
|
|
#endif
|
2016-09-22 12:11:40 +02:00
|
|
|
}
|
|
|
|
|
2017-02-09 02:28:55 +11:00
|
|
|
void gpuPopMatrix(void)
|
2016-09-22 12:11:40 +02:00
|
|
|
{
|
2017-03-20 17:19:21 -04:00
|
|
|
#if SUPPORT_LEGACY_MATRIX
|
|
|
|
if (state.mode == MATRIX_MODE_INACTIVE) {
|
|
|
|
glPopMatrix();
|
2017-03-21 00:25:47 -04:00
|
|
|
state.dirty = true;
|
2017-03-20 17:19:21 -04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2016-09-25 19:29:45 +02:00
|
|
|
BLI_assert(state.mode != MATRIX_MODE_INACTIVE);
|
|
|
|
BLI_assert(state.top > 0);
|
|
|
|
state.top--;
|
2016-10-20 14:17:54 -04:00
|
|
|
state.dirty = true;
|
2016-09-22 12:11:40 +02:00
|
|
|
}
|
|
|
|
|
2016-09-25 19:29:45 +02:00
|
|
|
void gpuLoadMatrix3D(const float m[4][4])
|
2016-09-22 12:11:40 +02:00
|
|
|
{
|
2017-03-20 17:19:21 -04:00
|
|
|
#if SUPPORT_LEGACY_MATRIX
|
|
|
|
if (state.mode == MATRIX_MODE_INACTIVE) {
|
2017-03-21 00:25:47 -04:00
|
|
|
glLoadMatrixf((const float*) m);
|
|
|
|
state.dirty = true;
|
|
|
|
return;
|
2017-03-20 17:19:21 -04:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2016-09-25 19:29:45 +02:00
|
|
|
BLI_assert(state.mode == MATRIX_MODE_3D);
|
|
|
|
copy_m4_m4(ModelView3D, m);
|
|
|
|
CHECKMAT(ModelView3D);
|
2016-10-20 14:17:54 -04:00
|
|
|
state.dirty = true;
|
2016-09-22 12:11:40 +02:00
|
|
|
}
|
|
|
|
|
2017-03-21 18:10:20 -04:00
|
|
|
void gpuLoadProjectionMatrix3D(const float m[4][4])
|
|
|
|
{
|
|
|
|
#if SUPPORT_LEGACY_MATRIX
|
|
|
|
if (state.mode == MATRIX_MODE_INACTIVE) {
|
2017-03-21 19:36:29 -04:00
|
|
|
GLenum mode;
|
|
|
|
glGetIntegerv(GL_MATRIX_MODE, (GLint*)&mode);
|
2017-03-22 14:45:35 -04:00
|
|
|
if (mode != GL_PROJECTION) {
|
|
|
|
glMatrixMode(GL_PROJECTION);
|
2017-03-21 18:10:20 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
glLoadMatrixf((const float*) m);
|
|
|
|
|
|
|
|
if (mode != GL_PROJECTION_MATRIX) {
|
|
|
|
glMatrixMode(mode); /* restore */
|
|
|
|
}
|
|
|
|
|
|
|
|
state.dirty = true;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
BLI_assert(state.mode == MATRIX_MODE_3D);
|
|
|
|
copy_m4_m4(Projection3D, m);
|
|
|
|
CHECKMAT(Projection3D);
|
|
|
|
state.dirty = true;
|
|
|
|
}
|
|
|
|
|
2017-04-13 04:00:19 -04:00
|
|
|
#if 0 /* unused at the moment */
|
2016-09-25 19:29:45 +02:00
|
|
|
void gpuLoadMatrix2D(const float m[3][3])
|
2016-09-22 12:11:40 +02:00
|
|
|
{
|
2016-09-25 19:29:45 +02:00
|
|
|
BLI_assert(state.mode == MATRIX_MODE_2D);
|
|
|
|
copy_m3_m3(ModelView2D, m);
|
|
|
|
CHECKMAT(ModelView2D);
|
2016-10-20 14:17:54 -04:00
|
|
|
state.dirty = true;
|
2016-09-22 12:11:40 +02:00
|
|
|
}
|
2017-04-13 04:00:19 -04:00
|
|
|
#endif
|
2016-09-22 12:11:40 +02:00
|
|
|
|
2017-02-09 02:28:55 +11:00
|
|
|
void gpuLoadIdentity(void)
|
2016-09-22 12:11:40 +02:00
|
|
|
{
|
2016-09-25 19:29:45 +02:00
|
|
|
switch (state.mode) {
|
|
|
|
case MATRIX_MODE_3D:
|
|
|
|
unit_m4(ModelView3D);
|
|
|
|
break;
|
|
|
|
case MATRIX_MODE_2D:
|
2017-04-13 04:00:19 -04:00
|
|
|
#if MATRIX_2D_4x4
|
|
|
|
unit_m4(ModelView2D);
|
|
|
|
#else
|
2016-09-25 19:29:45 +02:00
|
|
|
unit_m3(ModelView2D);
|
2017-04-13 04:00:19 -04:00
|
|
|
#endif
|
2016-09-25 19:29:45 +02:00
|
|
|
break;
|
2017-03-20 17:19:21 -04:00
|
|
|
#if SUPPORT_LEGACY_MATRIX
|
|
|
|
case MATRIX_MODE_INACTIVE:
|
|
|
|
glLoadIdentity();
|
|
|
|
break;
|
|
|
|
#endif
|
2016-09-25 19:29:45 +02:00
|
|
|
default:
|
|
|
|
BLI_assert(false);
|
|
|
|
}
|
2016-10-20 14:17:54 -04:00
|
|
|
state.dirty = true;
|
2016-09-25 19:29:45 +02:00
|
|
|
}
|
2016-09-22 12:11:40 +02:00
|
|
|
|
2016-09-25 19:29:45 +02:00
|
|
|
void gpuTranslate2f(float x, float y)
|
|
|
|
{
|
2017-03-20 17:19:21 -04:00
|
|
|
#if SUPPORT_LEGACY_MATRIX
|
|
|
|
if (state.mode == MATRIX_MODE_INACTIVE) {
|
|
|
|
glTranslatef(x, y, 0.0f);
|
2017-03-21 00:25:47 -04:00
|
|
|
state.dirty = true;
|
2017-03-20 17:19:21 -04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2017-04-13 04:00:19 -04:00
|
|
|
#if MATRIX_2D_4x4
|
|
|
|
Mat4 m;
|
|
|
|
unit_m4(m);
|
|
|
|
m[3][0] = x;
|
|
|
|
m[3][1] = y;
|
|
|
|
#else
|
2016-09-25 19:29:45 +02:00
|
|
|
Mat3 m;
|
|
|
|
unit_m3(m);
|
|
|
|
m[2][0] = x;
|
|
|
|
m[2][1] = y;
|
2017-04-13 04:00:19 -04:00
|
|
|
#endif
|
2016-09-25 19:29:45 +02:00
|
|
|
gpuMultMatrix2D(m);
|
|
|
|
}
|
2016-09-22 12:11:40 +02:00
|
|
|
|
2016-09-25 19:29:45 +02:00
|
|
|
void gpuTranslate2fv(const float vec[2])
|
|
|
|
{
|
|
|
|
gpuTranslate2f(vec[0], vec[1]);
|
|
|
|
}
|
2016-09-22 12:11:40 +02:00
|
|
|
|
2016-09-25 19:29:45 +02:00
|
|
|
void gpuTranslate3f(float x, float y, float z)
|
|
|
|
{
|
2017-03-20 17:19:21 -04:00
|
|
|
#if SUPPORT_LEGACY_MATRIX
|
|
|
|
if (state.mode == MATRIX_MODE_INACTIVE) {
|
|
|
|
glTranslatef(x, y, z);
|
2017-03-21 00:25:47 -04:00
|
|
|
state.dirty = true;
|
2017-03-20 17:19:21 -04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2016-09-25 19:29:45 +02:00
|
|
|
BLI_assert(state.mode == MATRIX_MODE_3D);
|
2016-10-20 14:17:54 -04:00
|
|
|
#if 1
|
2016-09-25 19:29:45 +02:00
|
|
|
translate_m4(ModelView3D, x, y, z);
|
|
|
|
CHECKMAT(ModelView3D);
|
2016-10-11 21:13:13 -04:00
|
|
|
#else /* above works well in early testing, below is generic version */
|
|
|
|
Mat4 m;
|
|
|
|
unit_m4(m);
|
|
|
|
m[3][0] = x;
|
|
|
|
m[3][1] = y;
|
|
|
|
m[3][2] = z;
|
|
|
|
gpuMultMatrix3D(m);
|
|
|
|
#endif
|
2016-10-20 14:17:54 -04:00
|
|
|
state.dirty = true;
|
2016-09-25 19:29:45 +02:00
|
|
|
}
|
2016-09-22 12:11:40 +02:00
|
|
|
|
2016-09-25 19:29:45 +02:00
|
|
|
void gpuTranslate3fv(const float vec[3])
|
|
|
|
{
|
|
|
|
gpuTranslate3f(vec[0], vec[1], vec[2]);
|
|
|
|
}
|
2016-09-22 12:11:40 +02:00
|
|
|
|
2016-09-25 19:29:45 +02:00
|
|
|
void gpuScaleUniform(float factor)
|
|
|
|
{
|
|
|
|
switch (state.mode) {
|
|
|
|
case MATRIX_MODE_3D:
|
|
|
|
{
|
|
|
|
Mat4 m;
|
|
|
|
scale_m4_fl(m, factor);
|
|
|
|
gpuMultMatrix3D(m);
|
|
|
|
break;
|
2016-09-22 12:11:40 +02:00
|
|
|
}
|
2016-09-25 19:29:45 +02:00
|
|
|
case MATRIX_MODE_2D:
|
|
|
|
{
|
2017-04-13 04:00:19 -04:00
|
|
|
#if MATRIX_2D_4x4
|
|
|
|
Mat4 m = {{0.0f}};
|
|
|
|
m[0][0] = factor;
|
|
|
|
m[1][1] = factor;
|
|
|
|
m[2][2] = 1.0f;
|
|
|
|
m[3][3] = 1.0f;
|
|
|
|
#else
|
2016-09-25 19:29:45 +02:00
|
|
|
Mat3 m = {{0.0f}};
|
|
|
|
m[0][0] = factor;
|
|
|
|
m[1][1] = factor;
|
|
|
|
m[2][2] = 1.0f;
|
2017-04-13 04:00:19 -04:00
|
|
|
#endif
|
2016-09-25 19:29:45 +02:00
|
|
|
gpuMultMatrix2D(m);
|
|
|
|
break;
|
2016-09-22 12:11:40 +02:00
|
|
|
}
|
2017-03-20 17:19:21 -04:00
|
|
|
#if SUPPORT_LEGACY_MATRIX
|
|
|
|
case MATRIX_MODE_INACTIVE:
|
|
|
|
glScalef(factor, factor, factor); /* always scale Z since we can't distinguish 2D from 3D */
|
2017-03-21 00:25:47 -04:00
|
|
|
state.dirty = true;
|
2017-03-20 17:19:21 -04:00
|
|
|
break;
|
|
|
|
#endif
|
2016-09-25 19:29:45 +02:00
|
|
|
default:
|
|
|
|
BLI_assert(false);
|
2016-09-22 12:11:40 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-09-25 19:29:45 +02:00
|
|
|
void gpuScale2f(float x, float y)
|
2016-09-22 12:11:40 +02:00
|
|
|
{
|
2017-03-20 17:19:21 -04:00
|
|
|
#if SUPPORT_LEGACY_MATRIX
|
|
|
|
if (state.mode == MATRIX_MODE_INACTIVE) {
|
|
|
|
glScalef(x, y, 1.0f);
|
2017-03-21 00:25:47 -04:00
|
|
|
state.dirty = true;
|
2017-03-20 17:19:21 -04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2017-04-13 04:00:19 -04:00
|
|
|
#if MATRIX_2D_4x4
|
|
|
|
Mat4 m = {{0.0f}};
|
|
|
|
m[0][0] = x;
|
|
|
|
m[1][1] = y;
|
|
|
|
m[2][2] = 1.0f;
|
|
|
|
m[3][3] = 1.0f;
|
|
|
|
#else
|
2016-09-25 19:29:45 +02:00
|
|
|
Mat3 m = {{0.0f}};
|
|
|
|
m[0][0] = x;
|
|
|
|
m[1][1] = y;
|
|
|
|
m[2][2] = 1.0f;
|
2017-04-13 04:00:19 -04:00
|
|
|
#endif
|
2016-09-25 19:29:45 +02:00
|
|
|
gpuMultMatrix2D(m);
|
2016-09-22 12:11:40 +02:00
|
|
|
}
|
|
|
|
|
2016-09-25 19:29:45 +02:00
|
|
|
void gpuScale2fv(const float vec[2])
|
2016-09-22 12:11:40 +02:00
|
|
|
{
|
2016-09-25 19:29:45 +02:00
|
|
|
gpuScale2f(vec[0], vec[1]);
|
2016-09-22 12:11:40 +02:00
|
|
|
}
|
|
|
|
|
2016-09-25 19:29:45 +02:00
|
|
|
void gpuScale3f(float x, float y, float z)
|
2016-09-22 12:11:40 +02:00
|
|
|
{
|
2017-03-20 17:19:21 -04:00
|
|
|
#if SUPPORT_LEGACY_MATRIX
|
|
|
|
if (state.mode == MATRIX_MODE_INACTIVE) {
|
|
|
|
glScalef(x, y, z);
|
2017-03-21 00:25:47 -04:00
|
|
|
state.dirty = true;
|
2017-03-20 17:19:21 -04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2016-09-25 19:29:45 +02:00
|
|
|
Mat4 m = {{0.0f}};
|
|
|
|
m[0][0] = x;
|
|
|
|
m[1][1] = y;
|
|
|
|
m[2][2] = z;
|
|
|
|
m[3][3] = 1.0f;
|
|
|
|
gpuMultMatrix3D(m);
|
2016-09-22 12:11:40 +02:00
|
|
|
}
|
|
|
|
|
2016-09-25 19:29:45 +02:00
|
|
|
void gpuScale3fv(const float vec[3])
|
2016-09-22 12:11:40 +02:00
|
|
|
{
|
2016-09-25 19:29:45 +02:00
|
|
|
gpuScale3f(vec[0], vec[1], vec[2]);
|
2016-09-22 12:11:40 +02:00
|
|
|
}
|
|
|
|
|
2016-09-25 19:29:45 +02:00
|
|
|
void gpuMultMatrix3D(const float m[4][4])
|
2016-09-22 12:11:40 +02:00
|
|
|
{
|
2017-03-20 17:19:21 -04:00
|
|
|
#if SUPPORT_LEGACY_MATRIX
|
|
|
|
if (state.mode == MATRIX_MODE_INACTIVE) {
|
|
|
|
glMultMatrixf((const float*) m);
|
2017-03-21 00:25:47 -04:00
|
|
|
state.dirty = true;
|
2017-03-20 17:19:21 -04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2016-09-25 19:29:45 +02:00
|
|
|
BLI_assert(state.mode == MATRIX_MODE_3D);
|
2017-01-31 17:03:07 -05:00
|
|
|
mul_m4_m4_post(ModelView3D, m);
|
2016-09-25 19:29:45 +02:00
|
|
|
CHECKMAT(ModelView3D);
|
2016-10-20 14:17:54 -04:00
|
|
|
state.dirty = true;
|
2016-09-22 12:11:40 +02:00
|
|
|
}
|
|
|
|
|
2017-04-13 04:00:19 -04:00
|
|
|
#if MATRIX_2D_4x4
|
|
|
|
void gpuMultMatrix2D(const float m[4][4])
|
|
|
|
{
|
|
|
|
BLI_assert(state.mode == MATRIX_MODE_2D);
|
|
|
|
mul_m4_m4_post(ModelView2D, m);
|
|
|
|
CHECKMAT(ModelView2D);
|
|
|
|
state.dirty = true;
|
|
|
|
}
|
|
|
|
#else
|
2016-09-25 19:29:45 +02:00
|
|
|
void gpuMultMatrix2D(const float m[3][3])
|
2016-09-22 12:11:40 +02:00
|
|
|
{
|
2016-09-25 19:29:45 +02:00
|
|
|
BLI_assert(state.mode == MATRIX_MODE_2D);
|
2017-01-31 17:03:07 -05:00
|
|
|
mul_m3_m3_post(ModelView2D, m);
|
2016-09-25 19:29:45 +02:00
|
|
|
CHECKMAT(ModelView2D);
|
2016-10-20 14:17:54 -04:00
|
|
|
state.dirty = true;
|
2016-09-22 12:11:40 +02:00
|
|
|
}
|
2017-04-13 04:00:19 -04:00
|
|
|
#endif
|
2016-09-22 12:11:40 +02:00
|
|
|
|
2017-03-21 00:08:09 -04:00
|
|
|
void gpuRotate2D(float deg)
|
|
|
|
{
|
|
|
|
#if SUPPORT_LEGACY_MATRIX
|
|
|
|
if (state.mode == MATRIX_MODE_INACTIVE) {
|
|
|
|
glRotatef(deg, 0.0f, 0.0f, 1.0f);
|
2017-03-21 00:25:47 -04:00
|
|
|
state.dirty = true;
|
2017-03-21 00:08:09 -04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2017-04-13 04:00:19 -04:00
|
|
|
#if MATRIX_2D_4x4
|
|
|
|
/* essentially RotateAxis('Z')
|
|
|
|
* TODO: simpler math for 2D case
|
|
|
|
*/
|
|
|
|
rotate_m4(ModelView2D, 'Z', DEG2RADF(deg));
|
|
|
|
#else
|
2017-03-21 00:08:09 -04:00
|
|
|
BLI_assert(false); /* TODO: finish for MATRIX_MODE_2D */
|
2017-04-13 04:00:19 -04:00
|
|
|
#endif
|
2017-03-21 00:08:09 -04:00
|
|
|
}
|
|
|
|
|
2017-02-12 19:23:08 +01:00
|
|
|
void gpuRotate3f(float deg, float x, float y, float z)
|
|
|
|
{
|
|
|
|
const float axis[3] = {x, y, z};
|
|
|
|
gpuRotate3fv(deg, axis);
|
|
|
|
}
|
|
|
|
|
2016-09-25 19:29:45 +02:00
|
|
|
void gpuRotate3fv(float deg, const float axis[3])
|
2016-09-22 12:11:40 +02:00
|
|
|
{
|
2017-03-20 17:19:21 -04:00
|
|
|
#if SUPPORT_LEGACY_MATRIX
|
|
|
|
if (state.mode == MATRIX_MODE_INACTIVE) {
|
|
|
|
glRotatef(deg, axis[0], axis[1], axis[2]);
|
2017-03-21 00:25:47 -04:00
|
|
|
state.dirty = true;
|
2017-03-20 17:19:21 -04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2016-09-25 19:29:45 +02:00
|
|
|
Mat4 m;
|
|
|
|
axis_angle_to_mat4(m, axis, DEG2RADF(deg));
|
|
|
|
gpuMultMatrix3D(m);
|
2016-09-22 12:11:40 +02:00
|
|
|
}
|
|
|
|
|
2016-09-25 19:29:45 +02:00
|
|
|
void gpuRotateAxis(float deg, char axis)
|
2016-09-22 12:11:40 +02:00
|
|
|
{
|
2017-03-20 17:19:21 -04:00
|
|
|
#if SUPPORT_LEGACY_MATRIX
|
|
|
|
if (state.mode == MATRIX_MODE_INACTIVE) {
|
|
|
|
float a[3] = { 0.0f };
|
|
|
|
switch (axis) {
|
|
|
|
case 'X': a[0] = 1.0f; break;
|
|
|
|
case 'Y': a[1] = 1.0f; break;
|
|
|
|
case 'Z': a[2] = 1.0f; break;
|
|
|
|
default: BLI_assert(false); /* bad axis */
|
|
|
|
}
|
|
|
|
glRotatef(deg, a[0], a[1], a[2]);
|
2017-03-21 00:25:47 -04:00
|
|
|
state.dirty = true;
|
2017-03-20 17:19:21 -04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2016-09-25 19:29:45 +02:00
|
|
|
BLI_assert(state.mode == MATRIX_MODE_3D);
|
2017-04-13 04:00:19 -04:00
|
|
|
/* rotate_m4 works in place */
|
2016-09-25 19:29:45 +02:00
|
|
|
rotate_m4(ModelView3D, axis, DEG2RADF(deg));
|
|
|
|
CHECKMAT(ModelView3D);
|
2016-10-20 14:17:54 -04:00
|
|
|
state.dirty = true;
|
2016-09-25 19:29:45 +02:00
|
|
|
}
|
2016-09-22 12:11:40 +02:00
|
|
|
|
2016-09-25 19:29:45 +02:00
|
|
|
static void mat4_ortho_set(float m[4][4], float left, float right, float bottom, float top, float near, float far)
|
|
|
|
{
|
|
|
|
m[0][0] = 2.0f / (right - left);
|
|
|
|
m[1][0] = 0.0f;
|
|
|
|
m[2][0] = 0.0f;
|
|
|
|
m[3][0] = -(right + left) / (right - left);
|
|
|
|
|
|
|
|
m[0][1] = 0.0f;
|
|
|
|
m[1][1] = 2.0f / (top - bottom);
|
|
|
|
m[2][1] = 0.0f;
|
|
|
|
m[3][1] = -(top + bottom) / (top - bottom);
|
|
|
|
|
|
|
|
m[0][2] = 0.0f;
|
|
|
|
m[1][2] = 0.0f;
|
|
|
|
m[2][2] = -2.0f / (far - near);
|
|
|
|
m[3][2] = -(far + near) / (far - near);
|
|
|
|
|
|
|
|
m[0][3] = 0.0f;
|
|
|
|
m[1][3] = 0.0f;
|
|
|
|
m[2][3] = 0.0f;
|
|
|
|
m[3][3] = 1.0f;
|
2016-10-20 14:17:54 -04:00
|
|
|
|
|
|
|
state.dirty = true;
|
2016-09-25 19:29:45 +02:00
|
|
|
}
|
2016-09-22 12:11:40 +02:00
|
|
|
|
2017-03-26 21:12:39 -04:00
|
|
|
static void mat4_frustum_set(float m[4][4], float left, float right, float bottom, float top, float near, float far)
|
2016-09-25 19:29:45 +02:00
|
|
|
{
|
|
|
|
m[0][0] = 2.0f * near / (right - left);
|
|
|
|
m[1][0] = 0.0f;
|
|
|
|
m[2][0] = (right + left) / (right - left);
|
|
|
|
m[3][0] = 0.0f;
|
|
|
|
|
|
|
|
m[0][1] = 0.0f;
|
|
|
|
m[1][1] = 2.0f * near / (top - bottom);
|
|
|
|
m[2][1] = (top + bottom) / (top - bottom);
|
|
|
|
m[3][1] = 0.0f;
|
|
|
|
|
|
|
|
m[0][2] = 0.0f;
|
|
|
|
m[1][2] = 0.0f;
|
|
|
|
m[2][2] = -(far + near) / (far - near);
|
|
|
|
m[3][2] = -2.0f * far * near / (far - near);
|
|
|
|
|
|
|
|
m[0][3] = 0.0f;
|
|
|
|
m[1][3] = 0.0f;
|
|
|
|
m[2][3] = -1.0f;
|
|
|
|
m[3][3] = 0.0f;
|
2016-10-20 14:17:54 -04:00
|
|
|
|
|
|
|
state.dirty = true;
|
2016-09-22 12:11:40 +02:00
|
|
|
}
|
|
|
|
|
2016-09-25 19:29:45 +02:00
|
|
|
static void mat4_look_from_origin(float m[4][4], float lookdir[3], float camup[3])
|
2016-09-22 12:11:40 +02:00
|
|
|
{
|
2016-09-25 19:29:45 +02:00
|
|
|
/* This function is loosely based on Mesa implementation.
|
|
|
|
*
|
|
|
|
* SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
|
|
|
|
* Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
|
|
|
|
*
|
|
|
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
|
|
* copy of this software and associated documentation files (the "Software"),
|
|
|
|
* to deal in the Software without restriction, including without limitation
|
|
|
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
|
|
* and/or sell copies of the Software, and to permit persons to whom the
|
|
|
|
* Software is furnished to do so, subject to the following conditions:
|
|
|
|
*
|
|
|
|
* The above copyright notice including the dates of first publication and
|
|
|
|
* either this permission notice or a reference to
|
|
|
|
* http://oss.sgi.com/projects/FreeB/
|
|
|
|
* shall be included in all copies or substantial portions of the Software.
|
|
|
|
*
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
|
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
|
|
* SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
|
|
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
|
|
|
|
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
|
|
* SOFTWARE.
|
|
|
|
*
|
|
|
|
* Except as contained in this notice, the name of Silicon Graphics, Inc.
|
|
|
|
* shall not be used in advertising or otherwise to promote the sale, use or
|
|
|
|
* other dealings in this Software without prior written authorization from
|
|
|
|
* Silicon Graphics, Inc.
|
|
|
|
*/
|
2016-09-22 12:11:40 +02:00
|
|
|
|
2016-09-25 19:29:45 +02:00
|
|
|
float side[3];
|
2016-09-22 12:11:40 +02:00
|
|
|
|
2016-09-25 19:29:45 +02:00
|
|
|
normalize_v3(lookdir);
|
2016-09-22 12:11:40 +02:00
|
|
|
|
2016-09-25 19:29:45 +02:00
|
|
|
cross_v3_v3v3(side, lookdir, camup);
|
2016-09-22 12:11:40 +02:00
|
|
|
|
2016-09-25 19:29:45 +02:00
|
|
|
normalize_v3(side);
|
2016-09-22 12:11:40 +02:00
|
|
|
|
2016-09-25 19:29:45 +02:00
|
|
|
cross_v3_v3v3(camup, side, lookdir);
|
2016-09-22 12:11:40 +02:00
|
|
|
|
2016-09-25 19:29:45 +02:00
|
|
|
m[0][0] = side[0];
|
|
|
|
m[1][0] = side[1];
|
|
|
|
m[2][0] = side[2];
|
|
|
|
m[3][0] = 0.0f;
|
2016-09-22 12:11:40 +02:00
|
|
|
|
2016-09-25 19:29:45 +02:00
|
|
|
m[0][1] = camup[0];
|
|
|
|
m[1][1] = camup[1];
|
|
|
|
m[2][1] = camup[2];
|
|
|
|
m[3][1] = 0.0f;
|
2016-09-22 12:11:40 +02:00
|
|
|
|
2016-09-25 19:29:45 +02:00
|
|
|
m[0][2] = -lookdir[0];
|
|
|
|
m[1][2] = -lookdir[1];
|
|
|
|
m[2][2] = -lookdir[2];
|
|
|
|
m[3][2] = 0.0f;
|
2016-09-22 12:11:40 +02:00
|
|
|
|
2016-09-25 19:29:45 +02:00
|
|
|
m[0][3] = 0.0f;
|
|
|
|
m[1][3] = 0.0f;
|
|
|
|
m[2][3] = 0.0f;
|
|
|
|
m[3][3] = 1.0f;
|
2016-10-20 14:17:54 -04:00
|
|
|
|
|
|
|
state.dirty = true;
|
2016-09-22 12:11:40 +02:00
|
|
|
}
|
|
|
|
|
2016-09-25 19:29:45 +02:00
|
|
|
void gpuOrtho(float left, float right, float bottom, float top, float near, float far)
|
2016-09-22 12:11:40 +02:00
|
|
|
{
|
2017-03-22 15:52:48 -04:00
|
|
|
#if SUPPORT_LEGACY_MATRIX
|
|
|
|
if (state.mode == MATRIX_MODE_INACTIVE) {
|
|
|
|
GLenum mode;
|
|
|
|
glGetIntegerv(GL_MATRIX_MODE, (GLint*)&mode);
|
|
|
|
if (mode != GL_PROJECTION) {
|
|
|
|
glMatrixMode(GL_PROJECTION);
|
|
|
|
}
|
|
|
|
|
|
|
|
glLoadIdentity();
|
|
|
|
glOrtho(left, right, bottom, top, near, far);
|
|
|
|
|
|
|
|
if (mode != GL_PROJECTION_MATRIX) {
|
|
|
|
glMatrixMode(mode); /* restore */
|
|
|
|
}
|
|
|
|
|
|
|
|
state.dirty = true;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2016-09-25 19:29:45 +02:00
|
|
|
BLI_assert(state.mode == MATRIX_MODE_3D);
|
|
|
|
mat4_ortho_set(Projection3D, left, right, bottom, top, near, far);
|
|
|
|
CHECKMAT(Projection3D);
|
2016-10-20 14:17:54 -04:00
|
|
|
state.dirty = true;
|
2016-09-22 12:11:40 +02:00
|
|
|
}
|
|
|
|
|
2016-09-25 19:29:45 +02:00
|
|
|
void gpuOrtho2D(float left, float right, float bottom, float top)
|
2016-09-22 12:11:40 +02:00
|
|
|
{
|
2017-03-22 15:52:48 -04:00
|
|
|
#if SUPPORT_LEGACY_MATRIX
|
|
|
|
if (state.mode == MATRIX_MODE_INACTIVE) {
|
|
|
|
GLenum mode;
|
|
|
|
glGetIntegerv(GL_MATRIX_MODE, (GLint*)&mode);
|
|
|
|
if (mode != GL_PROJECTION) {
|
|
|
|
glMatrixMode(GL_PROJECTION);
|
|
|
|
}
|
|
|
|
|
|
|
|
glLoadIdentity();
|
|
|
|
glOrtho(left, right, bottom, top, -1.0f, 1.0f);
|
|
|
|
|
|
|
|
if (mode != GL_PROJECTION_MATRIX) {
|
|
|
|
glMatrixMode(mode); /* restore */
|
|
|
|
}
|
|
|
|
|
|
|
|
state.dirty = true;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2016-09-25 19:29:45 +02:00
|
|
|
BLI_assert(state.mode == MATRIX_MODE_2D);
|
2017-04-13 04:00:19 -04:00
|
|
|
#if MATRIX_2D_4x4
|
2016-09-25 19:29:45 +02:00
|
|
|
Mat4 m;
|
|
|
|
mat4_ortho_set(m, left, right, bottom, top, -1.0f, 1.0f);
|
2017-04-13 04:00:19 -04:00
|
|
|
#else
|
|
|
|
/* TODO: correct 3x3 implementation */
|
|
|
|
#endif
|
2016-09-25 19:29:45 +02:00
|
|
|
CHECKMAT(Projection2D);
|
2016-10-20 14:17:54 -04:00
|
|
|
state.dirty = true;
|
2016-09-22 12:11:40 +02:00
|
|
|
}
|
|
|
|
|
2016-09-25 19:29:45 +02:00
|
|
|
void gpuFrustum(float left, float right, float bottom, float top, float near, float far)
|
2016-09-22 12:11:40 +02:00
|
|
|
{
|
2017-03-22 15:52:48 -04:00
|
|
|
#if SUPPORT_LEGACY_MATRIX
|
|
|
|
if (state.mode == MATRIX_MODE_INACTIVE) {
|
|
|
|
GLenum mode;
|
|
|
|
glGetIntegerv(GL_MATRIX_MODE, (GLint*)&mode);
|
|
|
|
if (mode != GL_PROJECTION) {
|
|
|
|
glMatrixMode(GL_PROJECTION);
|
|
|
|
}
|
|
|
|
|
|
|
|
glLoadIdentity();
|
|
|
|
glFrustum(left, right, bottom, top, near, far);
|
|
|
|
|
|
|
|
if (mode != GL_PROJECTION_MATRIX) {
|
|
|
|
glMatrixMode(mode); /* restore */
|
|
|
|
}
|
|
|
|
|
|
|
|
state.dirty = true;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2016-09-25 19:29:45 +02:00
|
|
|
BLI_assert(state.mode == MATRIX_MODE_3D);
|
|
|
|
mat4_frustum_set(Projection3D, left, right, bottom, top, near, far);
|
|
|
|
CHECKMAT(Projection3D);
|
2016-10-20 14:17:54 -04:00
|
|
|
state.dirty = true;
|
2016-09-25 19:29:45 +02:00
|
|
|
}
|
2016-09-22 12:11:40 +02:00
|
|
|
|
2016-09-25 19:29:45 +02:00
|
|
|
void gpuPerspective(float fovy, float aspect, float near, float far)
|
|
|
|
{
|
|
|
|
float half_height = tanf(fovy * (float)(M_PI / 360.0)) * near;
|
|
|
|
float half_width = half_height * aspect;
|
|
|
|
gpuFrustum(-half_width, +half_width, -half_height, +half_height, near, far);
|
2016-09-22 12:11:40 +02:00
|
|
|
}
|
|
|
|
|
2016-09-25 19:29:45 +02:00
|
|
|
void gpuLookAt(float eyeX, float eyeY, float eyeZ, float centerX, float centerY, float centerZ, float upX, float upY, float upZ)
|
2016-09-22 12:11:40 +02:00
|
|
|
{
|
2016-09-25 19:29:45 +02:00
|
|
|
Mat4 cm;
|
|
|
|
float lookdir[3];
|
|
|
|
float camup[3] = {upX, upY, upZ};
|
2016-09-22 12:11:40 +02:00
|
|
|
|
|
|
|
lookdir[0] = centerX - eyeX;
|
|
|
|
lookdir[1] = centerY - eyeY;
|
|
|
|
lookdir[2] = centerZ - eyeZ;
|
|
|
|
|
|
|
|
mat4_look_from_origin(cm, lookdir, camup);
|
|
|
|
|
2016-09-25 19:29:45 +02:00
|
|
|
gpuMultMatrix3D(cm);
|
|
|
|
gpuTranslate3f(-eyeX, -eyeY, -eyeZ);
|
2016-09-22 12:11:40 +02:00
|
|
|
}
|
|
|
|
|
2017-02-25 21:58:23 +01:00
|
|
|
void gpuProject(const float world[3], const float model[4][4], const float proj[4][4], const int view[4], float win[3])
|
2016-09-22 12:11:40 +02:00
|
|
|
{
|
|
|
|
float v[4];
|
|
|
|
|
2017-02-25 21:58:23 +01:00
|
|
|
mul_v4_m4v3(v, model, world);
|
2016-09-25 19:29:45 +02:00
|
|
|
mul_m4_v4(proj, v);
|
2016-09-22 12:11:40 +02:00
|
|
|
|
2017-02-25 21:58:23 +01:00
|
|
|
if (v[3] != 0.0f) {
|
|
|
|
mul_v3_fl(v, 1.0f / v[3]);
|
|
|
|
}
|
|
|
|
|
2016-09-22 12:11:40 +02:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2017-02-25 21:58:23 +01:00
|
|
|
bool gpuUnProject(const float win[3], const float model[4][4], const float proj[4][4], const int view[4], float world[3])
|
2016-09-22 12:11:40 +02:00
|
|
|
{
|
2016-09-25 19:29:45 +02:00
|
|
|
float pm[4][4];
|
|
|
|
float in[4];
|
|
|
|
float out[4];
|
2016-09-22 12:11:40 +02:00
|
|
|
|
2016-09-25 19:29:45 +02:00
|
|
|
mul_m4_m4m4(pm, proj, model);
|
2016-09-22 12:11:40 +02:00
|
|
|
|
|
|
|
if (!invert_m4(pm)) {
|
2017-02-25 21:58:23 +01:00
|
|
|
zero_v3(world);
|
2016-09-25 19:29:45 +02:00
|
|
|
return false;
|
2016-09-22 12:11:40 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
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];
|
|
|
|
|
2016-09-25 19:29:45 +02:00
|
|
|
/* Map to range -1 to +1 */
|
2016-09-22 12:11:40 +02:00
|
|
|
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) {
|
2017-02-25 21:58:23 +01:00
|
|
|
copy_v3_v3(world, out);
|
2016-09-25 19:29:45 +02:00
|
|
|
return false;
|
2016-09-22 12:11:40 +02:00
|
|
|
}
|
|
|
|
|
2017-02-25 21:58:23 +01:00
|
|
|
mul_v3_v3fl(world, out, 1.0f / out[3]);
|
|
|
|
return true;
|
2016-09-22 12:11:40 +02:00
|
|
|
}
|
2016-10-09 23:03:35 -04:00
|
|
|
|
|
|
|
const float *gpuGetModelViewMatrix3D(float m[4][4])
|
|
|
|
{
|
|
|
|
#if SUPPORT_LEGACY_MATRIX
|
|
|
|
if (state.mode == MATRIX_MODE_INACTIVE) {
|
|
|
|
if (m == NULL) {
|
|
|
|
static Mat4 temp;
|
|
|
|
m = temp;
|
|
|
|
}
|
|
|
|
|
|
|
|
glGetFloatv(GL_MODELVIEW_MATRIX, (float*)m);
|
|
|
|
return (const float*)m;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
BLI_assert(state.mode == MATRIX_MODE_3D);
|
|
|
|
|
|
|
|
if (m) {
|
|
|
|
copy_m4_m4(m, ModelView3D);
|
|
|
|
return (const float*)m;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return (const float*)ModelView3D;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const float *gpuGetProjectionMatrix3D(float m[4][4])
|
|
|
|
{
|
|
|
|
#if SUPPORT_LEGACY_MATRIX
|
|
|
|
if (state.mode == MATRIX_MODE_INACTIVE) {
|
|
|
|
if (m == NULL) {
|
|
|
|
static Mat4 temp;
|
|
|
|
m = temp;
|
|
|
|
}
|
|
|
|
|
|
|
|
glGetFloatv(GL_PROJECTION_MATRIX, (float*)m);
|
|
|
|
return (const float*)m;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
BLI_assert(state.mode == MATRIX_MODE_3D);
|
|
|
|
|
|
|
|
if (m) {
|
2017-03-26 21:12:39 -04:00
|
|
|
copy_m4_m4(m, Projection3D);
|
2016-10-09 23:03:35 -04:00
|
|
|
return (const float*)m;
|
|
|
|
}
|
|
|
|
else {
|
2017-03-26 21:12:39 -04:00
|
|
|
return (const float*)Projection3D;
|
2016-10-09 23:03:35 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const float *gpuGetModelViewProjectionMatrix3D(float m[4][4])
|
|
|
|
{
|
2017-02-18 19:53:55 -05:00
|
|
|
if (m == NULL) {
|
|
|
|
static Mat4 temp;
|
|
|
|
m = temp;
|
|
|
|
}
|
|
|
|
|
2016-10-09 23:03:35 -04:00
|
|
|
#if SUPPORT_LEGACY_MATRIX
|
|
|
|
if (state.mode == MATRIX_MODE_INACTIVE) {
|
|
|
|
Mat4 proj;
|
2017-02-18 19:53:55 -05:00
|
|
|
glGetFloatv(GL_MODELVIEW_MATRIX, (float*)m);
|
|
|
|
glGetFloatv(GL_PROJECTION_MATRIX, (float*)proj);
|
|
|
|
mul_m4_m4_pre(m, proj);
|
2016-10-09 23:03:35 -04:00
|
|
|
return (const float*)m;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
BLI_assert(state.mode == MATRIX_MODE_3D);
|
|
|
|
|
2016-10-11 21:13:13 -04:00
|
|
|
mul_m4_m4m4(m, Projection3D, ModelView3D);
|
2016-10-09 23:03:35 -04:00
|
|
|
return (const float*)m;
|
|
|
|
}
|
|
|
|
|
2016-10-23 23:37:53 -04:00
|
|
|
const float *gpuGetNormalMatrix(float m[3][3])
|
|
|
|
{
|
|
|
|
if (m == NULL) {
|
|
|
|
static Mat3 temp3;
|
|
|
|
m = temp3;
|
|
|
|
}
|
|
|
|
|
2017-02-09 02:28:55 +11:00
|
|
|
copy_m3_m4(m, (const float (*)[4])gpuGetModelViewMatrix3D(NULL));
|
2016-10-23 23:37:53 -04:00
|
|
|
|
|
|
|
invert_m3(m);
|
|
|
|
transpose_m3(m);
|
|
|
|
|
|
|
|
return (const float*)m;
|
|
|
|
}
|
|
|
|
|
|
|
|
const float *gpuGetNormalMatrixInverse(float m[3][3])
|
|
|
|
{
|
|
|
|
if (m == NULL) {
|
|
|
|
static Mat3 temp3;
|
|
|
|
m = temp3;
|
|
|
|
}
|
|
|
|
|
|
|
|
gpuGetNormalMatrix(m);
|
|
|
|
invert_m3(m);
|
|
|
|
|
|
|
|
return (const float*)m;
|
|
|
|
}
|
|
|
|
|
2017-04-13 04:00:19 -04:00
|
|
|
#if MATRIX_2D_4x4
|
|
|
|
static const float *gpuGetModelViewMatrix2D(float m[4][4])
|
|
|
|
{
|
|
|
|
BLI_assert(state.mode == MATRIX_MODE_2D);
|
|
|
|
|
|
|
|
if (m) {
|
|
|
|
copy_m4_m4(m, ModelView2D);
|
|
|
|
return (const float*)m;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return (const float*)ModelView2D;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static const float *gpuGetProjectionMatrix2D(float m[4][4])
|
|
|
|
{
|
|
|
|
BLI_assert(state.mode == MATRIX_MODE_2D);
|
|
|
|
|
|
|
|
if (m) {
|
|
|
|
copy_m4_m4(m, Projection2D);
|
|
|
|
return (const float*)m;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return (const float*)Projection2D;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static const float *gpuGetModelViewProjectionMatrix2D(float m[4][4])
|
|
|
|
{
|
|
|
|
BLI_assert(state.mode == MATRIX_MODE_2D);
|
|
|
|
|
|
|
|
if (m == NULL) {
|
|
|
|
static Mat4 temp;
|
|
|
|
m = temp;
|
|
|
|
}
|
|
|
|
|
|
|
|
mul_m4_m4m4(m, Projection2D, ModelView2D);
|
|
|
|
return (const float*)m;
|
|
|
|
}
|
|
|
|
#else /* not MATRIX_2D_4x4 */
|
|
|
|
/* TODO: implement 3x3 getters */
|
|
|
|
#endif
|
|
|
|
|
2017-04-12 18:55:32 -04:00
|
|
|
void gpuBindMatrices(const ShaderInterface* shaderface)
|
2016-10-09 23:03:35 -04:00
|
|
|
{
|
2017-04-12 18:55:32 -04:00
|
|
|
/* set uniform values to matrix stack values
|
|
|
|
* call this before a draw call if desired matrices are dirty
|
|
|
|
* call glUseProgram before this, as glUniform expects program to be bound
|
2016-10-09 23:03:35 -04:00
|
|
|
*/
|
|
|
|
|
2017-04-12 18:55:32 -04:00
|
|
|
const ShaderInput *MV = ShaderInterface_builtin_uniform(shaderface, UNIFORM_MODELVIEW_3D);
|
|
|
|
const ShaderInput *P = ShaderInterface_builtin_uniform(shaderface, UNIFORM_PROJECTION_3D);
|
|
|
|
const ShaderInput *MVP = ShaderInterface_builtin_uniform(shaderface, UNIFORM_MVP_3D);
|
2017-04-13 04:00:19 -04:00
|
|
|
/* TODO: teach ShaderInterface to distinguish 2D from 3D --^ */
|
2016-10-09 23:03:35 -04:00
|
|
|
|
2017-04-13 04:00:19 -04:00
|
|
|
if (state.mode == MATRIX_MODE_2D) {
|
|
|
|
if (MV) {
|
|
|
|
#if DEBUG_MATRIX_BIND
|
|
|
|
puts("setting 2D MV matrix");
|
|
|
|
#endif
|
2016-10-11 14:44:12 -04:00
|
|
|
|
2017-04-13 04:00:19 -04:00
|
|
|
glUniformMatrix4fv(MV->location, 1, GL_FALSE, gpuGetModelViewMatrix2D(NULL));
|
|
|
|
}
|
2016-10-09 23:03:35 -04:00
|
|
|
|
2017-04-13 04:00:19 -04:00
|
|
|
if (P) {
|
|
|
|
#if DEBUG_MATRIX_BIND
|
|
|
|
puts("setting 2D P matrix");
|
|
|
|
#endif
|
2016-10-11 14:44:12 -04:00
|
|
|
|
2017-04-13 04:00:19 -04:00
|
|
|
glUniformMatrix4fv(P->location, 1, GL_FALSE, gpuGetProjectionMatrix2D(NULL));
|
|
|
|
}
|
2016-10-09 23:03:35 -04:00
|
|
|
|
2017-04-13 04:00:19 -04:00
|
|
|
if (MVP) {
|
|
|
|
#if DEBUG_MATRIX_BIND
|
|
|
|
puts("setting 2D MVP matrix");
|
|
|
|
#endif
|
2016-10-11 14:44:12 -04:00
|
|
|
|
2017-04-13 04:00:19 -04:00
|
|
|
glUniformMatrix4fv(MVP->location, 1, GL_FALSE, gpuGetModelViewProjectionMatrix2D(NULL));
|
|
|
|
}
|
2016-10-09 23:03:35 -04:00
|
|
|
}
|
2017-04-13 04:00:19 -04:00
|
|
|
else {
|
|
|
|
const ShaderInput *N = ShaderInterface_builtin_uniform(shaderface, UNIFORM_NORMAL_3D);
|
|
|
|
const ShaderInput *MV_inv = ShaderInterface_builtin_uniform(shaderface, UNIFORM_MODELVIEW_INV_3D);
|
|
|
|
const ShaderInput *P_inv = ShaderInterface_builtin_uniform(shaderface, UNIFORM_PROJECTION_INV_3D);
|
2016-10-20 14:17:54 -04:00
|
|
|
|
2017-04-13 04:00:19 -04:00
|
|
|
if (MV) {
|
|
|
|
#if DEBUG_MATRIX_BIND
|
|
|
|
puts("setting 3D MV matrix");
|
|
|
|
#endif
|
2016-10-23 23:37:53 -04:00
|
|
|
|
2017-04-13 04:00:19 -04:00
|
|
|
glUniformMatrix4fv(MV->location, 1, GL_FALSE, gpuGetModelViewMatrix3D(NULL));
|
|
|
|
}
|
2016-10-23 23:37:53 -04:00
|
|
|
|
2017-04-13 04:00:19 -04:00
|
|
|
if (P) {
|
|
|
|
#if DEBUG_MATRIX_BIND
|
|
|
|
puts("setting 3D P matrix");
|
|
|
|
#endif
|
2017-03-26 21:12:39 -04:00
|
|
|
|
2017-04-13 04:00:19 -04:00
|
|
|
glUniformMatrix4fv(P->location, 1, GL_FALSE, gpuGetProjectionMatrix3D(NULL));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (MVP) {
|
|
|
|
#if DEBUG_MATRIX_BIND
|
|
|
|
puts("setting 3D MVP matrix");
|
|
|
|
#endif
|
|
|
|
|
|
|
|
glUniformMatrix4fv(MVP->location, 1, GL_FALSE, gpuGetModelViewProjectionMatrix3D(NULL));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (N) {
|
|
|
|
#if DEBUG_MATRIX_BIND
|
|
|
|
puts("setting 3D normal matrix");
|
|
|
|
#endif
|
|
|
|
|
|
|
|
glUniformMatrix3fv(N->location, 1, GL_FALSE, gpuGetNormalMatrix(NULL));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (MV_inv) {
|
|
|
|
Mat4 m;
|
|
|
|
gpuGetModelViewMatrix3D(m);
|
|
|
|
invert_m4(m);
|
|
|
|
glUniformMatrix4fv(MV_inv->location, 1, GL_FALSE, (const float*) m);
|
|
|
|
}
|
2017-03-26 21:12:39 -04:00
|
|
|
|
2017-04-13 04:00:19 -04:00
|
|
|
if (P_inv) {
|
|
|
|
Mat4 m;
|
|
|
|
gpuGetProjectionMatrix3D(m);
|
|
|
|
invert_m4(m);
|
|
|
|
glUniformMatrix4fv(P_inv->location, 1, GL_FALSE, (const float*) m);
|
|
|
|
}
|
2017-03-26 21:12:39 -04:00
|
|
|
}
|
|
|
|
|
2016-10-20 14:17:54 -04:00
|
|
|
state.dirty = false;
|
|
|
|
}
|
|
|
|
|
2017-02-09 02:28:55 +11:00
|
|
|
bool gpuMatricesDirty(void)
|
2016-10-20 14:17:54 -04:00
|
|
|
{
|
|
|
|
return state.dirty;
|
2016-10-09 23:03:35 -04:00
|
|
|
}
|