Add arbitrary asteroid polygon rendering
This commit is contained in:
parent
b75d700dd6
commit
e49984b3d0
Binary file not shown.
203
src/Asteroid.c
203
src/Asteroid.c
@ -163,10 +163,146 @@ INTERNAL b32 getKeyStatus(KeyState *key, enum ReadKeyType readType,
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct Basis
|
||||||
|
{
|
||||||
|
v2 basis;
|
||||||
|
v2 pivotPoint;
|
||||||
|
} Basis;
|
||||||
|
|
||||||
|
enum RectBaseline
|
||||||
|
{
|
||||||
|
rectbaseline_top,
|
||||||
|
rectbaseline_topLeft,
|
||||||
|
rectbaseline_topRight,
|
||||||
|
rectbaseline_bottom,
|
||||||
|
rectbaseline_bottomRight,
|
||||||
|
rectbaseline_bottomLeft,
|
||||||
|
rectbaseline_left,
|
||||||
|
rectbaseline_right,
|
||||||
|
rectbaseline_center,
|
||||||
|
rectbaseline_count,
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
Basis getBasis(Entity *entity, enum RectBaseline baseline)
|
||||||
|
{
|
||||||
|
ASSERT(baseline < rectbaseline_count);
|
||||||
|
|
||||||
|
v2 basis = v2_sub(entity->pos, entity->offset);
|
||||||
|
v2 pivotPoint = v2_scale(entity->size, 0.5f);
|
||||||
|
v2 size = entity->size;
|
||||||
|
switch (baseline)
|
||||||
|
{
|
||||||
|
case rectbaseline_top:
|
||||||
|
basis.y += (size.h);
|
||||||
|
basis.x += (size.w * 0.5f);
|
||||||
|
break;
|
||||||
|
case rectbaseline_topLeft:
|
||||||
|
basis.y += (size.h);
|
||||||
|
break;
|
||||||
|
case rectbaseline_topRight:
|
||||||
|
basis.y += (size.h);
|
||||||
|
basis.x += (size.w);
|
||||||
|
break;
|
||||||
|
case rectbaseline_bottom:
|
||||||
|
basis.x += (size.w * 0.5f);
|
||||||
|
break;
|
||||||
|
case rectbaseline_bottomRight:
|
||||||
|
basis.x += (size.w);
|
||||||
|
break;
|
||||||
|
case rectbaseline_left:
|
||||||
|
basis.y += (size.h * 0.5f);
|
||||||
|
break;
|
||||||
|
case rectbaseline_right:
|
||||||
|
basis.x += (size.w);
|
||||||
|
basis.y += (size.h * 0.5f);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case rectbaseline_bottomLeft:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
DEBUG_LOG(
|
||||||
|
"getPosRelativeToRect() warning: baseline enum not recognised");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Basis result = {0};
|
||||||
|
result.basis = basis;
|
||||||
|
result.pivotPoint = pivotPoint;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Basis getDefaultBasis(Entity *entity)
|
||||||
|
{
|
||||||
|
Basis result = getBasis(entity, rectbaseline_bottomLeft);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <time.h>
|
||||||
|
v2 *createAsteroidVertexList(MemoryArena_ *arena, v2 pos, i32 iterations)
|
||||||
|
{
|
||||||
|
f32 iterationAngle = 360.0f / iterations;
|
||||||
|
iterationAngle = DEGREES_TO_RADIANS(iterationAngle);
|
||||||
|
v2 *result =
|
||||||
|
memory_pushBytes(arena, iterations * sizeof(v2));
|
||||||
|
|
||||||
|
srand(time(NULL));
|
||||||
|
for (i32 i = 0; i < iterations; i++)
|
||||||
|
{
|
||||||
|
i32 randValue = rand();
|
||||||
|
i32 asteroidRadius = (randValue % 100) + 50;
|
||||||
|
|
||||||
|
result[i] = V2(math_cosf(iterationAngle * i) * asteroidRadius,
|
||||||
|
math_sinf(iterationAngle * i) * asteroidRadius);
|
||||||
|
result[i] = v2_add(result[i], pos);
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
f32 displacementDist = 0.25f * asteroidRadius;
|
||||||
|
i32 vertexDisplacement =
|
||||||
|
randValue % (i32)displacementDist + (i32)(displacementDist * 0.1f);
|
||||||
|
|
||||||
|
i32 quadrantSize = iterations / 4;
|
||||||
|
|
||||||
|
i32 firstQuadrant = quadrantSize;
|
||||||
|
i32 secondQuadrant = quadrantSize * 2;
|
||||||
|
i32 thirdQuadrant = quadrantSize * 3;
|
||||||
|
i32 fourthQuadrant = quadrantSize * 4;
|
||||||
|
|
||||||
|
if (i < firstQuadrant)
|
||||||
|
{
|
||||||
|
result[i].x += vertexDisplacement;
|
||||||
|
result[i].y += vertexDisplacement;
|
||||||
|
}
|
||||||
|
else if (i < secondQuadrant)
|
||||||
|
{
|
||||||
|
result[i].x -= vertexDisplacement;
|
||||||
|
result[i].y += vertexDisplacement;
|
||||||
|
}
|
||||||
|
else if (i < thirdQuadrant)
|
||||||
|
{
|
||||||
|
result[i].x -= vertexDisplacement;
|
||||||
|
result[i].y -= vertexDisplacement;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result[i].x += vertexDisplacement;
|
||||||
|
result[i].y -= vertexDisplacement;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOCAL_PERSIST v2 *asteroidVertexList = NULL;
|
||||||
|
LOCAL_PERSIST f32 updateAsteroidListTimerThreshold = 1.0f;
|
||||||
|
LOCAL_PERSIST f32 updateAsteroidListTimer = 1.0f;
|
||||||
void asteroid_gameUpdateAndRender(GameState *state, Memory *memory,
|
void asteroid_gameUpdateAndRender(GameState *state, Memory *memory,
|
||||||
v2 windowSize, f32 dt)
|
v2 windowSize, f32 dt)
|
||||||
{
|
{
|
||||||
|
i32 iterations = 16;
|
||||||
if (!state->init)
|
if (!state->init)
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -200,11 +336,22 @@ void asteroid_gameUpdateAndRender(GameState *state, Memory *memory,
|
|||||||
|
|
||||||
debug_init(&state->persistentArena, windowSize,
|
debug_init(&state->persistentArena, windowSize,
|
||||||
state->assetManager.font);
|
state->assetManager.font);
|
||||||
|
|
||||||
|
asteroidVertexList =
|
||||||
|
createAsteroidVertexList(&state->persistentArena, V2(500, 500), 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
memory_arenaInit(&state->transientArena, memory->transient,
|
memory_arenaInit(&state->transientArena, memory->transient,
|
||||||
memory->transientSize);
|
memory->transientSize);
|
||||||
|
|
||||||
|
updateAsteroidListTimer -= dt;
|
||||||
|
if (updateAsteroidListTimer < 0)
|
||||||
|
{
|
||||||
|
asteroidVertexList = createAsteroidVertexList(&state->persistentArena,
|
||||||
|
V2(500, 500), iterations);
|
||||||
|
updateAsteroidListTimer = updateAsteroidListTimerThreshold;
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
KeyState *keys = state->input.keys;
|
KeyState *keys = state->input.keys;
|
||||||
for (enum KeyCode code = 0; code < keycode_count; code++)
|
for (enum KeyCode code = 0; code < keycode_count; code++)
|
||||||
@ -236,8 +383,20 @@ void asteroid_gameUpdateAndRender(GameState *state, Memory *memory,
|
|||||||
ASSERT(entity->type != entitytype_invalid);
|
ASSERT(entity->type != entitytype_invalid);
|
||||||
|
|
||||||
v2 pivotPoint = {0};
|
v2 pivotPoint = {0};
|
||||||
if (entity->type == entitytype_ship) {
|
|
||||||
|
|
||||||
|
// Loop entity around world
|
||||||
|
if (entity->pos.y >= state->worldSize.h)
|
||||||
|
entity->pos.y = 0;
|
||||||
|
else if (entity->pos.y < 0)
|
||||||
|
entity->pos.y = state->worldSize.h;
|
||||||
|
|
||||||
|
if (entity->pos.x >= state->worldSize.w)
|
||||||
|
entity->pos.x = 0;
|
||||||
|
else if (entity->pos.x < 0)
|
||||||
|
entity->pos.x = state->worldSize.w;
|
||||||
|
|
||||||
|
if (entity->type == entitytype_ship)
|
||||||
|
{
|
||||||
v2 ddP = {0};
|
v2 ddP = {0};
|
||||||
if (getKeyStatus(&state->input.keys[keycode_up], readkeytype_repeat,
|
if (getKeyStatus(&state->input.keys[keycode_up], readkeytype_repeat,
|
||||||
0.0f, dt))
|
0.0f, dt))
|
||||||
@ -245,7 +404,9 @@ void asteroid_gameUpdateAndRender(GameState *state, Memory *memory,
|
|||||||
// TODO(doyle): Renderer creates upfacing triangles by default,
|
// TODO(doyle): Renderer creates upfacing triangles by default,
|
||||||
// but we need to offset rotation so that our base "0 degrees"
|
// but we need to offset rotation so that our base "0 degrees"
|
||||||
// is right facing for trig to work
|
// is right facing for trig to work
|
||||||
Radians rotation = DEGREES_TO_RADIANS((entity->rotation + 90.0f));
|
Radians rotation =
|
||||||
|
DEGREES_TO_RADIANS((entity->rotation + 90.0f));
|
||||||
|
|
||||||
v2 direction = V2(math_cosf(rotation), math_sinf(rotation));
|
v2 direction = V2(math_cosf(rotation), math_sinf(rotation));
|
||||||
ddP = direction;
|
ddP = direction;
|
||||||
}
|
}
|
||||||
@ -293,25 +454,6 @@ void asteroid_gameUpdateAndRender(GameState *state, Memory *memory,
|
|||||||
entity->pos = v2_add(v2_add(ddPHalfDtSquared, oldDpDt), oldPos);
|
entity->pos = v2_add(v2_add(ddPHalfDtSquared, oldDpDt), oldPos);
|
||||||
|
|
||||||
pivotPoint = v2_scale(entity->size, 0.5f);
|
pivotPoint = v2_scale(entity->size, 0.5f);
|
||||||
}
|
|
||||||
|
|
||||||
if (entity->pos.y >= state->worldSize.h)
|
|
||||||
{
|
|
||||||
entity->pos.y = 0;
|
|
||||||
}
|
|
||||||
else if (entity->pos.y < 0)
|
|
||||||
{
|
|
||||||
entity->pos.y = state->worldSize.h;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (entity->pos.x >= state->worldSize.w)
|
|
||||||
{
|
|
||||||
entity->pos.x = 0;
|
|
||||||
}
|
|
||||||
else if (entity->pos.x < 0)
|
|
||||||
{
|
|
||||||
entity->pos.x = state->worldSize.w;
|
|
||||||
}
|
|
||||||
|
|
||||||
DEBUG_PUSH_VAR("Pos: %5.2f, %5.2f", entity->pos, "v2");
|
DEBUG_PUSH_VAR("Pos: %5.2f, %5.2f", entity->pos, "v2");
|
||||||
DEBUG_PUSH_VAR("Velocity: %5.2f, %5.2f", entity->dP, "v2");
|
DEBUG_PUSH_VAR("Velocity: %5.2f, %5.2f", entity->dP, "v2");
|
||||||
@ -321,18 +463,17 @@ void asteroid_gameUpdateAndRender(GameState *state, Memory *memory,
|
|||||||
renderer_entity(&state->renderer, state->camera, entity, pivotPoint, 0,
|
renderer_entity(&state->renderer, state->camera, entity, pivotPoint, 0,
|
||||||
V4(0.4f, 0.8f, 1.0f, 1.0f), flags);
|
V4(0.4f, 0.8f, 1.0f, 1.0f), flags);
|
||||||
|
|
||||||
v2 leftAlignedP = v2_sub(entity->pos, entity->offset);
|
Basis entityBasis = getDefaultBasis(entity);
|
||||||
renderer_rect(&state->renderer, state->camera, leftAlignedP,
|
renderer_rect(&state->renderer, state->camera, entityBasis.basis,
|
||||||
entity->size, v2_scale(entity->size, 0.5f),
|
V2(4, 4), entityBasis.pivotPoint,
|
||||||
DEGREES_TO_RADIANS(entity->rotation), NULL,
|
DEGREES_TO_RADIANS(entity->rotation), NULL,
|
||||||
V4(1.0f, 0.8f, 1.0f, 1.0f), flags);
|
V4(1.0f, 0, 0, 1.0f), flags);
|
||||||
|
|
||||||
v2 rightAlignedP = v2_add(leftAlignedP, entity->size);
|
|
||||||
renderer_rect(&state->renderer, state->camera, rightAlignedP, V2(4, 4),
|
|
||||||
v2_scale(pivotPoint, -1.0f),
|
|
||||||
DEGREES_TO_RADIANS(entity->rotation), NULL,
|
|
||||||
V4(0.4f, 0.8f, 1.0f, 1.0f), flags);
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
renderer_polygon(&state->renderer, &state->transientArena, state->camera,
|
||||||
|
asteroidVertexList, iterations, V2(0, 0), 0, NULL,
|
||||||
|
V4(0.0f, 0.0f, 1.0f, 1.0f), 0);
|
||||||
|
|
||||||
TrianglePoints triangle = {0};
|
TrianglePoints triangle = {0};
|
||||||
triangle.points[0] = V2(100, 200);
|
triangle.points[0] = V2(100, 200);
|
||||||
|
@ -376,6 +376,52 @@ void renderer_rect(Renderer *const renderer, Rect camera, v2 pos, v2 size,
|
|||||||
ARRAY_COUNT(vertexList), rendermode_quad, flags);
|
ARRAY_COUNT(vertexList), rendermode_quad, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void renderer_polygon(Renderer *const renderer, MemoryArena_ *arena, Rect camera,
|
||||||
|
v2 *polygonPoints, i32 numPoints, v2 pivotPoint,
|
||||||
|
Radians rotate, RenderTex *renderTex, v4 color,
|
||||||
|
RenderFlags flags)
|
||||||
|
{
|
||||||
|
ASSERT(numPoints > 3);
|
||||||
|
|
||||||
|
for (i32 i = 0; i < numPoints; i++)
|
||||||
|
polygonPoints[i] = v2_sub(polygonPoints[i], camera.min);
|
||||||
|
|
||||||
|
RenderTex emptyRenderTex = {0};
|
||||||
|
if (!renderTex) renderTex = &emptyRenderTex;
|
||||||
|
|
||||||
|
i32 numTrisInTriangulation = numPoints - 2;
|
||||||
|
RenderTriangle_ *polygonTriangulation = memory_pushBytes(
|
||||||
|
arena, (sizeof(RenderTriangle_) * numTrisInTriangulation));
|
||||||
|
|
||||||
|
v2 triangulationBaseP = polygonPoints[0];
|
||||||
|
i32 triangulationIndex = 0;
|
||||||
|
|
||||||
|
Vertex triangulationBaseVertex = {0};
|
||||||
|
triangulationBaseVertex.pos = triangulationBaseP;
|
||||||
|
|
||||||
|
addVertexToRenderGroup(renderer, renderTex->tex, color,
|
||||||
|
&triangulationBaseVertex, 1, rendermode_polygon,
|
||||||
|
flags);
|
||||||
|
for (i32 i = 1; triangulationIndex < numTrisInTriangulation; i++)
|
||||||
|
{
|
||||||
|
RenderTriangle_ *tri = &polygonTriangulation[triangulationIndex++];
|
||||||
|
tri->vertex[0].pos = triangulationBaseP;
|
||||||
|
tri->vertex[1].pos = polygonPoints[i + 1];
|
||||||
|
tri->vertex[2].pos = polygonPoints[i];
|
||||||
|
|
||||||
|
addVertexToRenderGroup(renderer, renderTex->tex, color, tri->vertex, 3,
|
||||||
|
rendermode_polygon, flags);
|
||||||
|
}
|
||||||
|
RenderTriangle_ tri = polygonTriangulation[numTrisInTriangulation-1];
|
||||||
|
addVertexToRenderGroup(renderer, renderTex->tex, color, &tri.vertex[2], 1,
|
||||||
|
rendermode_polygon, flags);
|
||||||
|
/*
|
||||||
|
// NOTE(doyle): Create degenerate vertex setup
|
||||||
|
Vertex triVertexList[5] = {tri->vertex[0], tri->vertex[0], tri->vertex[1],
|
||||||
|
tri->vertex[2], tri->vertex[2]};
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
void renderer_triangle(Renderer *const renderer, Rect camera,
|
void renderer_triangle(Renderer *const renderer, Rect camera,
|
||||||
TrianglePoints triangle, v2 pivotPoint, Radians rotate,
|
TrianglePoints triangle, v2 pivotPoint, Radians rotate,
|
||||||
RenderTex *renderTex, v4 color, RenderFlags flags)
|
RenderTex *renderTex, v4 color, RenderFlags flags)
|
||||||
@ -472,6 +518,7 @@ void renderer_string(Renderer *const renderer, MemoryArena_ *arena, Rect camera,
|
|||||||
void renderer_entity(Renderer *renderer, Rect camera, Entity *entity,
|
void renderer_entity(Renderer *renderer, Rect camera, Entity *entity,
|
||||||
v2 pivotPoint, Degrees rotate, v4 color, RenderFlags flags)
|
v2 pivotPoint, Degrees rotate, v4 color, RenderFlags flags)
|
||||||
{
|
{
|
||||||
|
// TODO(doyle): Add early exit on entities out of camera bounds
|
||||||
Radians totalRotation = DEGREES_TO_RADIANS((entity->rotation + rotate));
|
Radians totalRotation = DEGREES_TO_RADIANS((entity->rotation + rotate));
|
||||||
RenderTex renderTex = {0};
|
RenderTex renderTex = {0};
|
||||||
if (entity->tex)
|
if (entity->tex)
|
||||||
|
@ -35,10 +35,14 @@ enum RenderFlag {
|
|||||||
renderflag_no_texture = 0x2,
|
renderflag_no_texture = 0x2,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// TODO(doyle): Since all vertexes are built with degenerate vertices and
|
||||||
|
// in a triangle strip format, we should not split render groups by render mode
|
||||||
|
// nor either generate buffers vao/vbo based on rendermode count
|
||||||
enum RenderMode
|
enum RenderMode
|
||||||
{
|
{
|
||||||
rendermode_quad,
|
rendermode_quad,
|
||||||
rendermode_triangle,
|
rendermode_triangle,
|
||||||
|
rendermode_polygon,
|
||||||
rendermode_count,
|
rendermode_count,
|
||||||
rendermode_invalid,
|
rendermode_invalid,
|
||||||
};
|
};
|
||||||
@ -48,7 +52,6 @@ typedef struct RenderGroup
|
|||||||
b32 init;
|
b32 init;
|
||||||
RenderFlags flags;
|
RenderFlags flags;
|
||||||
enum RenderMode mode;
|
enum RenderMode mode;
|
||||||
u32 glRenderMode;
|
|
||||||
|
|
||||||
Texture *tex;
|
Texture *tex;
|
||||||
v4 color;
|
v4 color;
|
||||||
@ -82,12 +85,18 @@ renderer_createNullRenderTex(AssetManager *const assetManager);
|
|||||||
// TODO(doyle): Clean up lines
|
// TODO(doyle): Clean up lines
|
||||||
// Renderer::~Renderer() { glDeleteVertexArrays(1, &this->quadVAO); }
|
// Renderer::~Renderer() { glDeleteVertexArrays(1, &this->quadVAO); }
|
||||||
void renderer_rect(Renderer *const renderer, Rect camera, v2 pos, v2 size,
|
void renderer_rect(Renderer *const renderer, Rect camera, v2 pos, v2 size,
|
||||||
v2 pivotPoint, Radians rotate, RenderTex *renderTex, v4 color,
|
v2 pivotPoint, Radians rotate, RenderTex *renderTex,
|
||||||
RenderFlags flags);
|
v4 color, RenderFlags flags);
|
||||||
|
|
||||||
|
void renderer_polygon(Renderer *const renderer, MemoryArena_ *arena,
|
||||||
|
Rect camera, v2 *polygonPoints, i32 numPoints,
|
||||||
|
v2 pivotPoint, Radians rotate, RenderTex *renderTex,
|
||||||
|
v4 color, RenderFlags flags);
|
||||||
|
|
||||||
inline void renderer_staticRect(Renderer *const renderer, v2 pos, v2 size,
|
inline void renderer_staticRect(Renderer *const renderer, v2 pos, v2 size,
|
||||||
v2 pivotPoint, Radians rotate, RenderTex *renderTex,
|
v2 pivotPoint, Radians rotate,
|
||||||
v4 color, RenderFlags flags)
|
RenderTex *renderTex, v4 color,
|
||||||
|
RenderFlags flags)
|
||||||
{
|
{
|
||||||
Rect staticCamera = {V2(0, 0), renderer->size};
|
Rect staticCamera = {V2(0, 0), renderer->size};
|
||||||
renderer_rect(renderer, staticCamera, pos, size, pivotPoint, rotate,
|
renderer_rect(renderer, staticCamera, pos, size, pivotPoint, rotate,
|
||||||
@ -98,15 +107,15 @@ void renderer_triangle(Renderer *const renderer, Rect camera,
|
|||||||
TrianglePoints triangle, v2 pivotPoint, Radians rotate,
|
TrianglePoints triangle, v2 pivotPoint, Radians rotate,
|
||||||
RenderTex *renderTex, v4 color, RenderFlags flags);
|
RenderTex *renderTex, v4 color, RenderFlags flags);
|
||||||
|
|
||||||
void renderer_string(Renderer *const renderer, MemoryArena_ *arena,
|
void renderer_string(Renderer *const renderer, MemoryArena_ *arena, Rect camera,
|
||||||
Rect camera, Font *const font,
|
Font *const font, const char *const string, v2 pos,
|
||||||
const char *const string, v2 pos, v2 pivotPoint,
|
v2 pivotPoint, Radians rotate, v4 color,
|
||||||
Radians rotate, v4 color, RenderFlags flags);
|
RenderFlags flags);
|
||||||
|
|
||||||
inline void renderer_staticString(Renderer *const renderer, MemoryArena_ *arena,
|
inline void renderer_staticString(Renderer *const renderer, MemoryArena_ *arena,
|
||||||
Font *const font, const char *const string,
|
Font *const font, const char *const string,
|
||||||
v2 pos, v2 pivotPoint, Radians rotate, v4 color,
|
v2 pos, v2 pivotPoint, Radians rotate,
|
||||||
RenderFlags flags)
|
v4 color, RenderFlags flags)
|
||||||
{
|
{
|
||||||
Rect staticCamera = {V2(0, 0), renderer->size};
|
Rect staticCamera = {V2(0, 0), renderer->size};
|
||||||
renderer_string(renderer, arena, staticCamera, font, string, pos,
|
renderer_string(renderer, arena, staticCamera, font, string, pos,
|
||||||
|
Loading…
Reference in New Issue
Block a user