Fix incorrect indexing into vertex array for model

Wavefront model obj format indexes starting from 1, offset during load by -1 to
make all indexes be 0 based.
This commit is contained in:
Doyle Thai 2017-05-22 20:54:34 +10:00
parent 2c745d3571
commit 237e73253a
3 changed files with 106 additions and 24 deletions

View File

@ -71,9 +71,9 @@ FILE_SCOPE bool ObjWaveFrontInit(WavefrontObj *const obj, const i32 vertexInitCa
} }
FILE_SCOPE bool ObjWavefrontLoad(const PlatformAPI api, PlatformMemory *const memory, FILE_SCOPE bool ObjWavefrontLoad(const PlatformAPI api, PlatformMemory *const memory,
const char *const path) const char *const path, WavefrontObj *const obj)
{ {
if (!memory || ! path) return false; if (!memory || !path || !obj) return false;
PlatformFile file = {}; PlatformFile file = {};
if (!api.FileOpen(path, &file, PlatformFilePermissionFlag_Read)) if (!api.FileOpen(path, &file, PlatformFilePermissionFlag_Read))
@ -98,8 +98,7 @@ FILE_SCOPE bool ObjWavefrontLoad(const PlatformAPI api, PlatformMemory *const me
WavefrontVertexType_Normal, WavefrontVertexType_Normal,
}; };
WavefrontObj obj = {}; if (!ObjWaveFrontInit(obj))
if (!ObjWaveFrontInit(&obj))
{ {
DqnMemStack_EndTempRegion(tmpMemRegion); DqnMemStack_EndTempRegion(tmpMemRegion);
return false; return false;
@ -160,15 +159,15 @@ FILE_SCOPE bool ObjWavefrontLoad(const PlatformAPI api, PlatformMemory *const me
DQN_ASSERT(vIndex == 3 || vIndex == 4); DQN_ASSERT(vIndex == 3 || vIndex == 4);
if (type == WavefrontVertexType_Geometric) if (type == WavefrontVertexType_Geometric)
{ {
DqnArray_Push(&obj.geometryArray, v4); DqnArray_Push(&obj->geometryArray, v4);
} }
else if (type == WavefrontVertexType_Texture) else if (type == WavefrontVertexType_Texture)
{ {
DqnArray_Push(&obj.texUVArray, v4.xyz); DqnArray_Push(&obj->texUVArray, v4.xyz);
} }
else if (type == WavefrontVertexType_Normal) else if (type == WavefrontVertexType_Normal)
{ {
DqnArray_Push(&obj.normalArray, v4.xyz); DqnArray_Push(&obj->normalArray, v4.xyz);
} }
else else
{ {
@ -239,7 +238,9 @@ FILE_SCOPE bool ObjWavefrontLoad(const PlatformAPI api, PlatformMemory *const me
i32 numLen = (i32)((size_t)scan - (size_t)numStartPtr); i32 numLen = (i32)((size_t)scan - (size_t)numStartPtr);
if (numLen > 0) if (numLen > 0)
{ {
i32 index = (i32)Dqn_StrToI64(numStartPtr, numLen); // NOTE(doyle): Obj format starts indexing from 1,
// so offset by -1 to make it zero-based indexes.
i32 index = (i32)Dqn_StrToI64(numStartPtr, numLen) - 1;
if (type == WavefrontVertexType_Geometric) if (type == WavefrontVertexType_Geometric)
{ {
@ -274,13 +275,13 @@ FILE_SCOPE bool ObjWavefrontLoad(const PlatformAPI api, PlatformMemory *const me
} }
} }
if (obj.model.faces.count == 7470 || obj.model.faces.count == 2491) if (obj->model.faces.count == 7470 || obj->model.faces.count == 2491)
{ {
int x = 5; int x = 5;
} }
} }
DQN_ASSERT(numVertexesParsed >= 3); DQN_ASSERT(numVertexesParsed >= 3);
DQN_ASSERT(DqnArray_Push(&obj.model.faces, face)); DQN_ASSERT(DqnArray_Push(&obj->model.faces, face));
} }
break; break;
@ -307,14 +308,14 @@ FILE_SCOPE bool ObjWavefrontLoad(const PlatformAPI api, PlatformMemory *const me
if (scan) if (scan)
{ {
i32 nameLen = (i32)((size_t)scan - (size_t)namePtr); i32 nameLen = (i32)((size_t)scan - (size_t)namePtr);
DQN_ASSERT(obj.model.groupNameIndex + 1 < DQN_ARRAY_COUNT(obj.model.groupName)); DQN_ASSERT(obj->model.groupNameIndex + 1 < DQN_ARRAY_COUNT(obj->model.groupName));
DQN_ASSERT(!obj.model.groupName[obj.model.groupNameIndex]); DQN_ASSERT(!obj->model.groupName[obj->model.groupNameIndex]);
obj.model.groupName[obj.model.groupNameIndex++] = (char *)DqnMemStack_Allocate( obj->model.groupName[obj->model.groupNameIndex++] = (char *)DqnMemStack_Allocate(
&memory->permMemStack, (nameLen + 1) * sizeof(char)); &memory->permMemStack, (nameLen + 1) * sizeof(char));
for (i32 i = 0; i < nameLen; i++) for (i32 i = 0; i < nameLen; i++)
obj.model.groupName[obj.model.groupNameIndex - 1][i] = namePtr[i]; obj->model.groupName[obj->model.groupNameIndex - 1][i] = namePtr[i];
while (scan && (*scan == ' ' || *scan == '\n')) while (scan && (*scan == ' ' || *scan == '\n'))
scan++; scan++;
@ -342,7 +343,7 @@ FILE_SCOPE bool ObjWavefrontLoad(const PlatformAPI api, PlatformMemory *const me
i32 numLen = (i32)((size_t)scan - (size_t)numStartPtr); i32 numLen = (i32)((size_t)scan - (size_t)numStartPtr);
i32 groupSmoothing = (i32)Dqn_StrToI64(numStartPtr, numLen); i32 groupSmoothing = (i32)Dqn_StrToI64(numStartPtr, numLen);
obj.model.groupSmoothing = groupSmoothing; obj->model.groupSmoothing = groupSmoothing;
} }
while (scan && *scan == ' ' || *scan == '\n') scan++; while (scan && *scan == ' ' || *scan == '\n') scan++;
@ -1479,6 +1480,7 @@ extern "C" void DTR_Update(PlatformRenderBuffer *const renderBuffer,
} }
DTR_DEBUG_TIMED_FUNCTION(); DTR_DEBUG_TIMED_FUNCTION();
LOCAL_PERSIST WavefrontObj waveObj = {};
if (!memory->isInit) if (!memory->isInit)
{ {
TestStrToF32Converter(); TestStrToF32Converter();
@ -1505,10 +1507,70 @@ extern "C" void DTR_Update(PlatformRenderBuffer *const renderBuffer,
int x = 5; int x = 5;
DqnMemStack_EndTempRegion(tmp); DqnMemStack_EndTempRegion(tmp);
ObjWavefrontLoad(input->api, memory, "african_head.obj"); #if 0
DQN_ASSERT(ObjWavefrontLoad(input->api, memory, "african_head.obj", &waveObj));
#endif
} }
DTRRender_Clear(renderBuffer, DqnV3_3f(0, 0, 0)); DTRRender_Clear(renderBuffer, DqnV3_3f(0, 0, 0));
#if 1
DqnV4 modelCol = DqnV4_4f(1, 1, 1, 1);
for (i32 i = 0; i < waveObj.model.faces.count; i++)
{
WavefrontModelFace face = waveObj.model.faces.data[i];
DQN_ASSERT(face.vertexArray.count == 3);
#if 0
i32 vertAIndex = face.vertexArray.data[0];
i32 vertBIndex = face.vertexArray.data[1];
i32 vertCIndex = face.vertexArray.data[2];
DqnV4 vertA = waveObj.geometryArray.data[vertAIndex];
DqnV4 vertB = waveObj.geometryArray.data[vertBIndex];
DqnV4 vertC = waveObj.geometryArray.data[vertCIndex];
vertA.x *= (renderBuffer->width * 0.5f);
vertA.y *= (renderBuffer->height * 0.5f);
vertB.x *= (renderBuffer->width * 0.5f);
vertB.y *= (renderBuffer->height * 0.5f);
vertC.x *= (renderBuffer->width * 0.5f);
vertC.y *= (renderBuffer->height * 0.5f);
vertA.x += (renderBuffer->width * 0.5f);
vertA.y += (renderBuffer->height * 0.5f);
vertB.x += (renderBuffer->width * 0.5f);
vertB.y += (renderBuffer->height * 0.5f);
vertC.x += (renderBuffer->width * 0.5f);
vertC.y += (renderBuffer->height * 0.5f);
DTRRender_Triangle(renderBuffer, vertA.xy, vertB.xy, vertC.xy, modelCol);
#else
const i32 NUM_VERTEXES = 3;
for (i32 j = 0; j < NUM_VERTEXES; j++)
{
i32 vertAIndex = face.vertexArray.data[j];
i32 vertBIndex = face.vertexArray.data[(j + 1) % NUM_VERTEXES];
DqnV4 vertA = waveObj.geometryArray.data[vertAIndex];
DqnV4 vertB = waveObj.geometryArray.data[vertBIndex];
vertA.x = (vertA.x * (renderBuffer->width * 0.5f)) + renderBuffer->width * 0.5f;
vertA.y = (vertA.y * (renderBuffer->height * 0.5f)) + renderBuffer->height * 0.5f;
vertB.x = (vertB.x * (renderBuffer->width * 0.5f)) + renderBuffer->width * 0.5f;
vertB.y = (vertB.y * (renderBuffer->height * 0.5f)) + renderBuffer->height * 0.5f;
DTRRender_Line(renderBuffer, DqnV2i_V2(vertA.xy), DqnV2i_V2(vertB.xy), modelCol);
}
#endif
}
#endif
#if 0
#if 1 #if 1
DqnV4 colorRed = DqnV4_4f(0.8f, 0, 0, 1); DqnV4 colorRed = DqnV4_4f(0.8f, 0, 0, 1);
DqnV2i bufferMidP = DqnV2i bufferMidP =
@ -1563,6 +1625,7 @@ extern "C" void DTR_Update(PlatformRenderBuffer *const renderBuffer,
#else #else
CompAssignment(renderBuffer, input, memory); CompAssignment(renderBuffer, input, memory);
#endif
#endif #endif
DTRDebug_Update(state, renderBuffer, input, memory); DTRDebug_Update(state, renderBuffer, input, memory);
} }

View File

@ -4,7 +4,7 @@
#include "dqn.h" #include "dqn.h"
#define DTR_DEBUG 1 #define DTR_DEBUG 1
#ifdef DTR_DEBUG #ifdef DTR_DEBUG
#define DTR_DEBUG_RENDER 1 #define DTR_DEBUG_RENDER 0
#define DTR_DEBUG_PROFILING 1 #define DTR_DEBUG_PROFILING 1
#ifdef DTR_DEBUG_PROFILING #ifdef DTR_DEBUG_PROFILING

View File

@ -129,11 +129,12 @@ DQN_FILE_SCOPE bool DqnMemStack_InitWithFixedMem (DqnMemStack *const stack, u8 *
DQN_FILE_SCOPE bool DqnMemStack_InitWithFixedSize(DqnMemStack *const stack, size_t size, const bool zeroClear, const u32 byteAlign = 4); // Single allocation from platform, no further allocations, returns NULL of allocate if out of space DQN_FILE_SCOPE bool DqnMemStack_InitWithFixedSize(DqnMemStack *const stack, size_t size, const bool zeroClear, const u32 byteAlign = 4); // Single allocation from platform, no further allocations, returns NULL of allocate if out of space
DQN_FILE_SCOPE bool DqnMemStack_Init (DqnMemStack *const stack, size_t size, const bool zeroClear, const u32 byteAlign = 4); // Allocates from platform dynamically as space runs out DQN_FILE_SCOPE bool DqnMemStack_Init (DqnMemStack *const stack, size_t size, const bool zeroClear, const u32 byteAlign = 4); // Allocates from platform dynamically as space runs out
DQN_FILE_SCOPE void *DqnMemStack_Allocate (DqnMemStack *const stack, size_t size); // Returns NULL if out of space and stack is using fixed memory/size, or platform allocation fails DQN_FILE_SCOPE void *DqnMemStack_Allocate (DqnMemStack *const stack, size_t size); // Returns NULL if out of space and stack is using fixed memory/size, or platform allocation fails
DQN_FILE_SCOPE void DqnMemStack_Free (DqnMemStack *const stack); // Frees all blocks belonging to this stack DQN_FILE_SCOPE bool DqnMemStack_Pop (DqnMemStack *const stack, void *ptr, size_t size); // Frees the given ptr. It MUST be the last allocated item in the stack
DQN_FILE_SCOPE void DqnMemStack_Free (DqnMemStack *const stack); // Frees all blocks belonging to this stack
DQN_FILE_SCOPE bool DqnMemStack_FreeStackBlock (DqnMemStack *const stack, DqnMemStackBlock *block); // Frees the specified block, returns false if block doesn't belong DQN_FILE_SCOPE bool DqnMemStack_FreeStackBlock (DqnMemStack *const stack, DqnMemStackBlock *block); // Frees the specified block, returns false if block doesn't belong
DQN_FILE_SCOPE bool DqnMemStack_FreeLastBlock (DqnMemStack *const stack); // Frees the last-most memory block. If last block, free that block, next allocate will attach a block. DQN_FILE_SCOPE bool DqnMemStack_FreeLastBlock (DqnMemStack *const stack); // Frees the last-most memory block. If last block, free that block, next allocate will attach a block.
DQN_FILE_SCOPE void DqnMemStack_ClearCurrBlock (DqnMemStack *const stack, const bool zeroClear); // Reset the current memory block usage to 0 DQN_FILE_SCOPE void DqnMemStack_ClearCurrBlock (DqnMemStack *const stack, const bool zeroClear); // Reset the current memory block usage to 0
// TempMemStack is only required for the function. Once BeginTempRegion() is called, subsequent allocation calls can be made using the original stack. // TempMemStack is only required for the function. Once BeginTempRegion() is called, subsequent allocation calls can be made using the original stack.
// Upon EndTempRegion() the original stack will free any additional blocks it allocated during the temp region and revert to the original // Upon EndTempRegion() the original stack will free any additional blocks it allocated during the temp region and revert to the original
@ -547,8 +548,12 @@ DQN_FILE_SCOPE DqnV3i DqnV3i_3f(f32 x, f32 y, f32 z);
// Vec4 // Vec4
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
typedef union DqnV4 { typedef union DqnV4 {
struct { f32 x, y, z, w; }; struct
{
f32 x, y, z, w;
};
DqnV3 xyz; DqnV3 xyz;
DqnV2 xy;
struct { f32 r, g, b, a; }; struct { f32 r, g, b, a; };
DqnV3 rgb; DqnV3 rgb;
@ -1498,8 +1503,22 @@ DQN_FILE_SCOPE void *DqnMemStack_Allocate(DqnMemStack *const stack, size_t size)
return result; return result;
} }
DQN_FILE_SCOPE bool DqnMemStack_FreeStackBlock(DqnMemStack *const stack, DQN_FILE_SCOPE bool DqnMemStack_Pop(DqnMemStack *const stack, void *ptr, size_t size)
DqnMemStackBlock *block) {
if (!stack || !stack->block) return false;
u8 *currPtr = stack->block->memory + stack->block->used;
DQN_ASSERT((u8 *)ptr >= stack->block->memory && ptr < currPtr);
size_t calcSize = (size_t)currPtr - (size_t)ptr;
DQN_ASSERT(calcSize == size);
stack->block->used -= size;
return true;
}
DQN_FILE_SCOPE bool DqnMemStack_FreeStackBlock(DqnMemStack *const stack, DqnMemStackBlock *block)
{ {
if (!stack || !block || !stack->block) return false; if (!stack || !block || !stack->block) return false;
if (stack->flags & DqnMemStackFlag_IsFixedMemoryFromUser) return false; if (stack->flags & DqnMemStackFlag_IsFixedMemoryFromUser) return false;