From 08f5c4618dcdbf94bd8451d75f0f376b3726adcf Mon Sep 17 00:00:00 2001 From: Marc Sunet Date: Sat, 11 Aug 2012 11:41:21 +0200 Subject: OBJ loader rewritten in C --- Spear.cabal | 7 +- Spear.lkshs | 12 +- Spear.lkshw | 2 +- Spear/Assets/Model/OBJ/Makefile | 17 ++- Spear/Assets/Model/OBJ/OBJ_load.c | 276 +++++++++++++++++++++++++++++++++++++ Spear/Assets/Model/OBJ/OBJ_load.cc | 273 ------------------------------------ Spear/Assets/Model/OBJ/cvector.c | 90 ++++++++++++ Spear/Assets/Model/OBJ/cvector.h | 36 +++++ Spear/Assets/Model/OBJ/test.cc | 47 ------- 9 files changed, 424 insertions(+), 336 deletions(-) create mode 100644 Spear/Assets/Model/OBJ/OBJ_load.c delete mode 100644 Spear/Assets/Model/OBJ/OBJ_load.cc create mode 100644 Spear/Assets/Model/OBJ/cvector.c create mode 100644 Spear/Assets/Model/OBJ/cvector.h delete mode 100644 Spear/Assets/Model/OBJ/test.cc diff --git a/Spear.cabal b/Spear.cabal index d30cbae..37ab48b 100644 --- a/Spear.cabal +++ b/Spear.cabal @@ -42,15 +42,16 @@ library cc-options: -O2 -g -Wno-unused-result c-sources: Spear/Assets/Image/Image.c Spear/Assets/Image/BMP/BMP_load.c Spear/Assets/Model/Model.c - Spear/Assets/Model/MD2/MD2_load.c - Spear/Assets/Model/OBJ/OBJ_load.cc Spear/Render/RenderModel.c + Spear/Assets/Model/MD2/MD2_load.c Spear/Assets/Model/OBJ/cvector.c + Spear/Assets/Model/OBJ/OBJ_load.c Spear/Render/RenderModel.c Spear/Sys/Timer/ctimer.c extensions: TypeFamilies extra-libraries: stdc++ includes: Spear/Assets/Image/BMP/BMP_load.h Spear/Assets/Image/Image.h Spear/Assets/Image/Image_error_code.h Spear/Assets/Image/sys_types.h Spear/Assets/Model/MD2/MD2_load.h - Spear/Assets/Model/OBJ/OBJ_load.h Spear/Assets/Model/Model.h + Spear/Assets/Model/OBJ/OBJ_load.h Spear/Assets/Model/OBJ/cvector.h + Spear/Assets/Model/Model.h Spear/Assets/Model/Model_error_code.h Spear/Assets/Model/sys_types.h Spear/Render/RenderModel.h Timer/Timer.h diff --git a/Spear.lkshs b/Spear.lkshs index d69e4f9..c4ef8ee 100644 --- a/Spear.lkshs +++ b/Spear.lkshs @@ -1,18 +1,18 @@ Version of session file format: 1 Time of storage: - "Fri Aug 10 15:19:04 CEST 2012" -Layout: VerticalP (TerminalP {paneGroups = fromList [], paneTabs = Just TopP, currentPage = 4, detachedId = Nothing, detachedSize = Nothing}) (HorizontalP (TerminalP {paneGroups = fromList [("Browser",HorizontalP (TerminalP {paneGroups = fromList [], paneTabs = Nothing, currentPage = 0, detachedId = Nothing, detachedSize = Nothing}) (HorizontalP (TerminalP {paneGroups = fromList [], paneTabs = Nothing, currentPage = 0, detachedId = Nothing, detachedSize = Nothing}) (TerminalP {paneGroups = fromList [], paneTabs = Nothing, currentPage = 0, detachedId = Nothing, detachedSize = Nothing}) 255) 201)], paneTabs = Just BottomP, currentPage = 0, detachedId = Nothing, detachedSize = Nothing}) (TerminalP {paneGroups = fromList [], paneTabs = Nothing, currentPage = 0, detachedId = Nothing, detachedSize = Nothing}) 707) 954 -Population: [(Just (ErrorsSt ErrorsState),[SplitP RightP,SplitP TopP]),(Just (FilesSt FilesState),[SplitP RightP,SplitP TopP]),(Just (InfoSt (InfoState Nothing)),[SplitP RightP,SplitP TopP,GroupP "Browser",SplitP BottomP,SplitP BottomP]),(Just (BufferSt (BufferState "/home/jeanne/programming/haskell/Spear/Spear/Scene/Loader.hs" 6686)),[SplitP LeftP]),(Just (LogSt LogState),[SplitP RightP,SplitP BottomP]),(Just (BufferSt (BufferState "/home/jeanne/programming/haskell/Spear/Spear/Assets/Model/MD2/MD2_load.c" 13934)),[SplitP LeftP]),(Just (BufferSt (BufferState "/home/jeanne/programming/haskell/Spear/Spear/Assets/Model/Model.c" 433)),[SplitP LeftP]),(Just (BufferSt (BufferState "/home/jeanne/programming/haskell/Spear/Spear/Assets/Model/Model.h" 1424)),[SplitP LeftP]),(Just (BufferSt (BufferState "/home/jeanne/programming/haskell/Spear/Spear/Assets/Model.hsc" 12957)),[SplitP LeftP]),(Just (ModulesSt (ModulesState 328 (PackageScope False,False) (Nothing,Nothing) (ExpanderState {packageExp = ([],[]), packageExpNoBlack = ([],[]), packageDExp = ([],[]), packageDExpNoBlack = ([],[]), workspaceExp = ([],[]), workspaceExpNoBlack = ([[0,2],[0]],[]), workspaceDExp = ([],[]), workspaceDExpNoBlack = ([],[]), systemExp = ([],[]), systemExpNoBlack = ([],[])}))),[SplitP RightP,SplitP TopP,GroupP "Browser",SplitP BottomP,SplitP TopP]),(Just (BufferSt (BufferState "/home/jeanne/programming/haskell/Spear/Spear/Assets/Model/OBJ/OBJ_load.cc" 266)),[SplitP LeftP]),(Just (BufferSt (BufferState "/home/jeanne/programming/haskell/Spear/Spear/Assets/Model/OBJ/OBJ_load.h" 0)),[SplitP LeftP]),(Just (WorkspaceSt WorkspaceState),[SplitP RightP,SplitP TopP,GroupP "Browser",SplitP TopP])] + "Fri Aug 10 23:05:26 CEST 2012" +Layout: VerticalP (TerminalP {paneGroups = fromList [], paneTabs = Just TopP, currentPage = 3, detachedId = Nothing, detachedSize = Nothing}) (HorizontalP (TerminalP {paneGroups = fromList [("Browser",HorizontalP (TerminalP {paneGroups = fromList [], paneTabs = Nothing, currentPage = 0, detachedId = Nothing, detachedSize = Nothing}) (HorizontalP (TerminalP {paneGroups = fromList [], paneTabs = Nothing, currentPage = 0, detachedId = Nothing, detachedSize = Nothing}) (TerminalP {paneGroups = fromList [], paneTabs = Nothing, currentPage = 0, detachedId = Nothing, detachedSize = Nothing}) 244) 202)], paneTabs = Just BottomP, currentPage = 0, detachedId = Nothing, detachedSize = Nothing}) (TerminalP {paneGroups = fromList [], paneTabs = Nothing, currentPage = 0, detachedId = Nothing, detachedSize = Nothing}) 710) 954 +Population: [(Just (ErrorsSt ErrorsState),[SplitP RightP,SplitP TopP]),(Just (FilesSt FilesState),[SplitP RightP,SplitP TopP]),(Just (InfoSt (InfoState Nothing)),[SplitP RightP,SplitP TopP,GroupP "Browser",SplitP BottomP,SplitP BottomP]),(Just (LogSt LogState),[SplitP RightP,SplitP BottomP]),(Just (BufferSt (BufferState "/home/jeanne/programming/haskell/Spear/Spear/Assets/Model/Model.c" 433)),[SplitP LeftP]),(Just (BufferSt (BufferState "/home/jeanne/programming/haskell/Spear/Spear/Assets/Model/Model.h" 1424)),[SplitP LeftP]),(Just (BufferSt (BufferState "/home/jeanne/programming/haskell/Spear/Spear/Assets/Model.hsc" 423)),[SplitP LeftP]),(Just (ModulesSt (ModulesState 328 (PackageScope False,False) (Nothing,Nothing) (ExpanderState {packageExp = ([],[]), packageExpNoBlack = ([],[]), packageDExp = ([],[]), packageDExpNoBlack = ([],[]), workspaceExp = ([],[]), workspaceExpNoBlack = ([[0,2],[0]],[]), workspaceDExp = ([],[]), workspaceDExpNoBlack = ([],[]), systemExp = ([],[]), systemExpNoBlack = ([],[])}))),[SplitP RightP,SplitP TopP,GroupP "Browser",SplitP BottomP,SplitP TopP]),(Just (BufferSt (BufferState "/home/jeanne/programming/haskell/Spear/Spear/Assets/Model/OBJ/OBJ_load.c" 3824)),[SplitP LeftP]),(Just (BufferSt (BufferState "/home/jeanne/programming/haskell/Spear/Spear/Assets/Model/OBJ/OBJ_load.h" 0)),[SplitP LeftP]),(Just (WorkspaceSt WorkspaceState),[SplitP RightP,SplitP TopP,GroupP "Browser",SplitP TopP]),(Just (BufferSt (BufferState "/home/jeanne/programming/haskell/Spear/Spear/Assets/Model/OBJ/cvector.c" 575)),[SplitP LeftP]),(Just (BufferSt (BufferState "/home/jeanne/programming/haskell/Spear/Spear/Assets/Model/OBJ/cvector.h" 765)),[SplitP LeftP])] Window size: (1841,964) Completion size: (750,400) Workspace: Just "/home/jeanne/programming/haskell/Spear/Spear.lkshw" -Active pane: Just "Model.hsc" +Active pane: Just "OBJ_load.c" Toolbar visible: True -FindbarState: (False,FindState {entryStr = "asd", entryHist = ["allocaBytes","copyArray","allocaArray","allocaa","putStrLn","assigned","Triangle","transforma","gravity","asdad","rotSpeed","azimuth"], replaceStr = "objects", replaceHist = [], caseSensitive = True, entireWord = False, wrapAround = False, regex = False, lineNr = 1}) +FindbarState: (False,FindState {entryStr = "asd", entryHist = ["idxs","asd","elemIndexa","elemtIn","splitAt","allocaBytes","copyArray","allocaArray","allocaa","putStrLn","assigned","Triangle"], replaceStr = "objects", replaceHist = [], caseSensitive = True, entireWord = False, wrapAround = False, regex = False, lineNr = 1}) Recently opened files: - ["/home/jeanne/programming/haskell/Spear/Spear/Assets/Image.hsc","/home/jeanne/programming/haskell/Spear/Spear/Render/Model.hsc","/home/jeanne/programming/haskell/Spear/demos/simple-scene/main.hs","/home/jeanne/programming/haskell/Spear/demos/simple-scene/Game/GameObject/Player.hs","/home/jeanne/programming/haskell/Spear/demos/simple-scene/Game/GameState.hs","/home/jeanne/programming/haskell/Spear/demos/simple-scene/Game/GameObject.hs","/home/jeanne/programming/haskell/Spear/demos/simple-scene/Game/GameMessage.hs","/home/jeanne/programming/haskell/Spear/demos/simple-scene/Game/GameObject/Factory.hs","/home/jeanne/programming/haskell/Spear/demos/simple-scene/Game/Animation/Ogro.hs","/home/jeanne/programming/haskell/Spear/demos/simple-scene/Game/GameObject/AnimatedGO.hs","/home/jeanne/programming/haskell/Spear/demos/simple-scene/Game/GameObject/StaticGO.hs","/home/jeanne/programming/haskell/Spear/demos/simple-scene/Game/GameObject/Render.hs"] + ["/home/jeanne/programming/haskell/Spear/Spear/Scene/Loader.hs","/home/jeanne/programming/haskell/Spear/Spear/Assets/Model/OBJ/OBJ_load.h","/home/jeanne/programming/haskell/Spear/Spear/Assets/Model/OBJ/OBJ_load.cc","/home/jeanne/programming/haskell/Spear/Spear/Assets/Model/MD2/MD2_load.c","/home/jeanne/programming/haskell/Spear/Spear/Assets/Image.hsc","/home/jeanne/programming/haskell/Spear/Spear/Render/Model.hsc","/home/jeanne/programming/haskell/Spear/demos/simple-scene/main.hs","/home/jeanne/programming/haskell/Spear/demos/simple-scene/Game/GameObject/Player.hs","/home/jeanne/programming/haskell/Spear/demos/simple-scene/Game/GameState.hs","/home/jeanne/programming/haskell/Spear/demos/simple-scene/Game/GameObject.hs","/home/jeanne/programming/haskell/Spear/demos/simple-scene/Game/GameMessage.hs","/home/jeanne/programming/haskell/Spear/demos/simple-scene/Game/GameObject/Factory.hs"] Recently opened workspaces: ["/home/jeanne/leksah.lkshw"] \ No newline at end of file diff --git a/Spear.lkshw b/Spear.lkshw index 143acdc..1cbf39e 100644 --- a/Spear.lkshw +++ b/Spear.lkshw @@ -1,7 +1,7 @@ Version of workspace file format: 1 Time of storage: - "Fri Aug 10 15:56:20 CEST 2012" + "Sat Aug 11 11:39:35 CEST 2012" Name of the workspace: "Spear" File paths of contained packages: diff --git a/Spear/Assets/Model/OBJ/Makefile b/Spear/Assets/Model/OBJ/Makefile index 6f9556f..34424f7 100644 --- a/Spear/Assets/Model/OBJ/Makefile +++ b/Spear/Assets/Model/OBJ/Makefile @@ -1,10 +1,15 @@ -all: OBJ_load.h OBJ_load.cc test.cc ../Model.c - g++ -g -c OBJ_load.cc - g++ -g -c test.cc - g++ -g -c ../Model.c -o Model.o - g++ -o test *.o +test: ../Model.o OBJ_load.o cvector.o test.o + $(CC) Model.o OBJ_load.o cvector.o test.o -o $@ -lm + +vector: cvector.o vector-test.o + $(CC) cvector.o vector-test.o -o vector + + +%.o: %.c %.h + $(CC) -g -c $< + clean: - @rm -f test + @rm -f test vector @rm -f *.o diff --git a/Spear/Assets/Model/OBJ/OBJ_load.c b/Spear/Assets/Model/OBJ/OBJ_load.c new file mode 100644 index 0000000..2474091 --- /dev/null +++ b/Spear/Assets/Model/OBJ/OBJ_load.c @@ -0,0 +1,276 @@ +#include "OBJ_load.h" +#include "cvector.h" +#include +#include // free +#include // memcpy +#include // sqrt + + +char lastError [128]; + + +static void safe_free (void* ptr) +{ + if (ptr) + { + free (ptr); + ptr = 0; + } +} + + +// Cross product. +// (0,1,0) x (1,0,0) = (0,0,-1). +static void cross (vec3 a, vec3 b, vec3* c) +{ + c->x = a.y * b.z - a.z * b.y; + c->y = a.z * b.x - a.x * b.z; + c->z = a.x * b.y - a.y * b.x; +} + + +static void vec3_sub (vec3 a, vec3 b, vec3* out) +{ + out->x = a.x - b.x; + out->y = a.y - b.y; + out->z = a.z - b.z; +} + + +static void compute_normal (char clockwise, vec3 p1, vec3 p2, vec3 p3, vec3* n) +{ + vec3 v1, v2; + if (clockwise) + { + vec3_sub (p3, p2, &v1); + vec3_sub (p1, p2, &v2); + } + else + { + vec3_sub (p1, p2, &v1); + vec3_sub (p3, p2, &v2); + } + cross (v1, v2, n); +} + + +static void normalise (vec3* v) +{ + float x = v->x; + float y = v->y; + float z = v->z; + float mag = sqrt (x*x + y*y + z*z); + mag = mag == 0.0f ? 1.0f : mag; + v->x /= mag; + v->y /= mag; + v->z /= mag; +} + + +static void vec3_add (vec3 a, vec3* b) +{ + b->x += a.x; + b->y += a.y; + b->z += a.z; +} + + +static void read_vertex (FILE* file, vec3* vert) +{ + fscanf (file, "%f %f", &vert->x, &vert->y); + if (fscanf(file, "%f", &vert->z) == 0) vert->z = 0.0f; +} + + +static void read_normal (FILE* file, vec3* normal) +{ + fscanf (file, "%f %f %f", &normal->x, &normal->y, &normal->z); +} + + +static void read_tex_coord (FILE* file, texCoord* texc) +{ + fscanf (file, "%f %f", &texc->s, &texc->t); +} + + +static void read_face (FILE* file, + char clockwise, + vector* vertices, + vector* normals, + vector* triangles) +{ + vector idxs; + vector texCoords; + + vector_new (&idxs, sizeof(int), 4); + vector_new (&texCoords, sizeof(int), 4); + + unsigned int index; + unsigned int normal; + unsigned int texc; + + fscanf (file, "f"); + + while (!feof(file) && fscanf(file, "%d", &index) > 0) + { + vector_append (&idxs, &index); + + if (fgetc (file) == '/') + { + fscanf (file, "%d", &texc); + vector_append (&texCoords, &texc); + } + else fseek (file, -1, SEEK_CUR); + + if (fgetc (file) == '/') + { + fscanf (file, "%d", &normal); + } + else fseek (file, -1, SEEK_CUR); + } + + // Triangulate the face and add its triangles to the triangles vector. + triangle tri; + tri.vertexIndices[0] = *((int*) vector_ith (&idxs, 0)) - 1; + tri.textureIndices[0] = *((int*) vector_ith (&texCoords, 0)) - 1; + + int i; + for (i = 1; i < vector_size(&idxs)-1; i++) + { + tri.vertexIndices[1] = *((int*) vector_ith (&idxs, i)) - 1; + tri.textureIndices[1] = *((int*) vector_ith (&texCoords, i)) - 1; + tri.vertexIndices[2] = *((int*) vector_ith (&idxs, i+1)) - 1; + tri.textureIndices[2] = *((int*) vector_ith (&texCoords, i+1)) - 1; + vector_append (triangles, &tri); + } + + // Compute face normal and add contribution to each of the face's vertices. + unsigned int i0 = tri.vertexIndices[0]; + unsigned int i1 = tri.vertexIndices[1]; + unsigned int i2 = tri.vertexIndices[2]; + + vec3 n; + vec3 v0 = *((vec3*) vector_ith (vertices, i0)); + vec3 v1 = *((vec3*) vector_ith (vertices, i1)); + vec3 v2 = *((vec3*) vector_ith (vertices, i2)); + compute_normal (clockwise, v0, v1, v2, &n); + + for (i = 0; i < vector_size (&idxs); i++) + { + int j = *((int*) vector_ith (&idxs, i)) - 1; + vec3* normal = (vec3*) vector_ith (normals, j); + vec3_add (n, normal); + } + + vector_free (&idxs); + vector_free (&texCoords); +} + + +Model_error_code OBJ_load (const char* filename, char clockwise, char left_handed, Model* model) +{ + vec3* norms = 0; + vec3* verts = 0; + texCoord* texcs = 0; + triangle* tris = 0; + + FILE* file = fopen (filename, "r"); + if (file == NULL) return Model_File_Not_Found; + + vec3 vert; + vec3 normal; + texCoord texc; + + vector vertices; + vector normals; + vector texCoords; + vector triangles; + + int result = vector_new (&vertices, sizeof(vec3), 0) + | vector_new (&normals, sizeof(vec3), 0) + | vector_new (&texCoords, sizeof(texCoord), 0) + | vector_new (&triangles, sizeof(triangle), 0); + + if (result != 0) + { + safe_free (vertices.data); + safe_free (normals.data); + safe_free (texCoords.data); + safe_free (triangles.data); + return Model_Memory_Allocation_Error; + } + + while (!feof(file)) + { + switch (fgetc(file)) + { + case 'v': + switch (fgetc(file)) + { + case 't': + read_tex_coord (file, &texc); + vector_append (&texCoords, &texc); + break; + + case 'n': + read_normal (file, &normal); + vector_append (&normals, &normal); + break; + + default: + read_vertex (file, &vert); + vector_append (&vertices, &vert); + break; + } + break; + + case 'f': + // Initialise the normals vector if it is empty. + if (vector_size(&normals) == 0) + { + vec3 zero; + zero.x = 0.0f; zero.y = 0.0f; zero.z = 0.0f; + vector_new (&normals, sizeof(vec3), vector_size(&vertices)); + vector_initialise (&normals, &zero); + } + read_face (file, clockwise, &vertices, &normals, &triangles); + break; + + case '#': + { + int x = 17; + while (x != '\n' && x != EOF) x = fgetc(file); + break; + } + + default: break; + } + } + + fclose (file); + + unsigned numVertices = vector_size (&vertices); + + // Normalise normals. + unsigned i; + for (i = 0; i < numVertices; ++i) + { + normalise (vector_ith (&normals, i)); + } + + model->vertices = (vec3*) vertices.data; + model->normals = (vec3*) normals.data; + model->texCoords = (texCoord*) texCoords.data; + model->triangles = (triangle*) triangles.data; + model->skins = 0; + model->animations = 0; + model->numFrames = 1; + model->numVertices = numVertices; + model->numTriangles = vector_size (&triangles); + model->numTexCoords = vector_size (&texCoords); + model->numSkins = 0; + model->numAnimations = 0; + + return Model_Success; +} diff --git a/Spear/Assets/Model/OBJ/OBJ_load.cc b/Spear/Assets/Model/OBJ/OBJ_load.cc deleted file mode 100644 index bf409b1..0000000 --- a/Spear/Assets/Model/OBJ/OBJ_load.cc +++ /dev/null @@ -1,273 +0,0 @@ -#include "OBJ_load.h" -#include -#include // free -#include // memcpy -#include // sqrt -#include - - -char lastError [128]; - - -static void safe_free (void* ptr) -{ - if (ptr) - { - free (ptr); - ptr = 0; - } -} - - -// Cross product. -// (0,1,0) x (1,0,0) = (0,0,-1). -static void cross (const vec3& a, const vec3& b, vec3& c) -{ - c.x = a.y * b.z - a.z * b.y; - c.y = a.z * b.x - a.x * b.z; - c.z = a.x * b.y - a.y * b.x; -} - - -static void vec3_sub (const vec3& a, const vec3& b, vec3& out) -{ - out.x = a.x - b.x; - out.y = a.y - b.y; - out.z = a.z - b.z; -} - - -static void compute_normal (char clockwise, const vec3& p1, const vec3& p2, const vec3& p3, vec3& n) -{ - vec3 v1, v2; - if (clockwise) - { - vec3_sub (p3, p2, v1); - vec3_sub (p1, p2, v2); - } - else - { - vec3_sub (p1, p2, v1); - vec3_sub (p3, p2, v2); - } - cross (v1, v2, n); -} - - -static void normalise (vec3& v) -{ - float x = v.x; - float y = v.y; - float z = v.z; - float mag = sqrt (x*x + y*y + z*z); - mag = mag == 0.0f ? 1.0f : mag; - v.x /= mag; - v.y /= mag; - v.z /= mag; -} - - -static void vec3_add (const vec3& a, vec3& b) -{ - b.x += a.x; - b.y += a.y; - b.z += a.z; -} - - -static void read_vertex (FILE* file, vec3& vert) -{ - fscanf (file, "%f %f", &vert.x, &vert.y); - if (fscanf(file, "%f", &vert.z) == 0) vert.z = 0.0f; -} - - -static void read_normal (FILE* file, vec3& normal) -{ - fscanf (file, "%f %f %f", &normal.x, &normal.y, &normal.z); -} - - -static void read_tex_coord (FILE* file, texCoord& texc) -{ - fscanf (file, "%f %f", &texc.s, &texc.t); -} - - -static void read_face (FILE* file, char clockwise, - const std::vector& vertices, - std::vector& normals, - std::vector& triangles) -{ - std::vector idxs; - std::vector texCoords; - - unsigned int index; - unsigned int normal; - unsigned int texc; - - fscanf (file, "f"); - - while (!feof(file) && fscanf(file, "%d", &index) > 0) - { - idxs.push_back(index); - - if (fgetc (file) == '/') - { - fscanf (file, "%d", &texc); - texCoords.push_back(texc); - } - else fseek (file, -1, SEEK_CUR); - - if (fgetc (file) == '/') - { - fscanf (file, "%d", &normal); - } - else fseek (file, -1, SEEK_CUR); - } - - // Triangulate the face and add its triangles to the triangles vector. - triangle tri; - tri.vertexIndices[0] = idxs[0] - 1; - tri.textureIndices[0] = texCoords[0] - 1; - - for (int i = 1; i < idxs.size()-1; i++) - { - tri.vertexIndices[1] = idxs[i] - 1; - tri.textureIndices[1] = texCoords[i] - 1; - tri.vertexIndices[2] = idxs[i+1] - 1; - tri.textureIndices[2] = texCoords[i+1] - 1; - triangles.push_back(tri); - } - - // Compute face normal and add contribution to each of the face's vertices. - unsigned int i0 = tri.vertexIndices[0]; - unsigned int i1 = tri.vertexIndices[1]; - unsigned int i2 = tri.vertexIndices[2]; - - vec3 n; - compute_normal (clockwise, vertices[i0], vertices[i1], vertices[i2], n); - - for (int i = 0; i < idxs.size(); i++) - { - vec3_add (n, normals[idxs[i]-1]); - } -} - - -Model_error_code OBJ_load (const char* filename, char clockwise, char left_handed, Model* model) -{ - vec3* norms = 0; - vec3* verts = 0; - texCoord* texcs = 0; - triangle* tris = 0; - FILE* file = 0; - - try - { - file = fopen (filename, "r"); - - vec3 vert; - vec3 normal; - texCoord texc; - - std::vector vertices; - std::vector normals; - std::vector texCoords; - std::vector triangles; - - while (!feof(file)) - { - switch (fgetc(file)) - { - case 'v': - switch (fgetc(file)) - { - case 't': - read_tex_coord (file, texc); - texCoords.push_back(texc); - break; - - case 'n': - read_normal (file, normal); - break; - - default: - read_vertex (file, vert); - vertices.push_back(vert); - break; - } - break; - - case 'f': - // If the normals vector has no size, initialise it. - if (normals.size() == 0) - { - vec3 zero; - zero.x = 0.0f; zero.y = 0.0f; zero.z = 0.0f; - normals = std::vector(vertices.size(), zero); - } - read_face (file, clockwise, vertices, normals, triangles); - break; - - case '#': - { - int x = 17; - while (x != '\n' && x != EOF) x = fgetc(file); - break; - } - - default: break; - } - } - - fclose (file); - - unsigned int numVertices = vertices.size(); - unsigned int numTexCoords = texCoords.size(); - unsigned int numTriangles = triangles.size(); - - verts = new vec3 [numVertices]; - norms = new vec3 [numVertices]; - texcs = new texCoord [numTexCoords]; - tris = new triangle [numTriangles]; - - memcpy (verts, &vertices[0], numVertices * sizeof(vec3)); - memcpy (norms, &normals[0], numVertices * sizeof(vec3)); - memcpy (texcs, &texCoords[0], numTexCoords * sizeof(texCoord)); - memcpy (tris, &triangles[0], numTriangles * sizeof(triangle)); - - // Copy normals if the model file specified them. - - - - // Otherwise normalise the normals that have been previously computed. - - for (size_t i = 0; i < numVertices; ++i) - { - normalise(norms[i]); - } - - model->vertices = verts; - model->normals = norms; - model->texCoords = texcs; - model->triangles = tris; - model->skins = 0; - model->animations = 0; - model->numFrames = 1; - model->numVertices = numVertices; - model->numTriangles = numTriangles; - model->numTexCoords = numTexCoords; - model->numSkins = 0; - model->numAnimations = 0; - - return Model_Success; - } - catch (std::bad_alloc) - { - safe_free (verts); - safe_free (texcs); - safe_free (tris); - return Model_Memory_Allocation_Error; - } -} diff --git a/Spear/Assets/Model/OBJ/cvector.c b/Spear/Assets/Model/OBJ/cvector.c new file mode 100644 index 0000000..4e90204 --- /dev/null +++ b/Spear/Assets/Model/OBJ/cvector.c @@ -0,0 +1,90 @@ +#include "cvector.h" +#include // malloc, realloc, free +#include // memcpy + + +int max (int a, int b) +{ + if (a > b) return a; + return b; +} + + +int vector_new (vector* v, int elem_size, int num_elems) +{ + int n = num_elems * elem_size; + + char* data = 0; + if (num_elems > 0) + { + data = (char*) malloc (n); + if (data == NULL) return 1; + } + + v->data = data; + v->next = data; + v->chunk_size = n; + v->elem_size = elem_size; + + return 0; +} + + +void vector_free (vector* v) +{ + if (v->data != 0) free (v->data); +} + + +void vector_initialise (vector* v, void* value) +{ + char* ptr = v->data; + int esize = v->elem_size; + int n = vector_size (v); + + int i; + for (i = 0; i < n; ++i) + { + memcpy (ptr, value, esize); + ptr += esize; + } +} + + +int vector_append (vector* v, void* elem) +{ + // Realloc a bigger chunk when the vector runs out of space. + if (v->next == v->data + v->chunk_size) + { + int old_chunk_size = v->chunk_size; + int n = max (v->elem_size, 2 * old_chunk_size); + + char* data = (char*) realloc (v->data, n); + if (data == NULL) return 1; + + v->data = data; + v->next = data + old_chunk_size; + v->chunk_size = n; + } + + memcpy ((void*)v->next, elem, v->elem_size); + v->next += v->elem_size; +} + + +void* vector_ith (vector* v, int i) +{ + return (void*) (v->data + i*v->elem_size); +} + + +int vector_size (vector* v) +{ + return (v->next - v->data) / v->elem_size; +} + + +int vector_capacity (vector* v) +{ + return v->chunk_size / v->elem_size; +} diff --git a/Spear/Assets/Model/OBJ/cvector.h b/Spear/Assets/Model/OBJ/cvector.h new file mode 100644 index 0000000..1d16c46 --- /dev/null +++ b/Spear/Assets/Model/OBJ/cvector.h @@ -0,0 +1,36 @@ +#ifndef _C_SPEAR_VECTOR_H +#define _C_SPEAR_VECTOR_H + +typedef struct +{ + char* data; + char* next; + int chunk_size; + int elem_size; +} +vector; + +/// Construct a new vector. +/// Returns non-zero on error. +int vector_new (vector* v, int elem_size, int num_elems); + +/// Free the vector. +void vector_free (vector* v); + +/// Initialise every position to the given value. +void vector_initialise (vector* v, void* value); + +/// Append an element. +/// Returns non-zero on error. +int vector_append (vector* v, void* elem); + +/// Access the ith element. +void* vector_ith (vector* v, int i); + +/// Return the number of elements in the vector. +int vector_size (vector* v); + +/// Return the vector's capacity. +int vector_capacity (vector* v); + +#endif // _C_SPEAR_VECTOR_H diff --git a/Spear/Assets/Model/OBJ/test.cc b/Spear/Assets/Model/OBJ/test.cc deleted file mode 100644 index 31e0e39..0000000 --- a/Spear/Assets/Model/OBJ/test.cc +++ /dev/null @@ -1,47 +0,0 @@ -#include "OBJ_load.h" -#include - - -int main (void) -{ - Model model; - OBJ_load ("/home/jeanne/assets/box.obj", 1, 1, &model); - - printf("Vertices:\n"); - - for (size_t i = 0; i < model.numVertices; ++i) - { - vec3 v = model.vertices[i]; - printf ("%f, %f, %f\n", v.x, v.y, v.z); - } - - printf("\nNormals:\n"); - - for (size_t i = 0; i < model.numVertices; ++i) - { - vec3 n = model.normals[i]; - printf ("%f, %f, %f\n", n.x, n.y, n.z); - } - - printf("\nTex coords:\n"); - - for (size_t i = 0; i < model.numTexCoords; ++i) - { - texCoord tex = model.texCoords[i]; - printf("%f, %f\n", tex.s, tex.t); - } - - printf("\nTriangles:\n"); - - for (size_t i = 0; i < model.numTriangles; ++i) - { - triangle t = model.triangles[i]; - printf ("%d, %d, %d - %d, %d, %d\n", - t.vertexIndices[0]+1, t.vertexIndices[1]+1, t.vertexIndices[2]+1, - t.textureIndices[0]+1, t.textureIndices[1]+1, t.textureIndices[2]+1); - } - - model_free (&model); - - return 0; -} -- cgit v1.2.3