forked from LeenkxTeam/LNXSDK
		
	
		
			
	
	
		
			246 lines
		
	
	
		
			5.0 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
		
		
			
		
	
	
			246 lines
		
	
	
		
			5.0 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// 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;
							 | 
						||
| 
								 | 
							
								}
							 |