implement transformation and projection stacks
this allows for separate transformation and projection stacks
This commit is contained in:
parent
3a9f089018
commit
0faceea714
163
src/rlgl.h
163
src/rlgl.h
|
|
@ -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.transformRequired = false;
|
||||||
RLGL.State.currentMatrix = &RLGL.State.modelview;
|
RLGL.State.currentMatrix = &RLGL.State.modelview;
|
||||||
RLGL.State.transformRequired = false;
|
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
|
||||||
|
|
@ -3894,7 +3983,7 @@ void rlComputeShaderDispatch(unsigned int groupX, unsigned int groupY, unsigned
|
||||||
unsigned int rlLoadShaderBuffer(unsigned long long size, const void *data, int usageHint)
|
unsigned int rlLoadShaderBuffer(unsigned long long size, const void *data, int usageHint)
|
||||||
{
|
{
|
||||||
unsigned int ssbo = 0;
|
unsigned int ssbo = 0;
|
||||||
|
|
||||||
#if defined(GRAPHICS_API_OPENGL_43)
|
#if defined(GRAPHICS_API_OPENGL_43)
|
||||||
glGenBuffers(1, &ssbo);
|
glGenBuffers(1, &ssbo);
|
||||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo);
|
glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo);
|
||||||
|
|
@ -3925,7 +4014,7 @@ void rlUpdateShaderBufferElements(unsigned int id, const void *data, unsigned lo
|
||||||
unsigned long long rlGetShaderBufferSize(unsigned int id)
|
unsigned long long rlGetShaderBufferSize(unsigned int id)
|
||||||
{
|
{
|
||||||
long long size = 0;
|
long long size = 0;
|
||||||
|
|
||||||
#if defined(GRAPHICS_API_OPENGL_43)
|
#if defined(GRAPHICS_API_OPENGL_43)
|
||||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, id);
|
glBindBuffer(GL_SHADER_STORAGE_BUFFER, id);
|
||||||
glGetInteger64v(GL_SHADER_STORAGE_BUFFER_SIZE, &size);
|
glGetInteger64v(GL_SHADER_STORAGE_BUFFER_SIZE, &size);
|
||||||
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user