123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245 |
- //
- // Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
- //
- // This software is provided 'as-is', without any express or implied
- // warranty. In no event will the authors be held liable for any damages
- // arising from the use of this software.
- // Permission is granted to anyone to use this software for any purpose,
- // including commercial applications, and to alter it and redistribute it
- // freely, subject to the following restrictions:
- // 1. The origin of this software must not be misrepresented; you must not
- // claim that you wrote the original software. If you use this software
- // in a product, an acknowledgment in the product documentation would be
- // appreciated but is not required.
- // 2. Altered source versions must be plainly marked as such, and must not be
- // misrepresented as being the original software.
- // 3. This notice may not be removed or altered from any source distribution.
- //
- #include "MeshLoaderObj.h"
- #include <stdio.h>
- #include <stdlib.h>
- #include <cstring>
- #define _USE_MATH_DEFINES
- #include <math.h>
- rcMeshLoaderObj::rcMeshLoaderObj() :
- m_scale(1.0f),
- m_verts(0),
- m_tris(0),
- m_normals(0),
- m_vertCount(0),
- m_triCount(0)
- {
- }
- rcMeshLoaderObj::~rcMeshLoaderObj()
- {
- delete [] m_verts;
- delete [] m_normals;
- delete [] m_tris;
- }
-
- void rcMeshLoaderObj::addVertex(float x, float y, float z, int& cap)
- {
- if (m_vertCount+1 > cap)
- {
- cap = !cap ? 8 : cap*2;
- float* nv = new float[cap*3];
- if (m_vertCount)
- memcpy(nv, m_verts, m_vertCount*3*sizeof(float));
- delete [] m_verts;
- m_verts = nv;
- }
- float* dst = &m_verts[m_vertCount*3];
- *dst++ = x*m_scale;
- *dst++ = y*m_scale;
- *dst++ = z*m_scale;
- m_vertCount++;
- }
- void rcMeshLoaderObj::addTriangle(int a, int b, int c, int& cap)
- {
- if (m_triCount+1 > cap)
- {
- cap = !cap ? 8 : cap*2;
- int* nv = new int[cap*3];
- if (m_triCount)
- memcpy(nv, m_tris, m_triCount*3*sizeof(int));
- delete [] m_tris;
- m_tris = nv;
- }
- int* dst = &m_tris[m_triCount*3];
- *dst++ = a;
- *dst++ = b;
- *dst++ = c;
- m_triCount++;
- }
- static char* parseRow(char* buf, char* bufEnd, char* row, int len)
- {
- bool start = true;
- bool done = false;
- int n = 0;
- while (!done && buf < bufEnd)
- {
- char c = *buf;
- buf++;
- // multirow
- switch (c)
- {
- case '\\':
- break;
- case '\n':
- if (start) break;
- done = true;
- break;
- case '\r':
- break;
- case '\t':
- case ' ':
- if (start) break;
- // else falls through
- default:
- start = false;
- row[n++] = c;
- if (n >= len-1)
- done = true;
- break;
- }
- }
- row[n] = '\0';
- return buf;
- }
- static int parseFace(char* row, int* data, int n, int vcnt)
- {
- int j = 0;
- while (*row != '\0')
- {
- // Skip initial white space
- while (*row != '\0' && (*row == ' ' || *row == '\t'))
- row++;
- char* s = row;
- // Find vertex delimiter and terminated the string there for conversion.
- while (*row != '\0' && *row != ' ' && *row != '\t')
- {
- if (*row == '/') *row = '\0';
- row++;
- }
- if (*s == '\0')
- continue;
- int vi = atoi(s);
- data[j++] = vi < 0 ? vi+vcnt : vi-1;
- if (j >= n) return j;
- }
- return j;
- }
- bool rcMeshLoaderObj::load(const std::string& filename)
- {
- char* buf = 0;
- FILE* fp = fopen(filename.c_str(), "rb");
- if (!fp)
- return false;
- if (fseek(fp, 0, SEEK_END) != 0)
- {
- fclose(fp);
- return false;
- }
- long bufSize = ftell(fp);
- if (bufSize < 0)
- {
- fclose(fp);
- return false;
- }
- if (fseek(fp, 0, SEEK_SET) != 0)
- {
- fclose(fp);
- return false;
- }
- buf = new char[bufSize];
- if (!buf)
- {
- fclose(fp);
- return false;
- }
- size_t readLen = fread(buf, bufSize, 1, fp);
- fclose(fp);
- if (readLen != 1)
- {
- delete[] buf;
- return false;
- }
- char* src = buf;
- char* srcEnd = buf + bufSize;
- char row[512];
- int face[32];
- float x,y,z;
- int nv;
- int vcap = 0;
- int tcap = 0;
-
- while (src < srcEnd)
- {
- // Parse one row
- row[0] = '\0';
- src = parseRow(src, srcEnd, row, sizeof(row)/sizeof(char));
- // Skip comments
- if (row[0] == '#') continue;
- if (row[0] == 'v' && row[1] != 'n' && row[1] != 't')
- {
- // Vertex pos
- sscanf(row+1, "%f %f %f", &x, &y, &z);
- addVertex(x, y, z, vcap);
- }
- if (row[0] == 'f')
- {
- // Faces
- nv = parseFace(row+1, face, 32, m_vertCount);
- for (int i = 2; i < nv; ++i)
- {
- const int a = face[0];
- const int b = face[i-1];
- const int c = face[i];
- if (a < 0 || a >= m_vertCount || b < 0 || b >= m_vertCount || c < 0 || c >= m_vertCount)
- continue;
- addTriangle(a, b, c, tcap);
- }
- }
- }
- delete [] buf;
- // Calculate normals.
- m_normals = new float[m_triCount*3];
- for (int i = 0; i < m_triCount*3; i += 3)
- {
- const float* v0 = &m_verts[m_tris[i]*3];
- const float* v1 = &m_verts[m_tris[i+1]*3];
- const float* v2 = &m_verts[m_tris[i+2]*3];
- float e0[3], e1[3];
- for (int j = 0; j < 3; ++j)
- {
- e0[j] = v1[j] - v0[j];
- e1[j] = v2[j] - v0[j];
- }
- float* n = &m_normals[i];
- n[0] = e0[1]*e1[2] - e0[2]*e1[1];
- n[1] = e0[2]*e1[0] - e0[0]*e1[2];
- n[2] = e0[0]*e1[1] - e0[1]*e1[0];
- float d = sqrtf(n[0]*n[0] + n[1]*n[1] + n[2]*n[2]);
- if (d > 0)
- {
- d = 1.0f/d;
- n[0] *= d;
- n[1] *= d;
- n[2] *= d;
- }
- }
-
- m_filename = filename;
- return true;
- }
|