Move rotation step outside of inner rendering loop

We need to generate interim vertex points during the collision detection loop
that includes rotation to check for collision. During collision detection,
vertex points are rotated and positioned in placed for checking.

We also re-create this vertex list in the renderer suggesting that we could
cache the list in the entity or look at coupling rendering and collision
detection.
This commit is contained in:
Doyle Thai 2016-11-23 13:42:46 +11:00
parent 20749dd668
commit 0c7824bf18
6 changed files with 245 additions and 148 deletions

View File

@ -83,7 +83,7 @@ void initRenderer(GameState *state, v2 windowSize) {
glEnableVertexAttribArray(0);
u32 numVertexElements = 4;
u32 stride = sizeof(Vertex);
u32 stride = sizeof(RenderVertex);
glVertexAttribPointer(0, numVertexElements, GL_FLOAT,
GL_FALSE, stride, (GLvoid *)0);
@ -98,8 +98,9 @@ void initRenderer(GameState *state, v2 windowSize) {
renderer->groupCapacity = 4096;
for (i32 i = 0; i < ARRAY_COUNT(renderer->groups); i++)
{
renderer->groups[i].vertexList = memory_pushBytes(
&state->persistentArena, renderer->groupCapacity * sizeof(Vertex));
renderer->groups[i].vertexList =
memory_pushBytes(&state->persistentArena,
renderer->groupCapacity * sizeof(RenderVertex));
}
}
@ -221,38 +222,36 @@ v2 *createAsteroidVertexList(MemoryArena_ *arena, i32 iterations,
return result;
}
v2 *createEntityEdgeList(MemoryArena_ *transientArena, Entity *entity)
v2 *createNormalEdgeList(MemoryArena_ *transientArena, v2 *vertexList,
i32 vertexListSize)
{
v2 *result = memory_pushBytes(transientArena,
sizeof(v2) * entity->numVertexPoints);
i32 numVertexes = entity->numVertexPoints;
for (i32 i = 0; i < numVertexes - 1; i++)
v2 *result = memory_pushBytes(transientArena, sizeof(v2) * vertexListSize);
for (i32 i = 0; i < vertexListSize - 1; i++)
{
ASSERT((i + 1) < numVertexes);
result[i] =
v2_sub(entity->vertexPoints[i + 1], entity->vertexPoints[i]);
ASSERT((i + 1) < vertexListSize);
result[i] = v2_sub(vertexList[i + 1], vertexList[i]);
result[i] = v2_perpendicular(result[i]);
}
// NOTE(doyle): Creating the last edge requires using the first
// vertex point which is at index 0
result[numVertexes - 1] =
v2_sub(entity->vertexPoints[0], entity->vertexPoints[numVertexes - 1]);
result[vertexListSize - 1] =
v2_sub(vertexList[0], vertexList[vertexListSize - 1]);
result[vertexListSize - 1] = v2_perpendicular(result[vertexListSize - 1]);
return result;
}
v2 calculateProjectionRangeForEdge(Entity *entity, v2 edgeNormal)
v2 calculateProjectionRangeForEdge(v2 *vertexList, i32 vertexListSize,
v2 edgeNormal)
{
v2 result = {0};
result.max = v2_dot(entity->vertexPoints[0], edgeNormal);
result.min = v2_dot(vertexList[0], edgeNormal);
result.max = result.min;
for (i32 vertexIndex = 0; vertexIndex < entity->numVertexPoints;
vertexIndex++)
for (i32 vertexIndex = 0; vertexIndex < vertexListSize; vertexIndex++)
{
f32 dist =
v2_dot(entity->vertexPoints[vertexIndex], edgeNormal);
f32 dist = v2_dot(vertexList[vertexIndex], edgeNormal);
if (dist < result.min)
result.min = dist;
@ -263,20 +262,20 @@ v2 calculateProjectionRangeForEdge(Entity *entity, v2 edgeNormal)
return result;
}
b32 checkEntityProjectionOverlap(Entity *entity, Entity *checkEntity,
v2 *entityEdges)
b32 checkEdgeProjectionOverlap(v2 *vertexList, i32 listSize,
v2 *checkVertexList, i32 checkListSize,
v2 *edgeList, i32 totalNumEdges)
{
b32 result = TRUE;
for (i32 edgeIndex = 0; edgeIndex < entity->numVertexPoints && result;
edgeIndex++)
for (i32 edgeIndex = 0; edgeIndex < totalNumEdges && result; edgeIndex++)
{
v2 entityProjectionRange =
calculateProjectionRangeForEdge(entity, entityEdges[edgeIndex]);
v2 checkEntityProjectionRange = calculateProjectionRangeForEdge(
checkEntity, entityEdges[edgeIndex]);
v2 projectionRange = calculateProjectionRangeForEdge(
vertexList, listSize, edgeList[edgeIndex]);
if (!v2_intervalsOverlap(entityProjectionRange,
checkEntityProjectionRange))
v2 checkProjectionRange = calculateProjectionRangeForEdge(
checkVertexList, checkListSize, edgeList[edgeIndex]);
if (!v2_intervalsOverlap(projectionRange, checkProjectionRange))
{
result = FALSE;
return result;
@ -286,7 +285,7 @@ b32 checkEntityProjectionOverlap(Entity *entity, Entity *checkEntity,
return result;
}
void moveEntity(GameState *state, Entity *entity, v2 ddP, f32 dt, f32 ddPSpeed)
b32 moveEntity(GameState *state, Entity *entity, v2 ddP, f32 dt, f32 ddPSpeed)
{
ASSERT(ABS(ddP.x) <= 1.0f && ABS(ddP.y) <= 1.0f);
/*
@ -311,7 +310,8 @@ void moveEntity(GameState *state, Entity *entity, v2 ddP, f32 dt, f32 ddPSpeed)
v2 newPos = v2_add(v2_add(ddPHalfDtSquared, oldDpDt), oldPos);
b32 willCollide = FALSE;
#if 0
#if 1
if (entity->renderMode == rendermode_polygon && entity->collides)
{
for (i32 i = 0; i < state->entityIndex; i++)
@ -322,31 +322,40 @@ void moveEntity(GameState *state, Entity *entity, v2 ddP, f32 dt, f32 ddPSpeed)
if (checkEntity->renderMode == rendermode_polygon &&
checkEntity->collides)
{
i32 numEntityEdges = entity->numVertexPoints;
i32 numCheckEntityEdges = checkEntity->numVertexPoints;
v2 *entityEdges =
createEntityEdgeList(&state->transientArena, entity);
v2 *checkEntityEdges =
createEntityEdgeList(&state->transientArena, entity);
/* Create entity edge lists */
v2 *entityVertexListOffsetToP =
entity_createVertexList(&state->transientArena, entity);
v2 *checkEntityVertexListOffsetToP = entity_createVertexList(
&state->transientArena, checkEntity);
// Convert inplace the vector normal of the edges
for (i32 i = 0; i < numEntityEdges; i++)
v2 *entityEdgeList = createNormalEdgeList(
&state->transientArena, entityVertexListOffsetToP,
entity->numVertexPoints);
v2 *checkEntityEdgeList = createNormalEdgeList(
&state->transientArena, checkEntityVertexListOffsetToP,
checkEntity->numVertexPoints);
/* Combine both edge lists into one */
i32 totalNumEdges =
checkEntity->numVertexPoints + entity->numVertexPoints;
v2 *edgeList = memory_pushBytes(&state->transientArena,
totalNumEdges * sizeof(v2));
for (i32 i = 0; i < entity->numVertexPoints; i++)
{
entityEdges[i] = v2_perpendicular(entityEdges[i]);
entityEdges[i] = v2_add(entityEdges[i], entity->pos);
edgeList[i] = entityEdgeList[i];
}
for (i32 i = 0; i < numCheckEntityEdges; i++)
for (i32 i = 0; i < checkEntity->numVertexPoints; i++)
{
checkEntityEdges[i] = v2_perpendicular(checkEntityEdges[i]);
checkEntityEdges[i] =
v2_add(checkEntityEdges[i], checkEntity->pos);
edgeList[i + entity->numVertexPoints] =
checkEntityEdgeList[i];
}
if ((checkEntityProjectionOverlap(entity, checkEntity,
entityEdges) &&
checkEntityProjectionOverlap(entity, checkEntity,
checkEntityEdges)))
if (checkEdgeProjectionOverlap(
entityVertexListOffsetToP, entity->numVertexPoints,
checkEntityVertexListOffsetToP,
checkEntity->numVertexPoints, edgeList, totalNumEdges))
{
willCollide = TRUE;
}
@ -364,13 +373,17 @@ void moveEntity(GameState *state, Entity *entity, v2 ddP, f32 dt, f32 ddPSpeed)
entity->dP = newDp;
entity->pos = newPos;
}
else
{
entity->dP = v2_scale(newDp, -1.0f);
}
return willCollide;
}
void asteroid_gameUpdateAndRender(GameState *state, Memory *memory,
v2 windowSize, f32 dt)
{
i32 iterations = 16;
memory_arenaInit(&state->transientArena, memory->transient,
memory->transientSize);
@ -387,8 +400,9 @@ void asteroid_gameUpdateAndRender(GameState *state, Memory *memory,
{ // Init ship entity
Entity *ship = &state->entityList[state->entityIndex];
ship->id = state->entityIndex++;
ship->pos = V2(0, 0);
ship->pos = V2(100, 100);
ship->size = V2(25.0f, 50.0f);
ship->rotation = 90.0f;
ship->hitbox = ship->size;
ship->offset = v2_scale(ship->size, 0.5f);
@ -411,7 +425,7 @@ void asteroid_gameUpdateAndRender(GameState *state, Memory *memory,
ship->tex = NULL;
ship->collides = TRUE;
i32 numAsteroids = 8;
i32 numAsteroids = 1;
for (i32 i = 0; i < numAsteroids; i++)
{
Entity *asteroid = &state->entityList[state->entityIndex];
@ -420,7 +434,7 @@ void asteroid_gameUpdateAndRender(GameState *state, Memory *memory,
i32 randValue = rand();
i32 randX = (randValue % (i32)windowSize.w);
i32 randY = (randValue % (i32)windowSize.h);
asteroid->pos = V2i(randX, randY);
asteroid->pos = V2i(500, 500);
asteroid->size = V2(100.0f, 100.0f);
asteroid->hitbox = asteroid->size;
@ -438,6 +452,19 @@ void asteroid_gameUpdateAndRender(GameState *state, Memory *memory,
asteroid->tex = NULL;
asteroid->collides = TRUE;
}
Entity *square = &state->entityList[state->entityIndex];
square->id = state->entityIndex++;
square->pos = V2(350, 350);
square->size = V2(75.0f, 75.0f);
square->hitbox = square->size;
square->offset = v2_scale(square->size, 0.5f);
square->scale = 1;
square->type = entitytype_asteroid;
square->direction = direction_null;
square->renderMode = rendermode_quad;
square->tex = NULL;
square->collides = TRUE;
}
state->camera.min = V2(0, 0);
@ -546,6 +573,7 @@ void asteroid_gameUpdateAndRender(GameState *state, Memory *memory,
}
v2 ddP = {0};
#if 0
switch (entity->direction)
{
case direction_north:
@ -613,15 +641,20 @@ void asteroid_gameUpdateAndRender(GameState *state, Memory *memory,
// NOTE(doyle): Make asteroids start and move at constant speed
ddPSpeedInMs = 2;
entity->dP = v2_scale(ddP, state->pixelsPerMeter * ddPSpeedInMs);
#endif
entity->rotation += (randValue % 20) * dt;
}
moveEntity(state, entity, ddP, dt, ddPSpeedInMs);
b32 willCollide = moveEntity(state, entity, ddP, dt, ddPSpeedInMs);
v4 entityCollisionColor = V4(1.0f, 1.0f, 1.0f, 1.0f);
if (willCollide) entityCollisionColor = V4(1.0f, 0, 0, 1.0f);
RenderFlags flags = renderflag_wireframe | renderflag_no_texture;
renderer_entity(&state->renderer, &state->transientArena, state->camera,
entity, V2(0, 0), 0,
V4(0.4f, 0.8f, 1.0f, 1.0f), flags);
entityCollisionColor, flags);
}
debug_drawUi(state, dt);

View File

@ -1,6 +1,8 @@
#include "Dengine/Entity.h"
#include "Dengine/AssetManager.h"
#include "Dengine/Debug.h"
#include "Dengine/Math.h"
#include "Dengine/MemoryArena.h"
SubTexture entity_getActiveSubTexture(Entity *const entity)
{
@ -86,3 +88,22 @@ void entity_addAnim(AssetManager *const assetManager, Entity *const entity,
DEBUG_LOG("No more free entity animation slots");
}
v2 *entity_createVertexList(MemoryArena_ *transientArena, Entity *entity)
{
v2 *result =
memory_pushBytes(transientArena, entity->numVertexPoints * sizeof(v2));
for (i32 i = 0; i < entity->numVertexPoints; i++)
{
result[i] = v2_sub(entity->vertexPoints[i], entity->offset);
result[i] = v2_add(result[i], entity->pos);
}
math_applyRotationToVertexes(result[0], entity->offset,
DEGREES_TO_RADIANS(entity->rotation), result,
entity->numVertexPoints);
return result;
}

View File

@ -10,8 +10,8 @@
typedef struct RenderQuad
{
Vertex vertex[4];
} RenderQuad_;
RenderVertex vertexList[4];
} RenderQuad;
// NOTE(doyle): A vertex batch is the batch of vertexes comprised to make one
// shape
@ -56,7 +56,8 @@ INTERNAL void endVertexBatch(Renderer *renderer)
i32 freeVertexSlots = renderer->groupCapacity - group->vertexIndex;
if (numDegenerateVertexes < freeVertexSlots)
{
Vertex degenerateVertex = group->vertexList[group->vertexIndex-1];
RenderVertex degenerateVertex =
group->vertexList[group->vertexIndex - 1];
group->vertexList[group->vertexIndex++] = degenerateVertex;
group->vertexList[group->vertexIndex++] = degenerateVertex;
}
@ -65,8 +66,38 @@ INTERNAL void endVertexBatch(Renderer *renderer)
renderer->groupIndexForVertexBatch = -1;
}
INTERNAL void applyRotationToVertexes(v2 pos, v2 pivotPoint, Radians rotate,
RenderVertex *vertexList,
i32 vertexListSize)
{
if (rotate == 0) return;
// NOTE(doyle): Move the world origin to the base position of the object.
// Then move the origin to the pivot point (e.g. center of object) and
// rotate from that point.
v2 pointOfRotation = v2_add(pivotPoint, pos);
mat4 rotateMat = mat4_translate(pointOfRotation.x, pointOfRotation.y, 0.0f);
rotateMat = mat4_mul(rotateMat, mat4_rotate(rotate, 0.0f, 0.0f, 1.0f));
rotateMat = mat4_mul(rotateMat, mat4_translate(-pointOfRotation.x,
-pointOfRotation.y, 0.0f));
for (i32 i = 0; i < vertexListSize; i++)
{
// NOTE(doyle): Manual matrix multiplication since vertex pos is 2D and
// matrix is 4D
v2 oldP = vertexList[i].pos;
v2 newP = {0};
newP.x = (oldP.x * rotateMat.e[0][0]) + (oldP.y * rotateMat.e[1][0]) +
(rotateMat.e[3][0]);
newP.y = (oldP.x * rotateMat.e[0][1]) + (oldP.y * rotateMat.e[1][1]) +
(rotateMat.e[3][1]);
vertexList[i].pos = newP;
}
}
INTERNAL void addVertexToRenderGroup_(Renderer *renderer, Texture *tex,
v4 color, Vertex *vertexList,
v4 color, RenderVertex *vertexList,
i32 numVertexes,
enum RenderMode targetRenderMode,
RenderFlags flags)
@ -208,46 +239,17 @@ INTERNAL inline void flipTexCoord(v4 *texCoords, b32 flipX, b32 flipY)
INTERNAL void bufferRenderGroupToGL(Renderer *renderer, RenderGroup *group)
{
Vertex *vertexList = group->vertexList;
RenderVertex *vertexList = group->vertexList;
i32 numVertex = group->vertexIndex;
// TODO(doyle): We assume that vbo and vao are assigned
renderer->numVertexesInVbo = numVertex;
glBindBuffer(GL_ARRAY_BUFFER, renderer->vbo[group->mode]);
glBufferData(GL_ARRAY_BUFFER, numVertex * sizeof(Vertex), vertexList,
glBufferData(GL_ARRAY_BUFFER, numVertex * sizeof(RenderVertex), vertexList,
GL_STREAM_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
INTERNAL void applyRotationToVertexes(v2 pos, v2 pivotPoint, Radians rotate,
Vertex *vertexList, i32 vertexListSize)
{
if (rotate == 0) return;
// NOTE(doyle): Move the world origin to the base position of the object.
// Then move the origin to the pivot point (e.g. center of object) and
// rotate from that point.
v2 pointOfRotation = v2_add(pivotPoint, pos);
mat4 rotateMat = mat4_translate(pointOfRotation.x, pointOfRotation.y, 0.0f);
rotateMat = mat4_mul(rotateMat, mat4_rotate(rotate, 0.0f, 0.0f, 1.0f));
rotateMat = mat4_mul(rotateMat, mat4_translate(-pointOfRotation.x,
-pointOfRotation.y, 0.0f));
for (i32 i = 0; i < vertexListSize; i++)
{
// NOTE(doyle): Manual matrix multiplication since vertex pos is 2D and
// matrix is 4D
v2 oldP = vertexList[i].pos;
v2 newP = {0};
newP.x = (oldP.x * rotateMat.e[0][0]) + (oldP.y * rotateMat.e[1][0]) +
(rotateMat.e[3][0]);
newP.y = (oldP.x * rotateMat.e[0][1]) + (oldP.y * rotateMat.e[1][1]) +
(rotateMat.e[3][1]);
vertexList[i].pos = newP;
}
}
INTERNAL v4 getTexRectNormaliseDeviceCoords(RenderTex renderTex)
{
/* Convert texture coordinates to normalised texture coordinates */
@ -266,9 +268,9 @@ INTERNAL v4 getTexRectNormaliseDeviceCoords(RenderTex renderTex)
}
INTERNAL RenderQuad_ createRenderQuad(Renderer *renderer, v2 pos, v2 size,
v2 pivotPoint, Radians rotate,
RenderTex renderTex)
INTERNAL RenderQuad createRenderQuad(Renderer *renderer, v2 pos, v2 size,
v2 pivotPoint, Radians rotate,
RenderTex renderTex)
{
/*
* Rendering order
@ -291,33 +293,50 @@ INTERNAL RenderQuad_ createRenderQuad(Renderer *renderer, v2 pos, v2 size,
// NOTE(doyle): Create a quad composed of 4 vertexes to be rendered as
// a triangle strip using vertices v0, v1, v2, then v2, v1, v3 (note the
// order)
RenderQuad_ result = {0};
result.vertex[0].pos = V2(vertexPair.x, vertexPair.w); // Top left
result.vertex[0].texCoord = V2(texRectNdc.x, texRectNdc.w);
v2 vertexList[4] = {0};
v2 texCoordList[4] = {0};
result.vertex[1].pos = V2(vertexPair.x, vertexPair.y); // Bottom left
result.vertex[1].texCoord = V2(texRectNdc.x, texRectNdc.y);
// Top left
vertexList[0] = V2(vertexPair.x, vertexPair.w);
texCoordList[0] = V2(texRectNdc.x, texRectNdc.w);
result.vertex[2].pos = V2(vertexPair.z, vertexPair.w); // Top right
result.vertex[2].texCoord = V2(texRectNdc.z, texRectNdc.w);
// Bottom left
vertexList[1] = V2(vertexPair.x, vertexPair.y);
texCoordList[1] = V2(texRectNdc.x, texRectNdc.y);
result.vertex[3].pos = V2(vertexPair.z, vertexPair.y); // Bottom right
result.vertex[3].texCoord = V2(texRectNdc.z, texRectNdc.y);
// Top right
vertexList[2] = V2(vertexPair.z, vertexPair.w);
texCoordList[2] = V2(texRectNdc.z, texRectNdc.w);
// Bottom right
vertexList[3] = V2(vertexPair.z, vertexPair.y);
texCoordList[3] = V2(texRectNdc.z, texRectNdc.y);
// NOTE(doyle): Precalculate rotation on vertex positions
// NOTE(doyle): No translation/scale matrix as we pre-calculate it from
// entity data and work in world space until GLSL uses the projection matrix
applyRotationToVertexes(pos, pivotPoint, rotate, result.vertex,
ARRAY_COUNT(result.vertex));
math_applyRotationToVertexes(pos, pivotPoint, rotate, vertexList,
ARRAY_COUNT(vertexList));
RenderQuad result = {0};
ASSERT(ARRAY_COUNT(vertexList) == ARRAY_COUNT(result.vertexList));
for (i32 i = 0; i < ARRAY_COUNT(vertexList); i++)
{
result.vertexList[i].pos = vertexList[i];
result.vertexList[i].texCoord = texCoordList[i];
}
return result;
}
INTERNAL inline RenderQuad_
INTERNAL inline RenderQuad
createDefaultTexQuad(Renderer *renderer, RenderTex *renderTex)
{
RenderQuad_ result = {0};
result = createRenderQuad(renderer, V2(0, 0), V2(0, 0), V2(0, 0),
0.0f, *renderTex);
RenderQuad result = {0};
result = createRenderQuad(renderer, V2(0, 0), V2(0, 0), V2(0, 0), 0.0f,
*renderTex);
return result;
}
@ -384,12 +403,13 @@ void renderer_rect(Renderer *const renderer, Rect camera, v2 pos, v2 size,
RenderTex emptyRenderTex = {0};
if (!renderTex) renderTex = &emptyRenderTex;
RenderQuad_ quad = createRenderQuad(renderer, posInCameraSpace, size,
pivotPoint, rotate, *renderTex);
RenderQuad quad = createRenderQuad(renderer, posInCameraSpace, size,
pivotPoint, rotate, *renderTex);
beginVertexBatch(renderer);
addVertexToRenderGroup_(renderer, renderTex->tex, color, quad.vertex,
ARRAY_COUNT(quad.vertex), rendermode_quad, flags);
addVertexToRenderGroup_(renderer, renderTex->tex, color, quad.vertexList,
ARRAY_COUNT(quad.vertexList), rendermode_quad,
flags);
endVertexBatch(renderer);
}
@ -408,7 +428,7 @@ void renderer_polygon(Renderer *const renderer, Rect camera,
if (!renderTex) renderTex = &emptyRenderTex;
v2 triangulationBaseP = polygonPoints[0];
Vertex triangulationBaseVertex = {0};
RenderVertex triangulationBaseVertex = {0};
triangulationBaseVertex.pos = triangulationBaseP;
i32 numTrisInTriangulation = numPoints - 2;
@ -418,13 +438,11 @@ void renderer_polygon(Renderer *const renderer, Rect camera,
{
ASSERT((i + 1) < numPoints);
Vertex triangle[3] = {0};
triangle[0].pos = triangulationBaseP;
triangle[1].pos = polygonPoints[i];
triangle[2].pos = polygonPoints[i + 1];
RenderVertex triangle[3] = {0};
triangle[0].pos = triangulationBaseP;
triangle[1].pos = polygonPoints[i];
triangle[2].pos = polygonPoints[i + 1];
applyRotationToVertexes(triangulationBaseP, pivotPoint, rotate,
triangle, ARRAY_COUNT(triangle));
addVertexToRenderGroup_(renderer, renderTex->tex, color, triangle,
ARRAY_COUNT(triangle), rendermode_polygon,
flags);
@ -453,8 +471,8 @@ void renderer_string(Renderer *const renderer, MemoryArena_ *arena, Rect camera,
i32 vertexIndex = 0;
i32 numVertexPerQuad = 4;
i32 numVertexesToAlloc = (strLen * (numVertexPerQuad + 2));
Vertex *vertexList =
memory_pushBytes(arena, numVertexesToAlloc * sizeof(Vertex));
RenderVertex *vertexList =
memory_pushBytes(arena, numVertexesToAlloc * sizeof(RenderVertex));
v2 posInCameraSpace = v2_sub(pos, camera.min);
pos = posInCameraSpace;
@ -480,13 +498,13 @@ void renderer_string(Renderer *const renderer, MemoryArena_ *arena, Rect camera,
flipTexCoord(&charTexRect, FALSE, TRUE);
RenderTex renderTex = {tex, charTexRect};
RenderQuad_ quad = createRenderQuad(renderer, pos, font->maxSize,
pivotPoint, rotate, renderTex);
RenderQuad quad = createRenderQuad(renderer, pos, font->maxSize,
pivotPoint, rotate, renderTex);
beginVertexBatch(renderer);
addVertexToRenderGroup_(renderer, tex, color, quad.vertex,
ARRAY_COUNT(quad.vertex), rendermode_quad,
flags);
addVertexToRenderGroup_(renderer, tex, color, quad.vertexList,
ARRAY_COUNT(quad.vertexList),
rendermode_quad, flags);
endVertexBatch(renderer);
pos.x += metric.advance;
}
@ -531,24 +549,17 @@ void renderer_entity(Renderer *renderer, MemoryArena_ *transientArena,
if (entity->renderMode == rendermode_quad)
{
renderer_rect(renderer, camera, entity->pos, entity->size, pivotPoint,
totalRotation, &renderTex, color, flags);
renderer_rect(renderer, camera, entity->pos, entity->size,
v2_add(entity->offset, pivotPoint), totalRotation,
&renderTex, color, flags);
}
else if (entity->renderMode == rendermode_polygon)
{
ASSERT(entity->numVertexPoints >= 3);
ASSERT(entity->vertexPoints);
v2 *offsetVertexPoints = memory_pushBytes(
transientArena, entity->numVertexPoints * sizeof(v2));
for (i32 i = 0; i < entity->numVertexPoints; i++)
{
offsetVertexPoints[i] =
v2_add(entity->vertexPoints[i], entity->offset);
offsetVertexPoints[i] = v2_add(offsetVertexPoints[i], entity->pos);
}
v2 *offsetVertexPoints =
entity_createVertexList(transientArena, entity);
renderer_polygon(renderer, camera, offsetVertexPoints,
entity->numVertexPoints,
v2_add(entity->offset, pivotPoint), totalRotation,

View File

@ -6,6 +6,7 @@
#include "Dengine/Renderer.h"
typedef struct AudioRenderer AudioRenderer;
typedef struct MemoryArena_ MemoryArena;
enum Direction
{
@ -66,8 +67,6 @@ typedef struct Entity
f32 scale;
Degrees rotation;
b32 invisible;
enum EntityType type;
enum Direction direction;
@ -95,4 +94,6 @@ void entity_setActiveAnim(Entity *const entity, const char *const animName);
void entity_updateAnim(Entity *const entity, const f32 dt);
void entity_addAnim(AssetManager *const assetManager, Entity *const entity,
const char *const animName);
v2 *entity_createVertexList(MemoryArena_ *transientArena, Entity *entity);
#endif

View File

@ -367,4 +367,37 @@ INTERNAL inline v2 math_getRectSize(v4 rect)
return result;
}
INTERNAL inline void math_applyRotationToVertexes(v2 pos, v2 pivotPoint,
Radians rotate,
v2 *vertexList,
i32 vertexListSize)
{
if (rotate == 0) return;
// NOTE(doyle): Move the world origin to the base position of the object.
// Then move the origin to the pivot point (e.g. center of object) and
// rotate from that point.
v2 pointOfRotation = v2_add(pivotPoint, pos);
mat4 rotateMat = mat4_translate(pointOfRotation.x, pointOfRotation.y, 0.0f);
rotateMat = mat4_mul(rotateMat, mat4_rotate(rotate, 0.0f, 0.0f, 1.0f));
rotateMat = mat4_mul(rotateMat, mat4_translate(-pointOfRotation.x,
-pointOfRotation.y, 0.0f));
// TODO(doyle): Make it nice for 2d vector, stop using mat4
for (i32 i = 0; i < vertexListSize; i++)
{
// NOTE(doyle): Manual matrix multiplication since vertex pos is 2D and
// matrix is 4D
v2 oldP = vertexList[i];
v2 newP = {0};
newP.x = (oldP.x * rotateMat.e[0][0]) + (oldP.y * rotateMat.e[1][0]) +
(rotateMat.e[3][0]);
newP.y = (oldP.x * rotateMat.e[0][1]) + (oldP.y * rotateMat.e[1][1]) +
(rotateMat.e[3][1]);
vertexList[i] = newP;
}
}
#endif

View File

@ -13,11 +13,11 @@ typedef struct MemoryArena MemoryArena_;
typedef struct Shader Shader;
typedef struct Texture Texture;
typedef struct Vertex
typedef struct RenderVertex
{
v2 pos;
v2 texCoord;
} Vertex;
} RenderVertex;
typedef struct RenderTex
{
@ -51,7 +51,7 @@ typedef struct RenderGroup
Texture *tex;
v4 color;
Vertex *vertexList;
RenderVertex *vertexList;
i32 vertexIndex;
} RenderGroup;
@ -82,9 +82,7 @@ typedef struct Renderer
} Renderer;
// TODO(doyle): Use z-index occluding for rendering
RenderTex
renderer_createNullRenderTex(AssetManager *const assetManager);
RenderTex renderer_createNullRenderTex(AssetManager *const assetManager);
// TODO(doyle): Clean up lines
// Renderer::~Renderer() { glDeleteVertexArrays(1, &this->quadVAO); }