Add arbitrary asteroid polygon rendering
This commit is contained in:
		
							parent
							
								
									b75d700dd6
								
							
						
					
					
						commit
						e49984b3d0
					
				
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										225
									
								
								src/Asteroid.c
									
									
									
									
									
								
							
							
						
						
									
										225
									
								
								src/Asteroid.c
									
									
									
									
									
								
							| @ -163,10 +163,146 @@ INTERNAL b32 getKeyStatus(KeyState *key, enum ReadKeyType readType, | ||||
| 	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, | ||||
|                                   v2 windowSize, f32 dt) | ||||
| { | ||||
| 	i32 iterations = 16; | ||||
| 	if (!state->init) | ||||
| 	{ | ||||
| 
 | ||||
| @ -200,11 +336,22 @@ void asteroid_gameUpdateAndRender(GameState *state, Memory *memory, | ||||
| 
 | ||||
| 		debug_init(&state->persistentArena, windowSize, | ||||
| 		           state->assetManager.font); | ||||
| 
 | ||||
| 		asteroidVertexList = | ||||
| 		    createAsteroidVertexList(&state->persistentArena, V2(500, 500), 16); | ||||
| 	} | ||||
| 
 | ||||
| 	memory_arenaInit(&state->transientArena, memory->transient, | ||||
| 	                 memory->transientSize); | ||||
| 
 | ||||
| 	updateAsteroidListTimer -= dt; | ||||
| 	if (updateAsteroidListTimer < 0) | ||||
| 	{ | ||||
| 		asteroidVertexList = createAsteroidVertexList(&state->persistentArena, | ||||
| 		                                              V2(500, 500), iterations); | ||||
| 		updateAsteroidListTimer = updateAsteroidListTimerThreshold; | ||||
| 	} | ||||
| 
 | ||||
| 	{ | ||||
| 		KeyState *keys = state->input.keys; | ||||
| 		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); | ||||
| 
 | ||||
| 		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}; | ||||
| 			if (getKeyStatus(&state->input.keys[keycode_up], readkeytype_repeat, | ||||
| 			                 0.0f, dt)) | ||||
| @ -245,9 +404,11 @@ void asteroid_gameUpdateAndRender(GameState *state, Memory *memory, | ||||
| 				// TODO(doyle): Renderer creates upfacing triangles by default,
 | ||||
| 				// but we need to offset rotation so that our base "0 degrees"
 | ||||
| 				// is right facing for trig to work
 | ||||
| 				Radians rotation = DEGREES_TO_RADIANS((entity->rotation + 90.0f)); | ||||
| 				v2 direction     = V2(math_cosf(rotation), math_sinf(rotation)); | ||||
| 				ddP = direction; | ||||
| 				Radians rotation = | ||||
| 				    DEGREES_TO_RADIANS((entity->rotation + 90.0f)); | ||||
| 
 | ||||
| 				v2 direction = V2(math_cosf(rotation), math_sinf(rotation)); | ||||
| 				ddP          = direction; | ||||
| 			} | ||||
| 
 | ||||
| 			if (getKeyStatus(&state->input.keys[keycode_left], | ||||
| @ -293,47 +454,27 @@ void asteroid_gameUpdateAndRender(GameState *state, Memory *memory, | ||||
| 			entity->pos = v2_add(v2_add(ddPHalfDtSquared, oldDpDt), oldPos); | ||||
| 
 | ||||
| 			pivotPoint = v2_scale(entity->size, 0.5f); | ||||
| 
 | ||||
| 			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("Rotation: %5.2f", entity->rotation, "f32"); | ||||
| 
 | ||||
| 			RenderFlags flags = renderflag_wireframe | renderflag_no_texture; | ||||
| 			renderer_entity(&state->renderer, state->camera, entity, pivotPoint, 0, | ||||
| 					V4(0.4f, 0.8f, 1.0f, 1.0f), flags); | ||||
| 
 | ||||
| 			Basis entityBasis = getDefaultBasis(entity); | ||||
| 			renderer_rect(&state->renderer, state->camera, entityBasis.basis, | ||||
| 					V2(4, 4), entityBasis.pivotPoint, | ||||
| 					DEGREES_TO_RADIANS(entity->rotation), NULL, | ||||
| 					V4(1.0f, 0, 0, 1.0f), flags); | ||||
| 		} | ||||
| 
 | ||||
| 		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("Velocity: %5.2f, %5.2f", entity->dP, "v2"); | ||||
| 		DEBUG_PUSH_VAR("Rotation: %5.2f", entity->rotation, "f32"); | ||||
| 
 | ||||
| 		RenderFlags flags = renderflag_wireframe | renderflag_no_texture; | ||||
| 		renderer_entity(&state->renderer, state->camera, entity, pivotPoint, 0, | ||||
| 		                 V4(0.4f, 0.8f, 1.0f, 1.0f), flags); | ||||
| 
 | ||||
| 		v2 leftAlignedP = v2_sub(entity->pos, entity->offset); | ||||
| 		renderer_rect(&state->renderer, state->camera, leftAlignedP, | ||||
| 		              entity->size, v2_scale(entity->size, 0.5f), | ||||
| 		              DEGREES_TO_RADIANS(entity->rotation), NULL, | ||||
| 		              V4(1.0f, 0.8f, 1.0f, 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}; | ||||
| 	triangle.points[0] = V2(100, 200); | ||||
| 	triangle.points[1] = V2(200, 100); | ||||
|  | ||||
| @ -376,6 +376,52 @@ void renderer_rect(Renderer *const renderer, Rect camera, v2 pos, v2 size, | ||||
| 		                       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, | ||||
|                        TrianglePoints triangle, v2 pivotPoint, Radians rotate, | ||||
|                        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, | ||||
|                      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)); | ||||
| 	RenderTex renderTex   = {0}; | ||||
| 	if (entity->tex) | ||||
|  | ||||
| @ -35,10 +35,14 @@ enum RenderFlag { | ||||
| 	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 | ||||
| { | ||||
| 	rendermode_quad, | ||||
| 	rendermode_triangle, | ||||
| 	rendermode_polygon, | ||||
| 	rendermode_count, | ||||
| 	rendermode_invalid, | ||||
| }; | ||||
| @ -48,7 +52,6 @@ typedef struct RenderGroup | ||||
| 	b32 init; | ||||
| 	RenderFlags flags; | ||||
| 	enum RenderMode mode; | ||||
| 	u32 glRenderMode; | ||||
| 
 | ||||
| 	Texture *tex; | ||||
| 	v4 color; | ||||
| @ -82,12 +85,18 @@ renderer_createNullRenderTex(AssetManager *const assetManager); | ||||
| // TODO(doyle): Clean up lines
 | ||||
| // Renderer::~Renderer() { glDeleteVertexArrays(1, &this->quadVAO); }
 | ||||
| void renderer_rect(Renderer *const renderer, Rect camera, v2 pos, v2 size, | ||||
|                    v2 pivotPoint, Radians rotate, RenderTex *renderTex, v4 color, | ||||
|                    RenderFlags flags); | ||||
|                    v2 pivotPoint, Radians rotate, RenderTex *renderTex, | ||||
|                    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, | ||||
|                                 v2 pivotPoint, Radians rotate, RenderTex *renderTex, | ||||
|                                 v4 color, RenderFlags flags) | ||||
|                                 v2 pivotPoint, Radians rotate, | ||||
|                                 RenderTex *renderTex, v4 color, | ||||
|                                 RenderFlags flags) | ||||
| { | ||||
| 	Rect staticCamera = {V2(0, 0), renderer->size}; | ||||
| 	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, | ||||
|                        RenderTex *renderTex, v4 color, RenderFlags flags); | ||||
| 
 | ||||
| void renderer_string(Renderer *const renderer, MemoryArena_ *arena, | ||||
|                      Rect camera, Font *const font, | ||||
|                      const char *const string, v2 pos, v2 pivotPoint, | ||||
|                      Radians rotate, v4 color, RenderFlags flags); | ||||
| void renderer_string(Renderer *const renderer, MemoryArena_ *arena, Rect camera, | ||||
|                      Font *const font, const char *const string, v2 pos, | ||||
|                      v2 pivotPoint, Radians rotate, v4 color, | ||||
|                      RenderFlags flags); | ||||
| 
 | ||||
| inline void renderer_staticString(Renderer *const renderer, MemoryArena_ *arena, | ||||
|                                   Font *const font, const char *const string, | ||||
|                                   v2 pos, v2 pivotPoint, Radians rotate, v4 color, | ||||
|                                   RenderFlags flags) | ||||
|                                   v2 pos, v2 pivotPoint, Radians rotate, | ||||
|                                   v4 color, RenderFlags flags) | ||||
| { | ||||
| 	Rect staticCamera = {V2(0, 0), renderer->size}; | ||||
| 	renderer_string(renderer, arena, staticCamera, font, string, pos, | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user