implement transformation and projection stacks

this allows for separate transformation and projection stacks
This commit is contained in:
mgood7123 2021-11-18 18:02:59 +10:00 committed by GitHub
parent 3a9f089018
commit 0faceea714
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -888,6 +888,58 @@ RLAPI void rlLoadDrawQuad(void); // Load and draw a quad
// Types and Structures Definition // Types and Structures Definition
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
// A structure to represent a stack
struct rl_MatrixStackNode {
Matrix data;
struct rl_MatrixStackNode* next;
};
typedef struct rl_MatrixStackNode MStack;
MStack* rl_Matrix_newNode(Matrix data)
{
MStack* stackNode = (MStack*) RL_MALLOC(sizeof(MStack));
stackNode->data = data;
stackNode->next = NULL;
return stackNode;
}
void rl_Matrix_push(MStack** root, Matrix data)
{
MStack* stackNode = rl_Matrix_newNode(data);
stackNode->next = *root;
*root = stackNode;
}
Matrix rl_Matrix_pop(MStack** root)
{
MStack* temp = *root;
*root = (*root)->next;
Matrix popped = temp->data;
RL_FREE(temp);
return popped;
}
void rl_Matrix_clear(MStack** root)
{
while ((*root)->next != NULL) {
MStack* temp = *root;
*root = (*root)->next;
RL_FREE(temp);
}
}
void rl_Matrix_delete(MStack** root)
{
while (*root != NULL) {
MStack* temp = *root;
*root = (*root)->next;
RL_FREE(temp);
}
}
typedef struct rlglData { typedef struct rlglData {
rlRenderBatch *currentBatch; // Current render batch rlRenderBatch *currentBatch; // Current render batch
rlRenderBatch defaultBatch; // Default internal render batch rlRenderBatch defaultBatch; // Default internal render batch
@ -901,11 +953,15 @@ typedef struct rlglData {
int currentMatrixMode; // Current matrix mode int currentMatrixMode; // Current matrix mode
Matrix *currentMatrix; // Current matrix pointer Matrix *currentMatrix; // Current matrix pointer
Matrix modelview; // Default modelview matrix Matrix modelview; // Default modelview matrix
Matrix projection; // Default projection matrix Matrix * projection; // Default projection matrix
Matrix transform; // Transform matrix to be used with rlTranslate, rlRotate, rlScale Matrix * transform; // Transform matrix to be used with rlTranslate, rlRotate, rlScale
bool transformRequired; // Require transform matrix application to current draw-call vertex (if required) bool transformRequired; // Require transform matrix application to current draw-call vertex (if required)
Matrix stack[RL_MAX_MATRIX_STACK_SIZE];// Matrix stack for push/pop
int stackCounter; // Matrix stack counter MStack* stackProjection; // Matrix projection stack for push/pop
int stackProjectionCounter; // Matrix projection stack counter
MStack* stackTransform; // Matrix transformation stack for push/pop
int stackTransformCounter; // Matrix transformation stack counter
unsigned int defaultTextureId; // Default texture used on shapes/poly drawing (required by shader) unsigned int defaultTextureId; // Default texture used on shapes/poly drawing (required by shader)
unsigned int activeTextureId[RL_DEFAULT_BATCH_MAX_TEXTURE_UNITS]; // Active texture ids to be enabled on batch drawing (0 active by default) unsigned int activeTextureId[RL_DEFAULT_BATCH_MAX_TEXTURE_UNITS]; // Active texture ids to be enabled on batch drawing (0 active by default)
@ -1033,8 +1089,16 @@ void rlMultMatrixf(float *matf) { glMultMatrixf(matf); }
// Choose the current matrix to be transformed // Choose the current matrix to be transformed
void rlMatrixMode(int mode) void rlMatrixMode(int mode)
{ {
if (mode == RL_PROJECTION) RLGL.State.currentMatrix = &RLGL.State.projection; if (mode == RL_PROJECTION) {
else if (mode == RL_MODELVIEW) RLGL.State.currentMatrix = &RLGL.State.modelview; RLGL.State.currentMatrix = &RLGL.State.stackProjection->data;
}
else if (mode == RL_MODELVIEW) {
if (RLGL.State.stackTransformCounter == 0) {
RLGL.State.currentMatrix = &RLGL.State.modelview;
} else {
RLGL.State.currentMatrix = &RLGL.State.stackTransform->data;
}
}
//else if (mode == RL_TEXTURE) // Not supported //else if (mode == RL_TEXTURE) // Not supported
RLGL.State.currentMatrixMode = mode; RLGL.State.currentMatrixMode = mode;
@ -1043,32 +1107,50 @@ void rlMatrixMode(int mode)
// Push the current matrix into RLGL.State.stack // Push the current matrix into RLGL.State.stack
void rlPushMatrix(void) void rlPushMatrix(void)
{ {
if (RLGL.State.stackCounter >= RL_MAX_MATRIX_STACK_SIZE) TRACELOG(RL_LOG_ERROR, "RLGL: Matrix stack overflow (RL_MAX_MATRIX_STACK_SIZE)");
if (RLGL.State.currentMatrixMode == RL_MODELVIEW) if (RLGL.State.currentMatrixMode == RL_MODELVIEW)
{ {
RLGL.State.transformRequired = true; RLGL.State.transformRequired = true;
RLGL.State.currentMatrix = &RLGL.State.transform; rl_Matrix_push(&RLGL.State.stackTransform, RLGL.State.stackTransform->data);
RLGL.State.stackTransformCounter++;
RLGL.State.currentMatrix = &RLGL.State.stackTransform->data;
RLGL.State.transform = RLGL.State.currentMatrix;
} else {
rl_Matrix_push(&RLGL.State.stackProjection, RLGL.State.stackProjection->data);
RLGL.State.stackProjectionCounter++;
RLGL.State.currentMatrix = &RLGL.State.stackProjection->data;
RLGL.State.projection = RLGL.State.currentMatrix;
} }
RLGL.State.stack[RLGL.State.stackCounter] = *RLGL.State.currentMatrix;
RLGL.State.stackCounter++;
} }
// Pop lattest inserted matrix from RLGL.State.stack // Pop lattest inserted matrix from RLGL.State.stack
void rlPopMatrix(void) void rlPopMatrix(void)
{ {
if (RLGL.State.stackCounter > 0) if (RLGL.State.currentMatrixMode == RL_MODELVIEW)
{ {
Matrix mat = RLGL.State.stack[RLGL.State.stackCounter - 1]; if (RLGL.State.stackTransformCounter > 0) {
*RLGL.State.currentMatrix = mat; MStack* temp = RLGL.State.stackTransform;
RLGL.State.stackCounter--; RLGL.State.stackTransform = RLGL.State.stackTransform->next;
} RL_FREE(temp);
RLGL.State.stackTransformCounter--;
if ((RLGL.State.stackCounter == 0) && (RLGL.State.currentMatrixMode == RL_MODELVIEW)) if (RLGL.State.stackTransformCounter == 0) {
{
RLGL.State.currentMatrix = &RLGL.State.modelview;
RLGL.State.transformRequired = false; RLGL.State.transformRequired = false;
RLGL.State.currentMatrix = &RLGL.State.modelview;
RLGL.State.transform = NULL;
} else {
RLGL.State.currentMatrix = &RLGL.State.stackTransform->data;
RLGL.State.transform = RLGL.State.currentMatrix;
}
}
} else {
if (RLGL.State.stackProjectionCounter > 0) {
MStack* temp = RLGL.State.stackProjection;
RLGL.State.stackProjection = RLGL.State.stackProjection->next;
RL_FREE(temp);
RLGL.State.stackProjectionCounter--;
RLGL.State.currentMatrix = &RLGL.State.stackProjection->data;
RLGL.State.projection = RLGL.State.currentMatrix;
}
} }
} }
@ -1309,7 +1391,8 @@ void rlEnd(void)
// WARNING: If we are between rlPushMatrix() and rlPopMatrix() and we need to force a rlDrawRenderBatch(), // WARNING: If we are between rlPushMatrix() and rlPopMatrix() and we need to force a rlDrawRenderBatch(),
// we need to call rlPopMatrix() before to recover *RLGL.State.currentMatrix (RLGL.State.modelview) for the next forced draw call! // we need to call rlPopMatrix() before to recover *RLGL.State.currentMatrix (RLGL.State.modelview) for the next forced draw call!
// If we have multiple matrix pushed, it will require "RLGL.State.stackCounter" pops before launching the draw // If we have multiple matrix pushed, it will require "RLGL.State.stackCounter" pops before launching the draw
for (int i = RLGL.State.stackCounter; i >= 0; i--) rlPopMatrix(); rl_Matrix_clear(&RLGL.State.stackTransform);
RLGL.State.stackTransformCounter = 0;
rlDrawRenderBatch(RLGL.currentBatch); rlDrawRenderBatch(RLGL.currentBatch);
} }
} }
@ -1325,9 +1408,9 @@ void rlVertex3f(float x, float y, float z)
// Transform provided vector if required // Transform provided vector if required
if (RLGL.State.transformRequired) if (RLGL.State.transformRequired)
{ {
tx = RLGL.State.transform.m0*x + RLGL.State.transform.m4*y + RLGL.State.transform.m8*z + RLGL.State.transform.m12; tx = RLGL.State.transform[0].m0*x + RLGL.State.transform[0].m4*y + RLGL.State.transform[0].m8*z + RLGL.State.transform[0].m12;
ty = RLGL.State.transform.m1*x + RLGL.State.transform.m5*y + RLGL.State.transform.m9*z + RLGL.State.transform.m13; ty = RLGL.State.transform[0].m1*x + RLGL.State.transform[0].m5*y + RLGL.State.transform[0].m9*z + RLGL.State.transform[0].m13;
tz = RLGL.State.transform.m2*x + RLGL.State.transform.m6*y + RLGL.State.transform.m10*z + RLGL.State.transform.m14; tz = RLGL.State.transform[0].m2*x + RLGL.State.transform[0].m6*y + RLGL.State.transform[0].m10*z + RLGL.State.transform[0].m14;
} }
// Verify that current vertex buffer elements limit has not been reached // Verify that current vertex buffer elements limit has not been reached
@ -1898,11 +1981,13 @@ void rlglInit(int width, int height)
RLGL.currentBatch = &RLGL.defaultBatch; RLGL.currentBatch = &RLGL.defaultBatch;
// Init stack matrices (emulating OpenGL 1.1) // Init stack matrices (emulating OpenGL 1.1)
for (int i = 0; i < RL_MAX_MATRIX_STACK_SIZE; i++) RLGL.State.stack[i] = rlMatrixIdentity(); rl_Matrix_push(&RLGL.State.stackTransform, rlMatrixIdentity());
rl_Matrix_push(&RLGL.State.stackProjection, rlMatrixIdentity());
// Init internal matrices // Init internal matrices
RLGL.State.transform = rlMatrixIdentity(); RLGL.State.transform = NULL;
RLGL.State.projection = rlMatrixIdentity(); RLGL.State.projection = &RLGL.State.stackProjection->data;
RLGL.State.modelview = rlMatrixIdentity(); RLGL.State.modelview = rlMatrixIdentity();
RLGL.State.currentMatrix = &RLGL.State.modelview; RLGL.State.currentMatrix = &RLGL.State.modelview;
#endif // GRAPHICS_API_OPENGL_33 || GRAPHICS_API_OPENGL_ES2 #endif // GRAPHICS_API_OPENGL_33 || GRAPHICS_API_OPENGL_ES2
@ -1959,6 +2044,10 @@ void rlglClose(void)
glDeleteTextures(1, &RLGL.State.defaultTextureId); // Unload default texture glDeleteTextures(1, &RLGL.State.defaultTextureId); // Unload default texture
TRACELOG(RL_LOG_INFO, "TEXTURE: [ID %i] Default texture unloaded successfully", RLGL.State.defaultTextureId); TRACELOG(RL_LOG_INFO, "TEXTURE: [ID %i] Default texture unloaded successfully", RLGL.State.defaultTextureId);
// unload matrix stacks
rl_Matrix_delete(&RLGL.State.stackTransform);
rl_Matrix_delete(&RLGL.State.stackProjection);
#endif #endif
} }
@ -2484,7 +2573,7 @@ void rlDrawRenderBatch(rlRenderBatch *batch)
// Draw batch vertex buffers (considering VR stereo if required) // Draw batch vertex buffers (considering VR stereo if required)
//------------------------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------------------------
Matrix matProjection = RLGL.State.projection; Matrix matProjection = RLGL.State.projection[0];
Matrix matModelView = RLGL.State.modelview; Matrix matModelView = RLGL.State.modelview;
int eyeCount = 1; int eyeCount = 1;
@ -2510,7 +2599,7 @@ void rlDrawRenderBatch(rlRenderBatch *batch)
glUseProgram(RLGL.State.currentShaderId); glUseProgram(RLGL.State.currentShaderId);
// Create modelview-projection matrix and upload to shader // Create modelview-projection matrix and upload to shader
Matrix matMVP = rlMatrixMultiply(RLGL.State.modelview, RLGL.State.projection); Matrix matMVP = rlMatrixMultiply(RLGL.State.modelview, RLGL.State.projection[0]);
float matMVPfloat[16] = { float matMVPfloat[16] = {
matMVP.m0, matMVP.m1, matMVP.m2, matMVP.m3, matMVP.m0, matMVP.m1, matMVP.m2, matMVP.m3,
matMVP.m4, matMVP.m5, matMVP.m6, matMVP.m7, matMVP.m4, matMVP.m5, matMVP.m6, matMVP.m7,
@ -2605,7 +2694,7 @@ void rlDrawRenderBatch(rlRenderBatch *batch)
batch->currentDepth = -1.0f; batch->currentDepth = -1.0f;
// Restore projection/modelview matrices // Restore projection/modelview matrices
RLGL.State.projection = matProjection; RLGL.State.projection[0] = matProjection;
RLGL.State.modelview = matModelView; RLGL.State.modelview = matModelView;
// Reset RLGL.currentBatch->draws array // Reset RLGL.currentBatch->draws array
@ -4028,7 +4117,7 @@ Matrix rlGetMatrixProjection(void)
m.m15 = mat[15]; m.m15 = mat[15];
return m; return m;
#else #else
return RLGL.State.projection; return RLGL.State.projection[0];
#endif #endif
} }
@ -4041,7 +4130,9 @@ Matrix rlGetMatrixTransform(void)
// Is this the right order? or should we start with the first stored matrix instead of the last one? // Is this the right order? or should we start with the first stored matrix instead of the last one?
//Matrix matStackTransform = rlMatrixIdentity(); //Matrix matStackTransform = rlMatrixIdentity();
//for (int i = RLGL.State.stackCounter; i > 0; i--) matStackTransform = rlMatrixMultiply(RLGL.State.stack[i], matStackTransform); //for (int i = RLGL.State.stackCounter; i > 0; i--) matStackTransform = rlMatrixMultiply(RLGL.State.stack[i], matStackTransform);
mat = RLGL.State.transform; if (RLGL.State.transform != NULL) {
mat = RLGL.State.transform[0];
}
#endif #endif
return mat; return mat;
} }
@ -4078,7 +4169,7 @@ void rlSetMatrixModelview(Matrix view)
void rlSetMatrixProjection(Matrix projection) void rlSetMatrixProjection(Matrix projection)
{ {
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
RLGL.State.projection = projection; RLGL.State.projection[0] = projection;
#endif #endif
} }