Changeset View
Changeset View
Standalone View
Standalone View
source/blender/gpu/intern/gpu_matrix.c
| Show All 38 Lines | |||||
| #define DEBUG_MATRIX_BIND 0 | #define DEBUG_MATRIX_BIND 0 | ||||
| #define MATRIX_STACK_DEPTH 32 | #define MATRIX_STACK_DEPTH 32 | ||||
| typedef float Mat4[4][4]; | typedef float Mat4[4][4]; | ||||
| typedef float Mat3[3][3]; | typedef float Mat3[3][3]; | ||||
| #define ModelView2DS | |||||
| typedef struct { | typedef struct { | ||||
| Mat4 ModelViewStack3D[MATRIX_STACK_DEPTH]; | Mat4 ModelViewStack3D[MATRIX_STACK_DEPTH]; | ||||
| Mat4 ProjectionMatrix3D; | Mat4 ProjectionMatrix3D; | ||||
| #if MATRIX_2D_4x4 | |||||
| Mat4 ModelViewStack2D[MATRIX_STACK_DEPTH]; | |||||
| Mat4 ProjectionMatrix2D; | |||||
| #else | |||||
| Mat3 ModelViewStack2D[MATRIX_STACK_DEPTH]; | |||||
| Mat3 ProjectionMatrix2D; | |||||
| #endif | |||||
| MatrixMode mode; | |||||
| unsigned top; /* of current stack (would have to replicate if gpuResume2D/3D are implemented) */ | unsigned top; /* of current stack (would have to replicate if gpuResume2D/3D are implemented) */ | ||||
| bool dirty; | bool dirty; | ||||
| /* TODO: cache of derived matrices (Normal, MVP, inverse MVP, etc) | /* TODO: cache of derived matrices (Normal, MVP, inverse MVP, etc) | ||||
| * generate as needed for shaders, invalidate when original matrices change | * generate as needed for shaders, invalidate when original matrices change | ||||
| * | * | ||||
| * TODO: separate Model from View transform? Batches/objects have model, | * TODO: separate Model from View transform? Batches/objects have model, | ||||
| * camera/eye has view & projection | * camera/eye has view & projection | ||||
| */ | */ | ||||
| } MatrixState; | } MatrixState; | ||||
| static MatrixState state; /* TODO(merwin): make part of GPUContext, alongside immediate mode & state tracker */ | static MatrixState state; /* TODO(merwin): make part of GPUContext, alongside immediate mode & state tracker */ | ||||
| #define MATRIX_4X4_IDENTITY {{1.0f, 0.0f, 0.0f, 0.0f}, \ | |||||
| {0.0f, 1.0f, 0.0f, 0.0f}, \ | |||||
| {0.0f, 0.0f, 1.0f, 0.0f}, \ | |||||
| {0.0f, 0.0f, 0.0f, 1.0f}} | |||||
| /* TODO(merwin): make part of GPUContext, alongside immediate mode & state tracker */ | |||||
| static MatrixState state = { | |||||
| .ModelViewStack3D = {MATRIX_4X4_IDENTITY}, | |||||
| .ProjectionMatrix3D = MATRIX_4X4_IDENTITY, | |||||
| }; | |||||
| #undef MATRIX_4X4_IDENTITY | |||||
| #define ModelView3D state.ModelViewStack3D[state.top] | #define ModelView3D state.ModelViewStack3D[state.top] | ||||
| #define ModelView2D state.ModelViewStack2D[state.top] | |||||
| #define Projection3D state.ProjectionMatrix3D | #define Projection3D state.ProjectionMatrix3D | ||||
| #define Projection2D state.ProjectionMatrix2D | |||||
| void gpuMatrixInit(void) | void gpuMatrixInit(void) | ||||
| { | { | ||||
| memset(&state, 0, sizeof(MatrixState)); | memset(&state, 0, sizeof(MatrixState)); | ||||
| } | } | ||||
| void gpuMatrixBegin2D(void) | |||||
| { | |||||
| state.mode = MATRIX_MODE_2D; | |||||
| state.top = 0; | |||||
| #if MATRIX_2D_4x4 | |||||
| unit_m4(ModelView2D); | |||||
| unit_m4(Projection2D); | |||||
| #else | |||||
| unit_m3(ModelView2D); | |||||
| unit_m3(Projection2D); | |||||
| #endif | |||||
| } | |||||
| void gpuMatrixBegin3D(void) | |||||
| { | |||||
| state.mode = MATRIX_MODE_3D; | |||||
| state.top = 0; | |||||
| unit_m4(ModelView3D); | |||||
| unit_m4(Projection3D); | |||||
| } | |||||
| void gpuMatrixEnd(void) | |||||
| { | |||||
| state.mode = MATRIX_MODE_INACTIVE; | |||||
| } | |||||
| #ifdef WITH_GPU_SAFETY | #ifdef WITH_GPU_SAFETY | ||||
| /* Check if matrix is numerically good */ | /* Check if matrix is numerically good */ | ||||
| static void checkmat(cosnt float *m) | static void checkmat(cosnt float *m) | ||||
| { | { | ||||
| #if MATRIX_2D_4x4 | |||||
| const int n = 16; | const int n = 16; | ||||
| #else | |||||
| const int n = state.mode == MATRIX_MODE_3D ? 16 : 9; | |||||
| #endif | |||||
| for (int i = 0; i < n; i++) { | for (int i = 0; i < n; i++) { | ||||
| #if _MSC_VER | #if _MSC_VER | ||||
| BLI_assert(_finite(m[i])); | BLI_assert(_finite(m[i])); | ||||
| #else | #else | ||||
| BLI_assert(!isinf(m[i])); | BLI_assert(!isinf(m[i])); | ||||
| #endif | #endif | ||||
| } | } | ||||
| } | } | ||||
| #define CHECKMAT(m) checkmat((const float*)m) | #define CHECKMAT(m) checkmat((const float*)m) | ||||
| #else | #else | ||||
| #define CHECKMAT(m) | #define CHECKMAT(m) | ||||
| #endif | #endif | ||||
| void gpuPushMatrix(void) | void gpuPushMatrix(void) | ||||
| { | { | ||||
| #if SUPPORT_LEGACY_MATRIX | #if SUPPORT_LEGACY_MATRIX | ||||
| if (state.mode == MATRIX_MODE_INACTIVE) { | { | ||||
| glPushMatrix(); | glPushMatrix(); | ||||
| state.dirty = true; | state.dirty = true; | ||||
| return; | return; | ||||
| } | } | ||||
| #endif | #endif | ||||
| BLI_assert(state.mode != MATRIX_MODE_INACTIVE); | |||||
| BLI_assert(state.top < MATRIX_STACK_DEPTH); | BLI_assert(state.top < MATRIX_STACK_DEPTH); | ||||
| state.top++; | state.top++; | ||||
| if (state.mode == MATRIX_MODE_3D) | |||||
| copy_m4_m4(ModelView3D, state.ModelViewStack3D[state.top - 1]); | copy_m4_m4(ModelView3D, state.ModelViewStack3D[state.top - 1]); | ||||
| else | |||||
| #if MATRIX_2D_4x4 | |||||
| copy_m4_m4(ModelView2D, state.ModelViewStack2D[state.top - 1]); | |||||
| #else | |||||
| copy_m3_m3(ModelView2D, state.ModelViewStack2D[state.top - 1]); | |||||
| #endif | |||||
| } | } | ||||
| void gpuPopMatrix(void) | void gpuPopMatrix(void) | ||||
| { | { | ||||
| #if SUPPORT_LEGACY_MATRIX | #if SUPPORT_LEGACY_MATRIX | ||||
| if (state.mode == MATRIX_MODE_INACTIVE) { | { | ||||
| glPopMatrix(); | glPopMatrix(); | ||||
| state.dirty = true; | state.dirty = true; | ||||
| return; | return; | ||||
| } | } | ||||
| #endif | #endif | ||||
| BLI_assert(state.mode != MATRIX_MODE_INACTIVE); | |||||
| BLI_assert(state.top > 0); | BLI_assert(state.top > 0); | ||||
| state.top--; | state.top--; | ||||
| state.dirty = true; | state.dirty = true; | ||||
| } | } | ||||
| void gpuLoadMatrix3D(const float m[4][4]) | void gpuLoadMatrix3D(const float m[4][4]) | ||||
| { | { | ||||
| #if SUPPORT_LEGACY_MATRIX | #if SUPPORT_LEGACY_MATRIX | ||||
| if (state.mode == MATRIX_MODE_INACTIVE) { | { | ||||
| glLoadMatrixf((const float*) m); | glLoadMatrixf((const float*) m); | ||||
| state.dirty = true; | state.dirty = true; | ||||
| return; | return; | ||||
| } | } | ||||
| #endif | #endif | ||||
| BLI_assert(state.mode == MATRIX_MODE_3D); | |||||
| copy_m4_m4(ModelView3D, m); | copy_m4_m4(ModelView3D, m); | ||||
| CHECKMAT(ModelView3D); | CHECKMAT(ModelView3D); | ||||
| state.dirty = true; | state.dirty = true; | ||||
| } | } | ||||
| void gpuLoadProjectionMatrix3D(const float m[4][4]) | void gpuLoadProjectionMatrix3D(const float m[4][4]) | ||||
| { | { | ||||
| #if SUPPORT_LEGACY_MATRIX | #if SUPPORT_LEGACY_MATRIX | ||||
| if (state.mode == MATRIX_MODE_INACTIVE) { | { | ||||
| GLenum mode; | GLenum mode; | ||||
| glGetIntegerv(GL_MATRIX_MODE, (GLint*)&mode); | glGetIntegerv(GL_MATRIX_MODE, (GLint*)&mode); | ||||
| if (mode != GL_PROJECTION) { | if (mode != GL_PROJECTION) { | ||||
| glMatrixMode(GL_PROJECTION); | glMatrixMode(GL_PROJECTION); | ||||
| } | } | ||||
| glLoadMatrixf((const float*) m); | glLoadMatrixf((const float*) m); | ||||
| if (mode != GL_PROJECTION_MATRIX) { | if (mode != GL_PROJECTION_MATRIX) { | ||||
| glMatrixMode(mode); /* restore */ | glMatrixMode(mode); /* restore */ | ||||
| } | } | ||||
| state.dirty = true; | state.dirty = true; | ||||
| return; | return; | ||||
| } | } | ||||
| #endif | #endif | ||||
| BLI_assert(state.mode == MATRIX_MODE_3D); | |||||
| copy_m4_m4(Projection3D, m); | copy_m4_m4(Projection3D, m); | ||||
| CHECKMAT(Projection3D); | CHECKMAT(Projection3D); | ||||
| state.dirty = true; | state.dirty = true; | ||||
| } | } | ||||
| #if 0 /* unused at the moment */ | #if 0 /* unused at the moment */ | ||||
| void gpuLoadMatrix2D(const float m[3][3]) | void gpuLoadMatrix2D(const float m[3][3]) | ||||
| { | { | ||||
| BLI_assert(state.mode == MATRIX_MODE_2D); | |||||
| copy_m3_m3(ModelView2D, m); | copy_m3_m3(ModelView2D, m); | ||||
| CHECKMAT(ModelView2D); | CHECKMAT(ModelView2D); | ||||
| state.dirty = true; | state.dirty = true; | ||||
| } | } | ||||
| #endif | #endif | ||||
| void gpuLoadIdentity(void) | void gpuLoadIdentity(void) | ||||
| { | { | ||||
| switch (state.mode) { | |||||
| case MATRIX_MODE_3D: | |||||
| unit_m4(ModelView3D); | unit_m4(ModelView3D); | ||||
| break; | |||||
| case MATRIX_MODE_2D: | |||||
| #if MATRIX_2D_4x4 | |||||
| unit_m4(ModelView2D); | |||||
| #else | |||||
| unit_m3(ModelView2D); | |||||
| #endif | |||||
| break; | |||||
| #if SUPPORT_LEGACY_MATRIX | #if SUPPORT_LEGACY_MATRIX | ||||
| case MATRIX_MODE_INACTIVE: | |||||
| glLoadIdentity(); | glLoadIdentity(); | ||||
| break; | |||||
| #endif | #endif | ||||
| default: | |||||
| BLI_assert(false); | |||||
| } | |||||
| state.dirty = true; | state.dirty = true; | ||||
| } | } | ||||
| void gpuTranslate2f(float x, float y) | void gpuTranslate2f(float x, float y) | ||||
| { | { | ||||
| #if SUPPORT_LEGACY_MATRIX | #if SUPPORT_LEGACY_MATRIX | ||||
| if (state.mode == MATRIX_MODE_INACTIVE) { | { | ||||
| glTranslatef(x, y, 0.0f); | glTranslatef(x, y, 0.0f); | ||||
| state.dirty = true; | state.dirty = true; | ||||
| return; | return; | ||||
| } | } | ||||
| #endif | #endif | ||||
| #if MATRIX_2D_4x4 | |||||
| Mat4 m; | Mat4 m; | ||||
| unit_m4(m); | unit_m4(m); | ||||
| m[3][0] = x; | m[3][0] = x; | ||||
| m[3][1] = y; | m[3][1] = y; | ||||
| #else | |||||
| Mat3 m; | |||||
| unit_m3(m); | |||||
| m[2][0] = x; | |||||
| m[2][1] = y; | |||||
| #endif | |||||
| gpuMultMatrix2D(m); | gpuMultMatrix2D(m); | ||||
| } | } | ||||
| void gpuTranslate2fv(const float vec[2]) | void gpuTranslate2fv(const float vec[2]) | ||||
| { | { | ||||
| gpuTranslate2f(vec[0], vec[1]); | gpuTranslate2f(vec[0], vec[1]); | ||||
| } | } | ||||
| void gpuTranslate3f(float x, float y, float z) | void gpuTranslate3f(float x, float y, float z) | ||||
| { | { | ||||
| #if SUPPORT_LEGACY_MATRIX | #if SUPPORT_LEGACY_MATRIX | ||||
| if (state.mode == MATRIX_MODE_INACTIVE) { | { | ||||
| glTranslatef(x, y, z); | glTranslatef(x, y, z); | ||||
| state.dirty = true; | state.dirty = true; | ||||
| return; | return; | ||||
| } | } | ||||
| #endif | #endif | ||||
| BLI_assert(state.mode == MATRIX_MODE_3D); | |||||
| #if 1 | #if 1 | ||||
| translate_m4(ModelView3D, x, y, z); | translate_m4(ModelView3D, x, y, z); | ||||
| CHECKMAT(ModelView3D); | CHECKMAT(ModelView3D); | ||||
| #else /* above works well in early testing, below is generic version */ | #else /* above works well in early testing, below is generic version */ | ||||
| Mat4 m; | Mat4 m; | ||||
| unit_m4(m); | unit_m4(m); | ||||
| m[3][0] = x; | m[3][0] = x; | ||||
| m[3][1] = y; | m[3][1] = y; | ||||
| m[3][2] = z; | m[3][2] = z; | ||||
| gpuMultMatrix3D(m); | gpuMultMatrix3D(m); | ||||
| #endif | #endif | ||||
| state.dirty = true; | state.dirty = true; | ||||
| } | } | ||||
| void gpuTranslate3fv(const float vec[3]) | void gpuTranslate3fv(const float vec[3]) | ||||
| { | { | ||||
| gpuTranslate3f(vec[0], vec[1], vec[2]); | gpuTranslate3f(vec[0], vec[1], vec[2]); | ||||
| } | } | ||||
| void gpuScaleUniform(float factor) | void gpuScaleUniform(float factor) | ||||
| { | { | ||||
| switch (state.mode) { | |||||
| case MATRIX_MODE_3D: | |||||
| { | |||||
| Mat4 m; | Mat4 m; | ||||
| scale_m4_fl(m, factor); | scale_m4_fl(m, factor); | ||||
| gpuMultMatrix3D(m); | gpuMultMatrix3D(m); | ||||
| break; | |||||
| } | |||||
| case MATRIX_MODE_2D: | |||||
| { | |||||
| #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 | |||||
| Mat3 m = {{0.0f}}; | |||||
| m[0][0] = factor; | |||||
| m[1][1] = factor; | |||||
| m[2][2] = 1.0f; | |||||
| #endif | |||||
| gpuMultMatrix2D(m); | |||||
| break; | |||||
| } | |||||
| #if SUPPORT_LEGACY_MATRIX | #if SUPPORT_LEGACY_MATRIX | ||||
| case MATRIX_MODE_INACTIVE: | |||||
| glScalef(factor, factor, factor); /* always scale Z since we can't distinguish 2D from 3D */ | glScalef(factor, factor, factor); /* always scale Z since we can't distinguish 2D from 3D */ | ||||
| state.dirty = true; | state.dirty = true; | ||||
| break; | |||||
| #endif | #endif | ||||
| default: | |||||
| BLI_assert(false); | |||||
| } | |||||
| } | } | ||||
| void gpuScale2f(float x, float y) | void gpuScale2f(float x, float y) | ||||
| { | { | ||||
| #if SUPPORT_LEGACY_MATRIX | #if SUPPORT_LEGACY_MATRIX | ||||
| if (state.mode == MATRIX_MODE_INACTIVE) { | { | ||||
| glScalef(x, y, 1.0f); | glScalef(x, y, 1.0f); | ||||
| state.dirty = true; | state.dirty = true; | ||||
| return; | return; | ||||
| } | } | ||||
| #endif | #endif | ||||
| #if MATRIX_2D_4x4 | |||||
| Mat4 m = {{0.0f}}; | Mat4 m = {{0.0f}}; | ||||
| m[0][0] = x; | m[0][0] = x; | ||||
| m[1][1] = y; | m[1][1] = y; | ||||
| m[2][2] = 1.0f; | m[2][2] = 1.0f; | ||||
| m[3][3] = 1.0f; | m[3][3] = 1.0f; | ||||
| #else | |||||
| Mat3 m = {{0.0f}}; | |||||
| m[0][0] = x; | |||||
| m[1][1] = y; | |||||
| m[2][2] = 1.0f; | |||||
| #endif | |||||
| gpuMultMatrix2D(m); | gpuMultMatrix2D(m); | ||||
| } | } | ||||
| void gpuScale2fv(const float vec[2]) | void gpuScale2fv(const float vec[2]) | ||||
| { | { | ||||
| gpuScale2f(vec[0], vec[1]); | gpuScale2f(vec[0], vec[1]); | ||||
| } | } | ||||
| void gpuScale3f(float x, float y, float z) | void gpuScale3f(float x, float y, float z) | ||||
| { | { | ||||
| #if SUPPORT_LEGACY_MATRIX | #if SUPPORT_LEGACY_MATRIX | ||||
| if (state.mode == MATRIX_MODE_INACTIVE) { | { | ||||
| glScalef(x, y, z); | glScalef(x, y, z); | ||||
| state.dirty = true; | state.dirty = true; | ||||
| return; | return; | ||||
| } | } | ||||
| #endif | #endif | ||||
| Mat4 m = {{0.0f}}; | Mat4 m = {{0.0f}}; | ||||
| m[0][0] = x; | m[0][0] = x; | ||||
| m[1][1] = y; | m[1][1] = y; | ||||
| m[2][2] = z; | m[2][2] = z; | ||||
| m[3][3] = 1.0f; | m[3][3] = 1.0f; | ||||
| gpuMultMatrix3D(m); | gpuMultMatrix3D(m); | ||||
| } | } | ||||
| void gpuScale3fv(const float vec[3]) | void gpuScale3fv(const float vec[3]) | ||||
| { | { | ||||
| gpuScale3f(vec[0], vec[1], vec[2]); | gpuScale3f(vec[0], vec[1], vec[2]); | ||||
| } | } | ||||
| void gpuMultMatrix3D(const float m[4][4]) | void gpuMultMatrix3D(const float m[4][4]) | ||||
| { | { | ||||
| #if SUPPORT_LEGACY_MATRIX | #if SUPPORT_LEGACY_MATRIX | ||||
| if (state.mode == MATRIX_MODE_INACTIVE) { | { | ||||
| glMultMatrixf((const float*) m); | glMultMatrixf((const float*) m); | ||||
| state.dirty = true; | state.dirty = true; | ||||
| return; | return; | ||||
| } | } | ||||
| #endif | #endif | ||||
| BLI_assert(state.mode == MATRIX_MODE_3D); | |||||
| mul_m4_m4_post(ModelView3D, m); | mul_m4_m4_post(ModelView3D, m); | ||||
| CHECKMAT(ModelView3D); | CHECKMAT(ModelView3D); | ||||
| state.dirty = true; | state.dirty = true; | ||||
| } | } | ||||
| #if MATRIX_2D_4x4 | #if MATRIX_2D_4x4 | ||||
| void gpuMultMatrix2D(const float m[4][4]) | void gpuMultMatrix2D(const float m[4][4]) | ||||
| { | { | ||||
| BLI_assert(state.mode == MATRIX_MODE_2D); | mul_m4_m4_post(ModelView3D, m); | ||||
| mul_m4_m4_post(ModelView2D, m); | |||||
| CHECKMAT(ModelView2D); | CHECKMAT(ModelView2D); | ||||
| state.dirty = true; | state.dirty = true; | ||||
| } | } | ||||
| #else | #else | ||||
| void gpuMultMatrix2D(const float m[3][3]) | void gpuMultMatrix2D(const float m[3][3]) | ||||
| { | { | ||||
| BLI_assert(state.mode == MATRIX_MODE_2D); | |||||
| mul_m3_m3_post(ModelView2D, m); | mul_m3_m3_post(ModelView2D, m); | ||||
| CHECKMAT(ModelView2D); | CHECKMAT(ModelView2D); | ||||
| state.dirty = true; | state.dirty = true; | ||||
| } | } | ||||
| #endif | #endif | ||||
| void gpuRotate2D(float deg) | void gpuRotate2D(float deg) | ||||
| { | { | ||||
| #if SUPPORT_LEGACY_MATRIX | #if SUPPORT_LEGACY_MATRIX | ||||
| if (state.mode == MATRIX_MODE_INACTIVE) { | { | ||||
| glRotatef(deg, 0.0f, 0.0f, 1.0f); | glRotatef(deg, 0.0f, 0.0f, 1.0f); | ||||
| state.dirty = true; | state.dirty = true; | ||||
| return; | return; | ||||
| } | } | ||||
| #endif | #endif | ||||
| #if MATRIX_2D_4x4 | |||||
| /* essentially RotateAxis('Z') | /* essentially RotateAxis('Z') | ||||
| * TODO: simpler math for 2D case | * TODO: simpler math for 2D case | ||||
| */ | */ | ||||
| rotate_m4(ModelView2D, 'Z', DEG2RADF(deg)); | rotate_m4(ModelView3D, 'Z', DEG2RADF(deg)); | ||||
| #else | |||||
| BLI_assert(false); /* TODO: finish for MATRIX_MODE_2D */ | |||||
| #endif | |||||
| } | } | ||||
| void gpuRotate3f(float deg, float x, float y, float z) | void gpuRotate3f(float deg, float x, float y, float z) | ||||
| { | { | ||||
| const float axis[3] = {x, y, z}; | const float axis[3] = {x, y, z}; | ||||
| gpuRotate3fv(deg, axis); | gpuRotate3fv(deg, axis); | ||||
| } | } | ||||
| void gpuRotate3fv(float deg, const float axis[3]) | void gpuRotate3fv(float deg, const float axis[3]) | ||||
| { | { | ||||
| #if SUPPORT_LEGACY_MATRIX | #if SUPPORT_LEGACY_MATRIX | ||||
| if (state.mode == MATRIX_MODE_INACTIVE) { | { | ||||
| glRotatef(deg, axis[0], axis[1], axis[2]); | glRotatef(deg, axis[0], axis[1], axis[2]); | ||||
| state.dirty = true; | state.dirty = true; | ||||
| return; | return; | ||||
| } | } | ||||
| #endif | #endif | ||||
| Mat4 m; | Mat4 m; | ||||
| axis_angle_to_mat4(m, axis, DEG2RADF(deg)); | axis_angle_to_mat4(m, axis, DEG2RADF(deg)); | ||||
| gpuMultMatrix3D(m); | gpuMultMatrix3D(m); | ||||
| } | } | ||||
| void gpuRotateAxis(float deg, char axis) | void gpuRotateAxis(float deg, char axis) | ||||
| { | { | ||||
| #if SUPPORT_LEGACY_MATRIX | #if SUPPORT_LEGACY_MATRIX | ||||
| if (state.mode == MATRIX_MODE_INACTIVE) { | { | ||||
| float a[3] = { 0.0f }; | float a[3] = { 0.0f }; | ||||
| switch (axis) { | switch (axis) { | ||||
| case 'X': a[0] = 1.0f; break; | case 'X': a[0] = 1.0f; break; | ||||
| case 'Y': a[1] = 1.0f; break; | case 'Y': a[1] = 1.0f; break; | ||||
| case 'Z': a[2] = 1.0f; break; | case 'Z': a[2] = 1.0f; break; | ||||
| default: BLI_assert(false); /* bad axis */ | default: BLI_assert(false); /* bad axis */ | ||||
| } | } | ||||
| glRotatef(deg, a[0], a[1], a[2]); | glRotatef(deg, a[0], a[1], a[2]); | ||||
| state.dirty = true; | state.dirty = true; | ||||
| return; | return; | ||||
| } | } | ||||
| #endif | #endif | ||||
| BLI_assert(state.mode == MATRIX_MODE_3D); | |||||
| /* rotate_m4 works in place */ | /* rotate_m4 works in place */ | ||||
| rotate_m4(ModelView3D, axis, DEG2RADF(deg)); | rotate_m4(ModelView3D, axis, DEG2RADF(deg)); | ||||
| CHECKMAT(ModelView3D); | CHECKMAT(ModelView3D); | ||||
| state.dirty = true; | state.dirty = true; | ||||
| } | } | ||||
| static void mat4_ortho_set(float m[4][4], float left, float right, float bottom, float top, float near, float far) | static void mat4_ortho_set(float m[4][4], float left, float right, float bottom, float top, float near, float far) | ||||
| { | { | ||||
| ▲ Show 20 Lines • Show All 109 Lines • ▼ Show 20 Lines | */ | ||||
| m[3][3] = 1.0f; | m[3][3] = 1.0f; | ||||
| state.dirty = true; | state.dirty = true; | ||||
| } | } | ||||
| void gpuOrtho(float left, float right, float bottom, float top, float near, float far) | void gpuOrtho(float left, float right, float bottom, float top, float near, float far) | ||||
| { | { | ||||
| #if SUPPORT_LEGACY_MATRIX | #if SUPPORT_LEGACY_MATRIX | ||||
| if (state.mode == MATRIX_MODE_INACTIVE) { | { | ||||
| GLenum mode; | GLenum mode; | ||||
| glGetIntegerv(GL_MATRIX_MODE, (GLint*)&mode); | glGetIntegerv(GL_MATRIX_MODE, (GLint*)&mode); | ||||
| if (mode != GL_PROJECTION) { | if (mode != GL_PROJECTION) { | ||||
| glMatrixMode(GL_PROJECTION); | glMatrixMode(GL_PROJECTION); | ||||
| } | } | ||||
| glLoadIdentity(); | glLoadIdentity(); | ||||
| glOrtho(left, right, bottom, top, near, far); | glOrtho(left, right, bottom, top, near, far); | ||||
| if (mode != GL_PROJECTION_MATRIX) { | if (mode != GL_PROJECTION_MATRIX) { | ||||
| glMatrixMode(mode); /* restore */ | glMatrixMode(mode); /* restore */ | ||||
| } | } | ||||
| state.dirty = true; | state.dirty = true; | ||||
| return; | return; | ||||
| } | } | ||||
| #endif | #endif | ||||
| BLI_assert(state.mode == MATRIX_MODE_3D); | |||||
| mat4_ortho_set(Projection3D, left, right, bottom, top, near, far); | mat4_ortho_set(Projection3D, left, right, bottom, top, near, far); | ||||
| CHECKMAT(Projection3D); | CHECKMAT(Projection3D); | ||||
| state.dirty = true; | state.dirty = true; | ||||
| } | } | ||||
| void gpuOrtho2D(float left, float right, float bottom, float top) | void gpuOrtho2D(float left, float right, float bottom, float top) | ||||
| { | { | ||||
| #if SUPPORT_LEGACY_MATRIX | #if SUPPORT_LEGACY_MATRIX | ||||
| if (state.mode == MATRIX_MODE_INACTIVE) { | { | ||||
| GLenum mode; | GLenum mode; | ||||
| glGetIntegerv(GL_MATRIX_MODE, (GLint*)&mode); | glGetIntegerv(GL_MATRIX_MODE, (GLint*)&mode); | ||||
| if (mode != GL_PROJECTION) { | if (mode != GL_PROJECTION) { | ||||
| glMatrixMode(GL_PROJECTION); | glMatrixMode(GL_PROJECTION); | ||||
| } | } | ||||
| glLoadIdentity(); | glLoadIdentity(); | ||||
| glOrtho(left, right, bottom, top, -1.0f, 1.0f); | glOrtho(left, right, bottom, top, -1.0f, 1.0f); | ||||
| if (mode != GL_PROJECTION_MATRIX) { | if (mode != GL_PROJECTION_MATRIX) { | ||||
| glMatrixMode(mode); /* restore */ | glMatrixMode(mode); /* restore */ | ||||
| } | } | ||||
| state.dirty = true; | state.dirty = true; | ||||
| return; | return; | ||||
| } | } | ||||
| #endif | #endif | ||||
| BLI_assert(state.mode == MATRIX_MODE_2D); | |||||
| #if MATRIX_2D_4x4 | |||||
| Mat4 m; | Mat4 m; | ||||
| mat4_ortho_set(m, left, right, bottom, top, -1.0f, 1.0f); | mat4_ortho_set(m, left, right, bottom, top, -1.0f, 1.0f); | ||||
| #else | |||||
| /* TODO: correct 3x3 implementation */ | |||||
| #endif | |||||
| CHECKMAT(Projection2D); | CHECKMAT(Projection2D); | ||||
| state.dirty = true; | state.dirty = true; | ||||
| } | } | ||||
| void gpuFrustum(float left, float right, float bottom, float top, float near, float far) | void gpuFrustum(float left, float right, float bottom, float top, float near, float far) | ||||
| { | { | ||||
| #if SUPPORT_LEGACY_MATRIX | #if SUPPORT_LEGACY_MATRIX | ||||
| if (state.mode == MATRIX_MODE_INACTIVE) { | { | ||||
| GLenum mode; | GLenum mode; | ||||
| glGetIntegerv(GL_MATRIX_MODE, (GLint*)&mode); | glGetIntegerv(GL_MATRIX_MODE, (GLint*)&mode); | ||||
| if (mode != GL_PROJECTION) { | if (mode != GL_PROJECTION) { | ||||
| glMatrixMode(GL_PROJECTION); | glMatrixMode(GL_PROJECTION); | ||||
| } | } | ||||
| glLoadIdentity(); | glLoadIdentity(); | ||||
| glFrustum(left, right, bottom, top, near, far); | glFrustum(left, right, bottom, top, near, far); | ||||
| if (mode != GL_PROJECTION_MATRIX) { | if (mode != GL_PROJECTION_MATRIX) { | ||||
| glMatrixMode(mode); /* restore */ | glMatrixMode(mode); /* restore */ | ||||
| } | } | ||||
| state.dirty = true; | state.dirty = true; | ||||
| return; | return; | ||||
| } | } | ||||
| #endif | #endif | ||||
| BLI_assert(state.mode == MATRIX_MODE_3D); | |||||
| mat4_frustum_set(Projection3D, left, right, bottom, top, near, far); | mat4_frustum_set(Projection3D, left, right, bottom, top, near, far); | ||||
| CHECKMAT(Projection3D); | CHECKMAT(Projection3D); | ||||
| state.dirty = true; | state.dirty = true; | ||||
| } | } | ||||
| void gpuPerspective(float fovy, float aspect, float near, float far) | void gpuPerspective(float fovy, float aspect, float near, float far) | ||||
| { | { | ||||
| float half_height = tanf(fovy * (float)(M_PI / 360.0)) * near; | float half_height = tanf(fovy * (float)(M_PI / 360.0)) * near; | ||||
| ▲ Show 20 Lines • Show All 69 Lines • ▼ Show 20 Lines | bool gpuUnProject(const float win[3], const float model[4][4], const float proj[4][4], const int view[4], float world[3]) | ||||
| mul_v3_v3fl(world, out, 1.0f / out[3]); | mul_v3_v3fl(world, out, 1.0f / out[3]); | ||||
| return true; | return true; | ||||
| } | } | ||||
| const float *gpuGetModelViewMatrix3D(float m[4][4]) | const float *gpuGetModelViewMatrix3D(float m[4][4]) | ||||
| { | { | ||||
| #if SUPPORT_LEGACY_MATRIX | #if SUPPORT_LEGACY_MATRIX | ||||
| if (state.mode == MATRIX_MODE_INACTIVE) { | { | ||||
| if (m == NULL) { | if (m == NULL) { | ||||
| static Mat4 temp; | static Mat4 temp; | ||||
| m = temp; | m = temp; | ||||
| } | } | ||||
| glGetFloatv(GL_MODELVIEW_MATRIX, (float*)m); | glGetFloatv(GL_MODELVIEW_MATRIX, (float*)m); | ||||
| return (const float*)m; | return (const float*)m; | ||||
| } | } | ||||
| #endif | #endif | ||||
| BLI_assert(state.mode == MATRIX_MODE_3D); | |||||
| if (m) { | if (m) { | ||||
| copy_m4_m4(m, ModelView3D); | copy_m4_m4(m, ModelView3D); | ||||
| return (const float*)m; | return (const float*)m; | ||||
| } | } | ||||
| else { | else { | ||||
| return (const float*)ModelView3D; | return (const float*)ModelView3D; | ||||
| } | } | ||||
| } | } | ||||
| const float *gpuGetProjectionMatrix3D(float m[4][4]) | const float *gpuGetProjectionMatrix3D(float m[4][4]) | ||||
| { | { | ||||
| #if SUPPORT_LEGACY_MATRIX | #if SUPPORT_LEGACY_MATRIX | ||||
| if (state.mode == MATRIX_MODE_INACTIVE) { | { | ||||
| if (m == NULL) { | if (m == NULL) { | ||||
| static Mat4 temp; | static Mat4 temp; | ||||
| m = temp; | m = temp; | ||||
| } | } | ||||
| glGetFloatv(GL_PROJECTION_MATRIX, (float*)m); | glGetFloatv(GL_PROJECTION_MATRIX, (float*)m); | ||||
| return (const float*)m; | return (const float*)m; | ||||
| } | } | ||||
| #endif | #endif | ||||
| BLI_assert(state.mode == MATRIX_MODE_3D); | |||||
| if (m) { | if (m) { | ||||
| copy_m4_m4(m, Projection3D); | copy_m4_m4(m, Projection3D); | ||||
| return (const float*)m; | return (const float*)m; | ||||
| } | } | ||||
| else { | else { | ||||
| return (const float*)Projection3D; | return (const float*)Projection3D; | ||||
| } | } | ||||
| } | } | ||||
| const float *gpuGetModelViewProjectionMatrix3D(float m[4][4]) | const float *gpuGetModelViewProjectionMatrix3D(float m[4][4]) | ||||
| { | { | ||||
| if (m == NULL) { | if (m == NULL) { | ||||
| static Mat4 temp; | static Mat4 temp; | ||||
| m = temp; | m = temp; | ||||
| } | } | ||||
| #if SUPPORT_LEGACY_MATRIX | #if SUPPORT_LEGACY_MATRIX | ||||
| if (state.mode == MATRIX_MODE_INACTIVE) { | { | ||||
| Mat4 proj; | Mat4 proj; | ||||
| glGetFloatv(GL_MODELVIEW_MATRIX, (float*)m); | glGetFloatv(GL_MODELVIEW_MATRIX, (float*)m); | ||||
| glGetFloatv(GL_PROJECTION_MATRIX, (float*)proj); | glGetFloatv(GL_PROJECTION_MATRIX, (float*)proj); | ||||
| mul_m4_m4_pre(m, proj); | mul_m4_m4_pre(m, proj); | ||||
| return (const float*)m; | return (const float*)m; | ||||
| } | } | ||||
| #endif | #endif | ||||
| BLI_assert(state.mode == MATRIX_MODE_3D); | |||||
| mul_m4_m4m4(m, Projection3D, ModelView3D); | mul_m4_m4m4(m, Projection3D, ModelView3D); | ||||
| return (const float*)m; | return (const float*)m; | ||||
| } | } | ||||
| const float *gpuGetNormalMatrix(float m[3][3]) | const float *gpuGetNormalMatrix(float m[3][3]) | ||||
| { | { | ||||
| if (m == NULL) { | if (m == NULL) { | ||||
| static Mat3 temp3; | static Mat3 temp3; | ||||
| Show All 16 Lines | const float *gpuGetNormalMatrixInverse(float m[3][3]) | ||||
| } | } | ||||
| gpuGetNormalMatrix(m); | gpuGetNormalMatrix(m); | ||||
| invert_m3(m); | invert_m3(m); | ||||
| return (const float*)m; | return (const float*)m; | ||||
| } | } | ||||
| #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 | |||||
| void gpuBindMatrices(const ShaderInterface* shaderface) | void gpuBindMatrices(const ShaderInterface* shaderface) | ||||
| { | { | ||||
| /* set uniform values to matrix stack values | /* set uniform values to matrix stack values | ||||
| * call this before a draw call if desired matrices are dirty | * call this before a draw call if desired matrices are dirty | ||||
| * call glUseProgram before this, as glUniform expects program to be bound | * call glUseProgram before this, as glUniform expects program to be bound | ||||
| */ | */ | ||||
| const ShaderInput *MV = ShaderInterface_builtin_uniform(shaderface, UNIFORM_MODELVIEW_3D); | const ShaderInput *MV = ShaderInterface_builtin_uniform(shaderface, UNIFORM_MODELVIEW_3D); | ||||
| const ShaderInput *P = ShaderInterface_builtin_uniform(shaderface, UNIFORM_PROJECTION_3D); | const ShaderInput *P = ShaderInterface_builtin_uniform(shaderface, UNIFORM_PROJECTION_3D); | ||||
| const ShaderInput *MVP = ShaderInterface_builtin_uniform(shaderface, UNIFORM_MVP_3D); | const ShaderInput *MVP = ShaderInterface_builtin_uniform(shaderface, UNIFORM_MVP_3D); | ||||
| /* TODO: teach ShaderInterface to distinguish 2D from 3D --^ */ | |||||
| if (state.mode == MATRIX_MODE_2D) { | |||||
| if (MV) { | |||||
| #if DEBUG_MATRIX_BIND | |||||
| puts("setting 2D MV matrix"); | |||||
| #endif | |||||
| glUniformMatrix4fv(MV->location, 1, GL_FALSE, gpuGetModelViewMatrix2D(NULL)); | |||||
| } | |||||
| if (P) { | |||||
| #if DEBUG_MATRIX_BIND | |||||
| puts("setting 2D P matrix"); | |||||
| #endif | |||||
| glUniformMatrix4fv(P->location, 1, GL_FALSE, gpuGetProjectionMatrix2D(NULL)); | |||||
| } | |||||
| if (MVP) { | |||||
| #if DEBUG_MATRIX_BIND | |||||
| puts("setting 2D MVP matrix"); | |||||
| #endif | |||||
| glUniformMatrix4fv(MVP->location, 1, GL_FALSE, gpuGetModelViewProjectionMatrix2D(NULL)); | |||||
| } | |||||
| } | |||||
| else { | |||||
| const ShaderInput *N = ShaderInterface_builtin_uniform(shaderface, UNIFORM_NORMAL_3D); | const ShaderInput *N = ShaderInterface_builtin_uniform(shaderface, UNIFORM_NORMAL_3D); | ||||
| const ShaderInput *MV_inv = ShaderInterface_builtin_uniform(shaderface, UNIFORM_MODELVIEW_INV_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); | const ShaderInput *P_inv = ShaderInterface_builtin_uniform(shaderface, UNIFORM_PROJECTION_INV_3D); | ||||
| if (MV) { | if (MV) { | ||||
| #if DEBUG_MATRIX_BIND | #if DEBUG_MATRIX_BIND | ||||
| puts("setting 3D MV matrix"); | puts("setting 3D MV matrix"); | ||||
| #endif | #endif | ||||
| glUniformMatrix4fv(MV->location, 1, GL_FALSE, gpuGetModelViewMatrix3D(NULL)); | glUniformMatrix4fv(MV->location, 1, GL_FALSE, gpuGetModelViewMatrix3D(NULL)); | ||||
| } | } | ||||
| if (P) { | if (P) { | ||||
| #if DEBUG_MATRIX_BIND | #if DEBUG_MATRIX_BIND | ||||
| puts("setting 3D P matrix"); | puts("setting 3D P matrix"); | ||||
| #endif | #endif | ||||
| glUniformMatrix4fv(P->location, 1, GL_FALSE, gpuGetProjectionMatrix3D(NULL)); | glUniformMatrix4fv(P->location, 1, GL_FALSE, gpuGetProjectionMatrix3D(NULL)); | ||||
| } | } | ||||
| if (MVP) { | if (MVP) { | ||||
| #if DEBUG_MATRIX_BIND | #if DEBUG_MATRIX_BIND | ||||
| puts("setting 3D MVP matrix"); | puts("setting 3D MVP matrix"); | ||||
| #endif | #endif | ||||
| glUniformMatrix4fv(MVP->location, 1, GL_FALSE, gpuGetModelViewProjectionMatrix3D(NULL)); | glUniformMatrix4fv(MVP->location, 1, GL_FALSE, gpuGetModelViewProjectionMatrix3D(NULL)); | ||||
| } | } | ||||
| if (N) { | if (N) { | ||||
| #if DEBUG_MATRIX_BIND | #if DEBUG_MATRIX_BIND | ||||
| puts("setting 3D normal matrix"); | puts("setting 3D normal matrix"); | ||||
| #endif | #endif | ||||
| glUniformMatrix3fv(N->location, 1, GL_FALSE, gpuGetNormalMatrix(NULL)); | glUniformMatrix3fv(N->location, 1, GL_FALSE, gpuGetNormalMatrix(NULL)); | ||||
| } | } | ||||
| if (MV_inv) { | if (MV_inv) { | ||||
| Mat4 m; | Mat4 m; | ||||
| gpuGetModelViewMatrix3D(m); | gpuGetModelViewMatrix3D(m); | ||||
| invert_m4(m); | invert_m4(m); | ||||
| glUniformMatrix4fv(MV_inv->location, 1, GL_FALSE, (const float*) m); | glUniformMatrix4fv(MV_inv->location, 1, GL_FALSE, (const float*) m); | ||||
| } | } | ||||
| if (P_inv) { | if (P_inv) { | ||||
| Mat4 m; | Mat4 m; | ||||
| gpuGetProjectionMatrix3D(m); | gpuGetProjectionMatrix3D(m); | ||||
| invert_m4(m); | invert_m4(m); | ||||
| glUniformMatrix4fv(P_inv->location, 1, GL_FALSE, (const float*) m); | glUniformMatrix4fv(P_inv->location, 1, GL_FALSE, (const float*) m); | ||||
| } | } | ||||
| } | |||||
| state.dirty = false; | state.dirty = false; | ||||
| } | } | ||||
| bool gpuMatricesDirty(void) | bool gpuMatricesDirty(void) | ||||
| { | { | ||||
| return state.dirty; | return state.dirty; | ||||
| } | } | ||||