1
Fork 0
mirror of https://github.com/SapphireServer/Sapphire.git synced 2025-04-26 14:37:44 +00:00
sapphire/src/tools/pcb_reader/nav/ext/MeshLoaderObj.cpp

253 lines
5.7 KiB
C++
Raw Normal View History

//
// 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>
2019-01-26 19:43:42 +11:00
#define _USE_MATH_DEFINES
2019-01-26 19:43:42 +11:00
#include <math.h>
rcMeshLoaderObj::rcMeshLoaderObj() :
2019-01-26 19:43:42 +11:00
m_scale( 1.0f ),
m_verts( 0 ),
m_tris( 0 ),
m_normals( 0 ),
m_vertCount( 0 ),
m_triCount( 0 )
{
}
rcMeshLoaderObj::~rcMeshLoaderObj()
{
2019-01-26 19:43:42 +11:00
delete[] m_verts;
delete[] m_normals;
delete[] m_tris;
}
2019-01-26 19:43:42 +11:00
void rcMeshLoaderObj::addVertex( float x, float y, float z, int& cap )
{
2019-01-26 19:43:42 +11:00
if( m_vertCount + 1 > cap )
{
2019-01-26 19:43:42 +11:00
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;
}
2019-01-26 19:43:42 +11:00
float* dst = &m_verts[ m_vertCount * 3 ];
*dst++ = x * m_scale;
*dst++ = y * m_scale;
*dst++ = z * m_scale;
m_vertCount++;
}
2019-01-26 19:43:42 +11:00
void rcMeshLoaderObj::addTriangle( int a, int b, int c, int& cap )
{
2019-01-26 19:43:42 +11:00
if( m_triCount + 1 > cap )
{
2019-01-26 19:43:42 +11:00
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;
}
2019-01-26 19:43:42 +11:00
int* dst = &m_tris[ m_triCount * 3 ];
*dst++ = a;
*dst++ = b;
*dst++ = c;
m_triCount++;
}
2019-01-26 19:43:42 +11:00
static char* parseRow( char* buf, char* bufEnd, char* row, int len )
{
bool start = true;
bool done = false;
int n = 0;
2019-01-26 19:43:42 +11:00
while( !done && buf < bufEnd )
{
char c = *buf;
buf++;
// multirow
2019-01-26 19:43:42 +11:00
switch( c )
{
case '\\':
break;
case '\n':
2019-01-26 19:43:42 +11:00
if( start )
break;
done = true;
break;
case '\r':
break;
case '\t':
case ' ':
2019-01-26 19:43:42 +11:00
if( start )
break;
// else falls through
default:
start = false;
2019-01-26 19:43:42 +11:00
row[ n++ ] = c;
if( n >= len - 1 )
done = true;
break;
}
}
2019-01-26 19:43:42 +11:00
row[ n ] = '\0';
return buf;
}
2019-01-26 19:43:42 +11:00
static int parseFace( char* row, int* data, int n, int vcnt )
{
int j = 0;
2019-01-26 19:43:42 +11:00
while( *row != '\0' )
{
// Skip initial white space
2019-01-26 19:43:42 +11:00
while( *row != '\0' && ( *row == ' ' || *row == '\t' ) )
row++;
char* s = row;
// Find vertex delimiter and terminated the string there for conversion.
2019-01-26 19:43:42 +11:00
while( *row != '\0' && *row != ' ' && *row != '\t' )
{
2019-01-26 19:43:42 +11:00
if( *row == '/' )
*row = '\0';
row++;
}
2019-01-26 19:43:42 +11:00
if( *s == '\0' )
continue;
2019-01-26 19:43:42 +11:00
int vi = atoi( s );
data[ j++ ] = vi < 0 ? vi + vcnt : vi - 1;
if( j >= n )
return j;
}
return j;
}
2019-01-26 19:43:42 +11:00
bool rcMeshLoaderObj::load( const std::string& filename )
{
char* buf = 0;
2019-01-26 19:43:42 +11:00
FILE* fp = fopen( filename.c_str(), "rb" );
if( !fp )
return false;
2019-01-26 19:43:42 +11:00
if( fseek( fp, 0, SEEK_END ) != 0 )
{
2019-01-26 19:43:42 +11:00
fclose( fp );
return false;
}
2019-01-26 19:43:42 +11:00
long bufSize = ftell( fp );
if( bufSize < 0 )
{
2019-01-26 19:43:42 +11:00
fclose( fp );
return false;
}
2019-01-26 19:43:42 +11:00
if( fseek( fp, 0, SEEK_SET ) != 0 )
{
2019-01-26 19:43:42 +11:00
fclose( fp );
return false;
}
buf = new char[bufSize];
2019-01-26 19:43:42 +11:00
if( !buf )
{
2019-01-26 19:43:42 +11:00
fclose( fp );
return false;
}
2019-01-26 19:43:42 +11:00
size_t readLen = fread( buf, bufSize, 1, fp );
fclose( fp );
2019-01-26 19:43:42 +11:00
if( readLen != 1 )
{
delete[] buf;
return false;
}
char* src = buf;
char* srcEnd = buf + bufSize;
char row[512];
int face[32];
2019-01-26 19:43:42 +11:00
float x, y, z;
int nv;
int vcap = 0;
int tcap = 0;
2019-01-26 19:43:42 +11:00
while( src < srcEnd )
{
// Parse one row
2019-01-26 19:43:42 +11:00
row[ 0 ] = '\0';
src = parseRow( src, srcEnd, row, sizeof( row ) / sizeof( char ) );
// Skip comments
2019-01-26 19:43:42 +11:00
if( row[ 0 ] == '#' )
continue;
if( row[ 0 ] == 'v' && row[ 1 ] != 'n' && row[ 1 ] != 't' )
{
// Vertex pos
2019-01-26 19:43:42 +11:00
sscanf( row + 1, "%f %f %f", &x, &y, &z );
addVertex( x, y, z, vcap );
}
2019-01-26 19:43:42 +11:00
if( row[ 0 ] == 'f' )
{
// Faces
2019-01-26 19:43:42 +11:00
nv = parseFace( row + 1, face, 32, m_vertCount );
for( int i = 2; i < nv; ++i )
{
2019-01-26 19:43:42 +11:00
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;
2019-01-26 19:43:42 +11:00
addTriangle( a, b, c, tcap );
}
}
}
2019-01-26 19:43:42 +11:00
delete[] buf;
// Calculate normals.
2019-01-26 19:43:42 +11:00
m_normals = new float[m_triCount * 3];
for( int i = 0; i < m_triCount * 3; i += 3 )
{
2019-01-26 19:43:42 +11:00
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];
2019-01-26 19:43:42 +11:00
for( int j = 0; j < 3; ++j )
{
2019-01-26 19:43:42 +11:00
e0[ j ] = v1[ j ] - v0[ j ];
e1[ j ] = v2[ j ] - v0[ j ];
}
2019-01-26 19:43:42 +11:00
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 )
{
2019-01-26 19:43:42 +11:00
d = 1.0f / d;
n[ 0 ] *= d;
n[ 1 ] *= d;
n[ 2 ] *= d;
}
}
m_filename = filename;
return true;
}