#include <windows.h>
#include <stdio.h>
#include <GL/gl.h>
#include "obj.h"
#define BUFFER_LENGTH 1024
#define MAX_VECTOR_SIZE 4096
#define MAX_TRIANGLE_SIZE 4096
#define MAX_MTL_SIZE 32
//----------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------
Obj * LoadObj( const char * filename )
{
FILE * fp;
char line[ BUFFER_LENGTH ];
char name[ BUFFER_LENGTH ];
int i, j;
Vector vec;
int v_no[4], vt_no[4], vn_no[4];
int count;
Mtl * curr_mtl = NULL;
//fp = fopen( "car.obj", "r" );//Load the bones from file
fp = fopen( filename, "r" );
if ( fp == NULL )
return NULL;
Obj * obj = new Obj();
obj->num_vertices = 0;
obj->num_normals = 0;
obj->num_tex_coords = 0;
obj->vertices = new Vector[ MAX_VECTOR_SIZE ];
obj->normals = new Vector[ MAX_VECTOR_SIZE ];
obj->tex_coords = new Vector[ MAX_VECTOR_SIZE ];
obj->num_triangles = 0;
obj->tri_v_no = new int[ MAX_TRIANGLE_SIZE * 3 ];
obj->tri_vn_no = new int[ MAX_TRIANGLE_SIZE * 3 ];
obj->tri_vt_no = new int[ MAX_TRIANGLE_SIZE * 3 ];
obj->tri_material = new Mtl*[ MAX_TRIANGLE_SIZE * 3 ];
obj->num_materials = 0;
obj->materials = NULL;
while ( fgets( line, BUFFER_LENGTH, fp ) != NULL )
{
if ( strncmp( line, "mtllib", 6 ) == 0 )
{
sscanf( line, "mtllib %s", name );
if ( strlen( name ) > 0 )
LoadMtl( name, obj );
}
if ( strncmp( line, "usemtl", 6 ) == 0 )
{
sscanf( line, "usemtl %s", name );
for ( i=0; i<obj->num_materials; i++ )
{
if ( strcmp( name, obj->materials[ i ]->name ) == 0 )
{
curr_mtl = obj->materials[ i ];
break;
}
}
}
if ( line[0] == 'v' )
{
if ( line[1] == 'n' )
{
sscanf( line, "vn %f %f %f", &vec.x, &vec.y, &vec.z );
if ( obj->num_normals < MAX_VECTOR_SIZE )
{
obj->normals[ obj->num_normals ] = vec;
obj->num_normals ++;
}
}
else if ( line[1] == 't' )
{
sscanf( line, "vt %f %f %f", &vec.x, &vec.y, &vec.z );
if ( obj->num_tex_coords < MAX_VECTOR_SIZE )
{
obj->tex_coords[ obj->num_tex_coords ] = vec;
obj->num_tex_coords ++;
}
}
else
{
sscanf( line, "v %f %f %f", &vec.x, &vec.y, &vec.z );
if ( obj->num_vertices < MAX_VECTOR_SIZE )
{
obj->vertices[ obj->num_vertices ] = vec;
obj->num_vertices ++;
}
}
}
if ( line[0] == 'f' )
{
count = sscanf( line, "f %i//%i %i//%i %i//%i", &v_no[0], &vn_no[0], &v_no[1], &vn_no[1], &v_no[2], &vn_no[2] );
if ( count == 6 )
{
i = obj->num_triangles * 3;
for ( j=0; j<3; j++ )
{
obj->tri_v_no[ i+j ] = v_no[ j ] - 1;
obj->tri_vn_no[ i+j ] = vn_no[ j ] - 1;
obj->tri_vt_no[ i+j ] = vt_no[ j ] - 1;
}
obj->tri_material[ obj->num_triangles ] = curr_mtl;
obj->num_triangles ++;
}
{
// ......
}
if ( obj->num_triangles >= MAX_TRIANGLE_SIZE )
break;
}
};
Vector * new_array;
new_array = new Vector[ obj->num_vertices ];
memcpy( new_array, obj->vertices, sizeof( Vector ) * obj->num_vertices );
delete[] obj->vertices;
obj->vertices = new_array;
fclose( fp );
return obj;
}
//---------------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------
void LoadMtl( const char * filename, Obj * obj )
{
FILE * fp;
char line[ BUFFER_LENGTH ];
char name[ BUFFER_LENGTH ];
Color color;
Mtl * curr_mtl = NULL;
fp = fopen( filename, "r" );
if ( fp == NULL )
return;
obj->num_materials = 0;
obj->materials = new Mtl*[ MAX_MTL_SIZE ];
while ( fgets( line, BUFFER_LENGTH, fp ) != NULL )
{
if ( strncmp( line, "newmtl", 6 ) == 0 )
{
sscanf( line, "newmtl %s", name );
if ( strlen( name ) == 0 )
continue;
curr_mtl = new Mtl();
curr_mtl->name = new char[ strlen( name ) + 1 ];
strcpy( curr_mtl->name, name );
curr_mtl->kd.r = 0.8f;
curr_mtl->kd.g = 0.8f;
curr_mtl->kd.b = 0.8f;
obj->materials[ obj->num_materials ] = curr_mtl;
obj->num_materials ++;
}
if ( line[0] == 'K' )
{
if ( line[1] == 'd' )
{
sscanf( line, "Kd %f %f %f", &color.r, &color.g, &color.b );
if ( curr_mtl )
curr_mtl->kd = color;
}
}
}
fclose( fp );
}
//--------------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------
float ScaleObj( Obj * obj, float max_size )
{
if ( !obj || ( obj->num_vertices == 0 ) )
return 0.0;
Vector min, max;
min = max = obj->vertices[ 0 ];
int i;
for ( i=0; i<obj->num_vertices; i++ )
{
const Vector & p = obj->vertices[ i ];
if ( p.x < min.x ) min.x = p.x;
if ( p.y < min.y ) min.y = p.y;
if ( p.z < min.z ) min.z = p.z;
if ( p.x > max.x ) max.x = p.x;
if ( p.y > max.y ) max.y = p.y;
if ( p.z > max.z ) max.z = p.z;
}
float size, scale;
size = ( ( max.x - min.x ) > ( max.z - min.z ) ) ? ( max.x - min.x ) : ( max.z - min.z );
scale = max_size / size;
for ( i=0; i<obj->num_vertices; i++ )
{
obj->vertices[ i ].x *= scale;
obj->vertices[ i ].y *= scale;
obj->vertices[ i ].z *= scale;
}
float object_y = min.y * scale;
return object_y;
}
//-----------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------
void RenderObj( Obj * obj )
{
int i, j, no;
Mtl * curr_mtl = NULL;
glBegin( GL_TRIANGLES );
for ( i=0; i<obj->num_triangles; i++ )
{
if ( ( obj->num_materials > 0 ) && ( obj->tri_material[ i ] != curr_mtl ) )
{
curr_mtl = obj->tri_material[ i ];
glColor3f( curr_mtl->kd.r, curr_mtl->kd.g, curr_mtl->kd.b );
}
for ( j=0; j<3; j++ )
{
no = obj->tri_vn_no[ i*3 + j ];
const Vector & vn = obj->normals[ no ];
glNormal3f( vn.x, vn.y, vn.z );
no = obj->tri_v_no[ i*3 + j ];
const Vector & v = obj->vertices[ no ];
glVertex3f( v.x, v.y, v.z );
}
}
glEnd();
}
//------------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------------------