use Syoyo Fujita's Wavefront obj loader. made some performance improvements in debug mode for Visual Studio
use Maya style controls under Windows (need to fix Linux/OSX) use ALT+mouse to rotate, and mouse pick to pick objects
This commit is contained in:
88
Demos3/Wavefront/README.md
Normal file
88
Demos3/Wavefront/README.md
Normal file
@@ -0,0 +1,88 @@
|
||||
tinyobjloader
|
||||
=============
|
||||
|
||||
http://syoyo.github.io/tinyobjloader/
|
||||
|
||||
Tiny but poweful single file wavefront obj loader written in C++. No dependency except for C++ STL. It can parse 10M over polygons with moderate memory and time.
|
||||
|
||||
Good for embedding .obj loader to your (global illumination) renderer ;-)
|
||||
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||

|
||||
|
||||
tinyobjloader can successfully load 6M triangles Rungholt scene.
|
||||
http://graphics.cs.williams.edu/data/meshes.xml
|
||||
|
||||
Features
|
||||
--------
|
||||
|
||||
* Group
|
||||
* Vertex
|
||||
* Texcoord
|
||||
* Normal
|
||||
* Material
|
||||
* Unknown material attributes are treated as key-value.
|
||||
|
||||
Notes
|
||||
-----
|
||||
|
||||
Polygon is converted into triangle.
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
Licensed under 2 clause BSD.
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
std::string inputfile = "cornell_box.obj";
|
||||
std::vector<tinyobj::shape_t> shapes;
|
||||
|
||||
std::string err = tinyobj::LoadObj(shapes, inputfile.c_str());
|
||||
|
||||
if (!err.empty()) {
|
||||
std::cerr << err << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
std::cout << "# of shapes : " << shapes.size() << std::endl;
|
||||
|
||||
for (size_t i = 0; i < shapes.size(); i++) {
|
||||
printf("shape[%ld].name = %s\n", i, shapes[i].name.c_str());
|
||||
printf("shape[%ld].indices: %ld\n", i, shapes[i].mesh.indices.size());
|
||||
assert((shapes[i].mesh.indices.size() % 3) == 0);
|
||||
for (size_t f = 0; f < shapes[i].mesh.indices.size(); f++) {
|
||||
printf(" idx[%ld] = %d\n", f, shapes[i].mesh.indices[f]);
|
||||
}
|
||||
|
||||
printf("shape[%ld].vertices: %ld\n", i, shapes[i].mesh.positions.size());
|
||||
assert((shapes[i].mesh.positions.size() % 3) == 0);
|
||||
for (size_t v = 0; v < shapes[i].mesh.positions.size() / 3; v++) {
|
||||
printf(" v[%ld] = (%f, %f, %f)\n", v,
|
||||
shapes[i].mesh.positions[3*v+0],
|
||||
shapes[i].mesh.positions[3*v+1],
|
||||
shapes[i].mesh.positions[3*v+2]);
|
||||
}
|
||||
|
||||
printf("shape[%ld].material.name = %s\n", i, shapes[i].material.name.c_str());
|
||||
printf(" material.Ka = (%f, %f ,%f)\n", shapes[i].material.ambient[0], shapes[i].material.ambient[1], shapes[i].material.ambient[2]);
|
||||
printf(" material.Kd = (%f, %f ,%f)\n", shapes[i].material.diffuse[0], shapes[i].material.diffuse[1], shapes[i].material.diffuse[2]);
|
||||
printf(" material.Ks = (%f, %f ,%f)\n", shapes[i].material.specular[0], shapes[i].material.specular[1], shapes[i].material.specular[2]);
|
||||
printf(" material.Tr = (%f, %f ,%f)\n", shapes[i].material.transmittance[0], shapes[i].material.transmittance[1], shapes[i].material.transmittance[2]);
|
||||
printf(" material.Ke = (%f, %f ,%f)\n", shapes[i].material.emission[0], shapes[i].material.emission[1], shapes[i].material.emission[2]);
|
||||
printf(" material.Ns = %f\n", shapes[i].material.shininess);
|
||||
printf(" material.map_Ka = %s\n", shapes[i].material.ambient_texname.c_str());
|
||||
printf(" material.map_Kd = %s\n", shapes[i].material.diffuse_texname.c_str());
|
||||
printf(" material.map_Ks = %s\n", shapes[i].material.specular_texname.c_str());
|
||||
printf(" material.map_Ns = %s\n", shapes[i].material.normal_texname.c_str());
|
||||
std::map<std::string, std::string>::iterator it(shapes[i].material.unknown_parameter.begin());
|
||||
std::map<std::string, std::string>::iterator itEnd(shapes[i].material.unknown_parameter.end());
|
||||
for (; it != itEnd; it++) {
|
||||
printf(" material.%s = %s\n", it->first.c_str(), it->second.c_str());
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
@@ -1,205 +0,0 @@
|
||||
#include "list.h"
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
// internal helper functions
|
||||
char list_is_full(list *listo)
|
||||
{
|
||||
return(listo->item_count == listo->current_max_size);
|
||||
}
|
||||
|
||||
void list_grow(list *old_listo)
|
||||
{
|
||||
int i;
|
||||
list new_listo;
|
||||
|
||||
list_make(&new_listo, old_listo->current_max_size*2, old_listo->growable++);
|
||||
|
||||
for(i=0; i<old_listo->current_max_size; i++)
|
||||
list_add_item(&new_listo, old_listo->items[i] , old_listo->names[i]);
|
||||
|
||||
list_free(old_listo);
|
||||
|
||||
//copy new structure to old list
|
||||
old_listo->names = new_listo.names;
|
||||
old_listo->items = new_listo.items;
|
||||
old_listo->item_count = new_listo.item_count;
|
||||
old_listo->current_max_size = new_listo.current_max_size;
|
||||
old_listo->growable = new_listo.growable;
|
||||
}
|
||||
//end helpers
|
||||
|
||||
void list_make(list *listo, int start_size, char growable)
|
||||
{
|
||||
listo->names = (char**) malloc(sizeof(char*) * start_size);
|
||||
listo->items = (void**) malloc(sizeof(void*) * start_size);
|
||||
listo->item_count = 0;
|
||||
listo->current_max_size = start_size;
|
||||
listo->growable = growable;
|
||||
}
|
||||
|
||||
int list_add_item(list *listo, void *item, char *name)
|
||||
{
|
||||
int name_length;
|
||||
char *new_name;
|
||||
|
||||
if( list_is_full(listo) )
|
||||
{
|
||||
if( listo->growable )
|
||||
list_grow(listo);
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
listo->names[listo->item_count] = NULL;
|
||||
if(name != NULL)
|
||||
{
|
||||
name_length = strlen(name);
|
||||
new_name = (char*) malloc(sizeof(char) * name_length + 1);
|
||||
strncpy(new_name, name, name_length);
|
||||
listo->names[listo->item_count] = new_name;
|
||||
}
|
||||
|
||||
listo->items[listo->item_count] = item;
|
||||
listo->item_count++;
|
||||
|
||||
return listo->item_count-1;
|
||||
}
|
||||
|
||||
char* list_print_items(list *listo)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i=0; i < listo->item_count; i++)
|
||||
{
|
||||
printf("%s\n", listo->names[i]);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void* list_get_index(list *listo, int indx)
|
||||
{
|
||||
if(indx < listo->item_count)
|
||||
return listo->items[indx];
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void* list_get_item(list *listo, void *item_to_find)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
for(i=0; i < listo->item_count; i++)
|
||||
{
|
||||
if(listo->items[i] == item_to_find)
|
||||
return listo->items[i];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void* list_get_name(list *listo, char *name_to_find)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
for(i=0; i < listo->item_count; i++)
|
||||
{
|
||||
if(strncmp(listo->names[i], name_to_find, strlen(name_to_find)) == 0)
|
||||
return listo->items[i];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int list_find(list *listo, char *name_to_find)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
for(i=0; i < listo->item_count; i++)
|
||||
{
|
||||
if(strncmp(listo->names[i], name_to_find, strlen(name_to_find)) == 0)
|
||||
return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void list_delete_item(list *listo, void *item)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i=0; i < listo->item_count; i++)
|
||||
{
|
||||
if( listo->items[i] == item )
|
||||
list_delete_index(listo, i);
|
||||
}
|
||||
}
|
||||
|
||||
void list_delete_name(list *listo, char *name)
|
||||
{
|
||||
int i;
|
||||
//int j;
|
||||
//char remove = 0;
|
||||
|
||||
// int length_name = strlen(name);
|
||||
int item_name;
|
||||
|
||||
if(name == NULL)
|
||||
return;
|
||||
|
||||
for(i=0; i < listo->item_count; i++)
|
||||
{
|
||||
item_name = strlen(name);
|
||||
|
||||
if( name != NULL && (strncmp(listo->names[i], name, strlen(name)) == 0) )
|
||||
list_delete_index(listo, i);
|
||||
}
|
||||
}
|
||||
|
||||
void list_delete_index(list *listo, int indx)
|
||||
{
|
||||
int j;
|
||||
|
||||
//remove item
|
||||
if(listo->names[indx] != NULL)
|
||||
free(listo->names[indx]);
|
||||
|
||||
//restructure
|
||||
for(j=indx; j < listo->item_count-1; j++)
|
||||
{
|
||||
listo->names[j] = listo->names[j+1];
|
||||
listo->items[j] = listo->items[j+1];
|
||||
}
|
||||
|
||||
listo->item_count--;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void list_delete_all(list *listo)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i=listo->item_count-1; i>=0; i--)
|
||||
list_delete_index(listo, i);
|
||||
}
|
||||
|
||||
void list_free(list *listo)
|
||||
{
|
||||
list_delete_all(listo);
|
||||
free(listo->names);
|
||||
free(listo->items);
|
||||
}
|
||||
|
||||
void list_print_list(list *listo)
|
||||
{
|
||||
int i;
|
||||
|
||||
printf("count: %i/%i\n", listo->item_count, listo->current_max_size);
|
||||
|
||||
for(i=0; i < listo->item_count; i++)
|
||||
{
|
||||
printf("list[%i]: %s\n", i, listo->names[i]);
|
||||
}
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
#ifndef __LIST_H
|
||||
#define __LIST_H
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int item_count;
|
||||
int current_max_size;
|
||||
char growable;
|
||||
|
||||
void **items;
|
||||
char **names;
|
||||
} list;
|
||||
|
||||
void list_make(list *listo, int size, char growable);
|
||||
int list_add_item(list *listo, void *item, char *name);
|
||||
char* list_print_items(list *listo);
|
||||
void* list_get_name(list *listo, char *name);
|
||||
void* list_get_index(list *listo, int indx);
|
||||
void* list_get_item(list *listo, void *item_to_find);
|
||||
int list_find(list *listo, char *name_to_find);
|
||||
void list_delete_index(list *listo, int indx);
|
||||
void list_delete_name(list *listo, char *name);
|
||||
void list_delete_item(list *listo, void *item);
|
||||
void list_delete_all(list *listo);
|
||||
void list_print_list(list *listo);
|
||||
void list_free(list *listo);
|
||||
|
||||
void test_list();
|
||||
#endif
|
||||
107
Demos3/Wavefront/main.cpp
Normal file
107
Demos3/Wavefront/main.cpp
Normal file
@@ -0,0 +1,107 @@
|
||||
#include "tiny_obj_loader.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
|
||||
static bool
|
||||
TestLoadObj(
|
||||
const char* fileName,
|
||||
bool verbose
|
||||
)
|
||||
{
|
||||
|
||||
|
||||
const char* prefix[]={"./data/","../data/","../../data/","../../../data/","../../../../data/"};
|
||||
char fullPath[1024];
|
||||
int index=-1;
|
||||
{
|
||||
|
||||
int numPrefixes = sizeof(prefix)/sizeof(char*);
|
||||
|
||||
for (int i=0;i<numPrefixes;i++)
|
||||
{
|
||||
|
||||
sprintf(fullPath,"%s%s",prefix[i],fileName);
|
||||
FILE* f;
|
||||
f = fopen(fullPath,"r");
|
||||
if (f)
|
||||
{
|
||||
index=i;
|
||||
fclose(f);
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (index<0)
|
||||
{
|
||||
printf("file not found %s\n", fileName);
|
||||
return false;
|
||||
}
|
||||
|
||||
std::cout << "Loading " << fullPath << std::endl;
|
||||
|
||||
std::vector<tinyobj::shape_t> shapes;
|
||||
std::string err = tinyobj::LoadObj(shapes, fullPath, prefix[index]);
|
||||
|
||||
if (!err.empty()) {
|
||||
std::cerr << err << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
std::cout << "# of shapes : " << shapes.size() << std::endl;
|
||||
|
||||
if (verbose)
|
||||
{
|
||||
for (size_t i = 0; i < shapes.size(); i++) {
|
||||
printf("shape[%ld].name = %s\n", i, shapes[i].name.c_str());
|
||||
printf("shape[%ld].indices: %ld\n", i, shapes[i].mesh.indices.size());
|
||||
assert((shapes[i].mesh.indices.size() % 3) == 0);
|
||||
for (size_t f = 0; f < shapes[i].mesh.indices.size(); f++) {
|
||||
printf(" idx[%ld] = %d\n", f, shapes[i].mesh.indices[f]);
|
||||
}
|
||||
|
||||
printf("shape[%ld].vertices: %ld\n", i, shapes[i].mesh.positions.size());
|
||||
assert((shapes[i].mesh.positions.size() % 3) == 0);
|
||||
for (size_t v = 0; v < shapes[i].mesh.positions.size() / 3; v++) {
|
||||
printf(" v[%ld] = (%f, %f, %f)\n", v,
|
||||
shapes[i].mesh.positions[3*v+0],
|
||||
shapes[i].mesh.positions[3*v+1],
|
||||
shapes[i].mesh.positions[3*v+2]);
|
||||
}
|
||||
|
||||
printf("shape[%ld].material.name = %s\n", i, shapes[i].material.name.c_str());
|
||||
printf(" material.Ka = (%f, %f ,%f)\n", shapes[i].material.ambient[0], shapes[i].material.ambient[1], shapes[i].material.ambient[2]);
|
||||
printf(" material.Kd = (%f, %f ,%f)\n", shapes[i].material.diffuse[0], shapes[i].material.diffuse[1], shapes[i].material.diffuse[2]);
|
||||
printf(" material.Ks = (%f, %f ,%f)\n", shapes[i].material.specular[0], shapes[i].material.specular[1], shapes[i].material.specular[2]);
|
||||
printf(" material.Tr = (%f, %f ,%f)\n", shapes[i].material.transmittance[0], shapes[i].material.transmittance[1], shapes[i].material.transmittance[2]);
|
||||
printf(" material.Ke = (%f, %f ,%f)\n", shapes[i].material.emission[0], shapes[i].material.emission[1], shapes[i].material.emission[2]);
|
||||
printf(" material.Ns = %f\n", shapes[i].material.shininess);
|
||||
printf(" material.map_Ka = %s\n", shapes[i].material.ambient_texname.c_str());
|
||||
printf(" material.map_Kd = %s\n", shapes[i].material.diffuse_texname.c_str());
|
||||
printf(" material.map_Ks = %s\n", shapes[i].material.specular_texname.c_str());
|
||||
printf(" material.map_Ns = %s\n", shapes[i].material.normal_texname.c_str());
|
||||
std::map<std::string, std::string>::iterator it(shapes[i].material.unknown_parameter.begin());
|
||||
std::map<std::string, std::string>::iterator itEnd(shapes[i].material.unknown_parameter.end());
|
||||
for (; it != itEnd; it++) {
|
||||
printf(" material.%s = %s\n", it->first.c_str(), it->second.c_str());
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
int main( int argc, char **argv)
|
||||
{
|
||||
assert(true == TestLoadObj("cornell_box.obj",true));
|
||||
assert(true == TestLoadObj("cube.obj",true));
|
||||
assert(true==TestLoadObj("samurai_monastry.obj",false));
|
||||
assert(true==TestLoadObj("teddy2_VHACD_CHs.obj",true));
|
||||
return 0;
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
#include "objLoader.h"
|
||||
#include "obj_parser.h"
|
||||
|
||||
|
||||
int objLoader::load(char *filename)
|
||||
{
|
||||
int no_error = 1;
|
||||
no_error = parse_obj_scene(&data, filename);
|
||||
if(no_error)
|
||||
{
|
||||
this->vertexCount = data.vertex_count;
|
||||
this->normalCount = data.vertex_normal_count;
|
||||
this->textureCount = data.vertex_texture_count;
|
||||
|
||||
this->faceCount = data.face_count;
|
||||
this->sphereCount = data.sphere_count;
|
||||
this->planeCount = data.plane_count;
|
||||
|
||||
this->lightPointCount = data.light_point_count;
|
||||
this->lightDiscCount = data.light_disc_count;
|
||||
this->lightQuadCount = data.light_quad_count;
|
||||
|
||||
this->materialCount = data.material_count;
|
||||
|
||||
this->vertexList = data.vertex_list;
|
||||
this->normalList = data.vertex_normal_list;
|
||||
this->textureList = data.vertex_texture_list;
|
||||
|
||||
this->faceList = data.face_list;
|
||||
this->sphereList = data.sphere_list;
|
||||
this->planeList = data.plane_list;
|
||||
|
||||
this->lightPointList = data.light_point_list;
|
||||
this->lightDiscList = data.light_disc_list;
|
||||
this->lightQuadList = data.light_quad_list;
|
||||
|
||||
this->objectList = data.object_list;
|
||||
this->objectCount = data.object_count;
|
||||
|
||||
this->materialList = data.material_list;
|
||||
|
||||
this->camera = data.camera;
|
||||
}
|
||||
|
||||
return no_error;
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
#ifndef OBJ_LOADER_H
|
||||
#define OBJ_LOADER_H
|
||||
|
||||
#include "obj_parser.h"
|
||||
|
||||
class objLoader
|
||||
{
|
||||
public:
|
||||
objLoader() {}
|
||||
~objLoader()
|
||||
{
|
||||
delete_obj_data(&data);
|
||||
}
|
||||
|
||||
int load(char *filename);
|
||||
|
||||
obj_vector **vertexList;
|
||||
obj_vector **normalList;
|
||||
obj_vector **textureList;
|
||||
|
||||
obj_face **faceList;
|
||||
obj_sphere **sphereList;
|
||||
obj_plane **planeList;
|
||||
|
||||
obj_light_point **lightPointList;
|
||||
obj_light_quad **lightQuadList;
|
||||
obj_light_disc **lightDiscList;
|
||||
|
||||
obj_object** objectList;
|
||||
obj_material **materialList;
|
||||
|
||||
int vertexCount;
|
||||
int normalCount;
|
||||
int textureCount;
|
||||
|
||||
int faceCount;
|
||||
int sphereCount;
|
||||
int planeCount;
|
||||
|
||||
int lightPointCount;
|
||||
int lightQuadCount;
|
||||
int lightDiscCount;
|
||||
|
||||
int objectCount;
|
||||
int materialCount;
|
||||
|
||||
obj_camera *camera;
|
||||
private:
|
||||
obj_scene_data data;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,167 +0,0 @@
|
||||
// Obj_loader.cpp : Defines the entry point for the console application.
|
||||
//
|
||||
#include <stdio.h>
|
||||
#include "objLoader.h"
|
||||
|
||||
void printVector(obj_vector *v)
|
||||
{
|
||||
printf("%.2f,", v->e[0] );
|
||||
printf("%.2f,", v->e[1] );
|
||||
printf("%.2f ", v->e[2] );
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
objLoader *objData = new objLoader();
|
||||
objData->load("test.obj");
|
||||
|
||||
printf("Number of vertices: %i\n", objData->vertexCount);
|
||||
printf("Number of vertex normals: %i\n", objData->normalCount);
|
||||
printf("Number of texture coordinates: %i\n", objData->textureCount);
|
||||
printf("\n");
|
||||
|
||||
printf("Number of faces: %i\n", objData->faceCount);
|
||||
for(int i=0; i<objData->faceCount; i++)
|
||||
{
|
||||
obj_face *o = objData->faceList[i];
|
||||
printf(" face ");
|
||||
for(int j=0; j<3; j++)
|
||||
{
|
||||
printVector(objData->vertexList[ o->vertex_index[j] ]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
|
||||
printf("Number of spheres: %i\n", objData->sphereCount);
|
||||
for(int i=0; i<objData->sphereCount; i++)
|
||||
{
|
||||
obj_sphere *o = objData->sphereList[i];
|
||||
printf(" sphere ");
|
||||
printVector(objData->vertexList[ o->pos_index ]);
|
||||
printVector(objData->normalList[ o->up_normal_index ]);
|
||||
printVector(objData->normalList[ o->equator_normal_index ]);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
|
||||
printf("Number of planes: %i\n", objData->planeCount);
|
||||
for(int i=0; i<objData->planeCount; i++)
|
||||
{
|
||||
obj_plane *o = objData->planeList[i];
|
||||
printf(" plane ");
|
||||
printVector(objData->vertexList[ o->pos_index ]);
|
||||
printVector(objData->normalList[ o->normal_index]);
|
||||
printVector(objData->normalList[ o->rotation_normal_index]);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
|
||||
printf("Number of point lights: %i\n", objData->lightPointCount);
|
||||
for(int i=0; i<objData->lightPointCount; i++)
|
||||
{
|
||||
obj_light_point *o = objData->lightPointList[i];
|
||||
printf(" plight ");
|
||||
printVector(objData->vertexList[ o->pos_index ]);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
|
||||
printf("Number of disc lights: %i\n", objData->lightDiscCount);
|
||||
for(int i=0; i<objData->lightDiscCount; i++)
|
||||
{
|
||||
obj_light_disc *o = objData->lightDiscList[i];
|
||||
printf(" dlight ");
|
||||
printVector(objData->vertexList[ o->pos_index ]);
|
||||
printVector(objData->normalList[ o->normal_index ]);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
|
||||
printf("Number of quad lights: %i\n", objData->lightQuadCount);
|
||||
for(int i=0; i<objData->lightQuadCount; i++)
|
||||
{
|
||||
obj_light_quad *o = objData->lightQuadList[i];
|
||||
printf(" qlight ");
|
||||
printVector(objData->vertexList[ o->vertex_index[0] ]);
|
||||
printVector(objData->vertexList[ o->vertex_index[1] ]);
|
||||
printVector(objData->vertexList[ o->vertex_index[2] ]);
|
||||
printVector(objData->vertexList[ o->vertex_index[3] ]);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
|
||||
if(objData->camera != NULL)
|
||||
{
|
||||
printf("Found a camera\n");
|
||||
printf(" position: ");
|
||||
printVector(objData->vertexList[ objData->camera->camera_pos_index ]);
|
||||
printf("\n looking at: ");
|
||||
printVector(objData->vertexList[ objData->camera->camera_look_point_index ]);
|
||||
printf("\n up normal: ");
|
||||
printVector(objData->normalList[ objData->camera->camera_up_norm_index ]);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
|
||||
printf("Number of materials: %i\n", objData->materialCount);
|
||||
for(int i=0; i<objData->materialCount; i++)
|
||||
{
|
||||
obj_material *mtl = objData->materialList[i];
|
||||
printf(" name: %s", mtl->name);
|
||||
printf(" amb: %.2f ", mtl->amb[0]);
|
||||
printf("%.2f ", mtl->amb[1]);
|
||||
printf("%.2f\n", mtl->amb[2]);
|
||||
|
||||
printf(" diff: %.2f ", mtl->diff[0]);
|
||||
printf("%.2f ", mtl->diff[1]);
|
||||
printf("%.2f\n", mtl->diff[2]);
|
||||
|
||||
printf(" spec: %.2f ", mtl->spec[0]);
|
||||
printf("%.2f ", mtl->spec[1]);
|
||||
printf("%.2f\n", mtl->spec[2]);
|
||||
|
||||
printf(" reflect: %.2f\n", mtl->reflect);
|
||||
printf(" trans: %.2f\n", mtl->trans);
|
||||
printf(" glossy: %i\n", mtl->glossy);
|
||||
printf(" shiny: %i\n", mtl->shiny);
|
||||
printf(" refact: %.2f\n", mtl->refract_index);
|
||||
|
||||
printf(" texture: %s\n", mtl->texture_filename);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
|
||||
//vertex, normal, and texture test
|
||||
if(objData->textureCount > 2 && objData->normalCount > 2 && objData->faceCount > 2)
|
||||
{
|
||||
printf("Detailed face data:\n");
|
||||
|
||||
for(int i=0; i<3; i++)
|
||||
{
|
||||
obj_face *o = objData->faceList[i];
|
||||
printf(" face ");
|
||||
for(int j=0; j<3; j++)
|
||||
{
|
||||
printf("%i/", o->vertex_index[j] );
|
||||
printf("%i/", o->texture_index[j] );
|
||||
printf("%i ", o->normal_index[j] );
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,591 +0,0 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "obj_parser.h"
|
||||
#include "list.h"
|
||||
#include "string_extra.h"
|
||||
|
||||
#define WHITESPACE " \t\n\r"
|
||||
|
||||
void obj_free_half_list(list *listo)
|
||||
{
|
||||
list_delete_all(listo);
|
||||
free(listo->names);
|
||||
}
|
||||
|
||||
int obj_convert_to_list_index(int current_max, int index)
|
||||
{
|
||||
if(index == 0) //no index
|
||||
return -1;
|
||||
|
||||
if(index < 0) //relative to current list position
|
||||
return current_max + index;
|
||||
|
||||
return index - 1; //normal counting index
|
||||
}
|
||||
|
||||
void obj_convert_to_list_index_v(int current_max, int *indices)
|
||||
{
|
||||
for(int i=0; i<MAX_VERTEX_COUNT; i++)
|
||||
indices[i] = obj_convert_to_list_index(current_max, indices[i]);
|
||||
}
|
||||
|
||||
void obj_set_material_defaults(obj_material *mtl)
|
||||
{
|
||||
mtl->amb[0] = 0.2;
|
||||
mtl->amb[1] = 0.2;
|
||||
mtl->amb[2] = 0.2;
|
||||
mtl->diff[0] = 0.8;
|
||||
mtl->diff[1] = 0.8;
|
||||
mtl->diff[2] = 0.8;
|
||||
mtl->spec[0] = 1.0;
|
||||
mtl->spec[1] = 1.0;
|
||||
mtl->spec[2] = 1.0;
|
||||
mtl->reflect = 0.0;
|
||||
mtl->trans = 1;
|
||||
mtl->glossy = 98;
|
||||
mtl->shiny = 0;
|
||||
mtl->refract_index = 1;
|
||||
mtl->texture_filename[0] = '\0';
|
||||
}
|
||||
|
||||
int obj_parse_vertex_index(int *vertex_index, int *texture_index, int *normal_index)
|
||||
{
|
||||
char *temp_str;
|
||||
char *token;
|
||||
int vertex_count = 0;
|
||||
|
||||
|
||||
while( (token = strtok(NULL, WHITESPACE)) != NULL)
|
||||
{
|
||||
if(texture_index != NULL)
|
||||
texture_index[vertex_count] = 0;
|
||||
if(normal_index != NULL)
|
||||
normal_index[vertex_count] = 0;
|
||||
|
||||
vertex_index[vertex_count] = atoi( token );
|
||||
|
||||
if(contains(token, "//")) //normal only
|
||||
{
|
||||
temp_str = strchr(token, '/');
|
||||
temp_str++;
|
||||
normal_index[vertex_count] = atoi( ++temp_str );
|
||||
}
|
||||
else if(contains(token, "/"))
|
||||
{
|
||||
temp_str = strchr(token, '/');
|
||||
texture_index[vertex_count] = atoi( ++temp_str );
|
||||
|
||||
if(contains(temp_str, "/"))
|
||||
{
|
||||
temp_str = strchr(temp_str, '/');
|
||||
normal_index[vertex_count] = atoi( ++temp_str );
|
||||
}
|
||||
}
|
||||
|
||||
vertex_count++;
|
||||
}
|
||||
|
||||
return vertex_count;
|
||||
}
|
||||
|
||||
|
||||
obj_object* obj_parse_object(obj_growable_scene_data *scene)
|
||||
{
|
||||
obj_object* obj= (obj_object*)malloc(sizeof(obj_object));
|
||||
obj->vertex_offset = scene->vertex_list.item_count;
|
||||
obj->face_offset = scene->face_list.item_count;
|
||||
// get the name
|
||||
strncpy(obj->name, strtok(NULL, " \t"), OBJECT_NAME_SIZE);
|
||||
return obj;
|
||||
}
|
||||
|
||||
|
||||
obj_face* obj_parse_face(obj_growable_scene_data *scene)
|
||||
{
|
||||
int vertex_count;
|
||||
obj_face *face = (obj_face*)malloc(sizeof(obj_face));
|
||||
|
||||
vertex_count = obj_parse_vertex_index(face->vertex_index, face->texture_index, face->normal_index);
|
||||
obj_convert_to_list_index_v(scene->vertex_list.item_count, face->vertex_index);
|
||||
obj_convert_to_list_index_v(scene->vertex_texture_list.item_count, face->texture_index);
|
||||
obj_convert_to_list_index_v(scene->vertex_normal_list.item_count, face->normal_index);
|
||||
face->vertex_count = vertex_count;
|
||||
|
||||
return face;
|
||||
}
|
||||
|
||||
obj_sphere* obj_parse_sphere(obj_growable_scene_data *scene)
|
||||
{
|
||||
int temp_indices[MAX_VERTEX_COUNT];
|
||||
|
||||
obj_sphere *obj = (obj_sphere*)malloc(sizeof(obj_sphere));
|
||||
obj_parse_vertex_index(temp_indices, obj->texture_index, NULL);
|
||||
obj_convert_to_list_index_v(scene->vertex_texture_list.item_count, obj->texture_index);
|
||||
obj->pos_index = obj_convert_to_list_index(scene->vertex_list.item_count, temp_indices[0]);
|
||||
obj->up_normal_index = obj_convert_to_list_index(scene->vertex_normal_list.item_count, temp_indices[1]);
|
||||
obj->equator_normal_index = obj_convert_to_list_index(scene->vertex_normal_list.item_count, temp_indices[2]);
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
obj_plane* obj_parse_plane(obj_growable_scene_data *scene)
|
||||
{
|
||||
int temp_indices[MAX_VERTEX_COUNT];
|
||||
|
||||
obj_plane *obj = (obj_plane*)malloc(sizeof(obj_plane));
|
||||
obj_parse_vertex_index(temp_indices, obj->texture_index, NULL);
|
||||
obj_convert_to_list_index_v(scene->vertex_texture_list.item_count, obj->texture_index);
|
||||
obj->pos_index = obj_convert_to_list_index(scene->vertex_list.item_count, temp_indices[0]);
|
||||
obj->normal_index = obj_convert_to_list_index(scene->vertex_normal_list.item_count, temp_indices[1]);
|
||||
obj->rotation_normal_index = obj_convert_to_list_index(scene->vertex_normal_list.item_count, temp_indices[2]);
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
obj_light_point* obj_parse_light_point(obj_growable_scene_data *scene)
|
||||
{
|
||||
obj_light_point *o= (obj_light_point*)malloc(sizeof(obj_light_point));
|
||||
o->pos_index = obj_convert_to_list_index(scene->vertex_list.item_count, atoi( strtok(NULL, WHITESPACE)) );
|
||||
return o;
|
||||
}
|
||||
|
||||
obj_light_quad* obj_parse_light_quad(obj_growable_scene_data *scene)
|
||||
{
|
||||
obj_light_quad *o = (obj_light_quad*)malloc(sizeof(obj_light_quad));
|
||||
obj_parse_vertex_index(o->vertex_index, NULL, NULL);
|
||||
obj_convert_to_list_index_v(scene->vertex_list.item_count, o->vertex_index);
|
||||
|
||||
return o;
|
||||
}
|
||||
|
||||
obj_light_disc* obj_parse_light_disc(obj_growable_scene_data *scene)
|
||||
{
|
||||
int temp_indices[MAX_VERTEX_COUNT];
|
||||
|
||||
obj_light_disc *obj = (obj_light_disc*)malloc(sizeof(obj_light_disc));
|
||||
obj_parse_vertex_index(temp_indices, NULL, NULL);
|
||||
obj->pos_index = obj_convert_to_list_index(scene->vertex_list.item_count, temp_indices[0]);
|
||||
obj->normal_index = obj_convert_to_list_index(scene->vertex_normal_list.item_count, temp_indices[1]);
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
obj_vector* obj_parse_vector()
|
||||
{
|
||||
obj_vector *v = (obj_vector*)malloc(sizeof(obj_vector));
|
||||
v->e[0] = atof( strtok(NULL, WHITESPACE));
|
||||
v->e[1] = atof( strtok(NULL, WHITESPACE));
|
||||
v->e[2] = atof( strtok(NULL, WHITESPACE));
|
||||
return v;
|
||||
}
|
||||
|
||||
obj_vector* obj_parse_vector2()
|
||||
{
|
||||
obj_vector *v = (obj_vector*)malloc(sizeof(obj_vector));
|
||||
v->e[0] = atof( strtok(NULL, WHITESPACE));
|
||||
v->e[1] = atof( strtok(NULL, WHITESPACE));
|
||||
v->e[2] = 0.f;
|
||||
return v;
|
||||
}
|
||||
|
||||
void obj_parse_camera(obj_growable_scene_data *scene, obj_camera *camera)
|
||||
{
|
||||
int indices[3];
|
||||
obj_parse_vertex_index(indices, NULL, NULL);
|
||||
camera->camera_pos_index = obj_convert_to_list_index(scene->vertex_list.item_count, indices[0]);
|
||||
camera->camera_look_point_index = obj_convert_to_list_index(scene->vertex_list.item_count, indices[1]);
|
||||
camera->camera_up_norm_index = obj_convert_to_list_index(scene->vertex_normal_list.item_count, indices[2]);
|
||||
}
|
||||
|
||||
int obj_parse_mtl_file(char *filename, list *material_list)
|
||||
{
|
||||
int line_number = 0;
|
||||
char *current_token;
|
||||
char current_line[OBJ_LINE_SIZE];
|
||||
char material_open = 0;
|
||||
obj_material *current_mtl = NULL;
|
||||
FILE *mtl_file_stream;
|
||||
|
||||
// open scene
|
||||
mtl_file_stream = fopen( filename, "r");
|
||||
if(mtl_file_stream == 0)
|
||||
{
|
||||
fprintf(stderr, "Warning: cannot find material file: %s (skipping)\n", filename);
|
||||
return 0;
|
||||
}
|
||||
|
||||
list_make(material_list, 10, 1);
|
||||
|
||||
while( fgets(current_line, OBJ_LINE_SIZE, mtl_file_stream) )
|
||||
{
|
||||
current_token = strtok( current_line, " \t\n\r");
|
||||
line_number++;
|
||||
|
||||
//skip comments
|
||||
if( current_token == NULL || strequal(current_token, "//") || strequal(current_token, "#"))
|
||||
continue;
|
||||
|
||||
|
||||
//start material
|
||||
else if( strequal(current_token, "newmtl"))
|
||||
{
|
||||
material_open = 1;
|
||||
current_mtl = (obj_material*) malloc(sizeof(obj_material));
|
||||
obj_set_material_defaults(current_mtl);
|
||||
|
||||
// get the name
|
||||
strncpy(current_mtl->name, strtok(NULL, " \t"), MATERIAL_NAME_SIZE);
|
||||
list_add_item(material_list, current_mtl, current_mtl->name);
|
||||
}
|
||||
|
||||
//ambient
|
||||
else if( strequal(current_token, "Ka") && material_open)
|
||||
{
|
||||
current_mtl->amb[0] = atof( strtok(NULL, " \t"));
|
||||
current_mtl->amb[1] = atof( strtok(NULL, " \t"));
|
||||
current_mtl->amb[2] = atof( strtok(NULL, " \t"));
|
||||
}
|
||||
|
||||
//diff
|
||||
else if( strequal(current_token, "Kd") && material_open)
|
||||
{
|
||||
current_mtl->diff[0] = atof( strtok(NULL, " \t"));
|
||||
current_mtl->diff[1] = atof( strtok(NULL, " \t"));
|
||||
current_mtl->diff[2] = atof( strtok(NULL, " \t"));
|
||||
}
|
||||
|
||||
//specular
|
||||
else if( strequal(current_token, "Ks") && material_open)
|
||||
{
|
||||
current_mtl->spec[0] = atof( strtok(NULL, " \t"));
|
||||
current_mtl->spec[1] = atof( strtok(NULL, " \t"));
|
||||
current_mtl->spec[2] = atof( strtok(NULL, " \t"));
|
||||
}
|
||||
//shiny
|
||||
else if( strequal(current_token, "Ns") && material_open)
|
||||
{
|
||||
current_mtl->shiny = atof( strtok(NULL, " \t"));
|
||||
}
|
||||
//transparent
|
||||
else if( strequal(current_token, "d") && material_open)
|
||||
{
|
||||
current_mtl->trans = atof( strtok(NULL, " \t"));
|
||||
}
|
||||
//reflection
|
||||
else if( strequal(current_token, "r") && material_open)
|
||||
{
|
||||
current_mtl->reflect = atof( strtok(NULL, " \t"));
|
||||
}
|
||||
//glossy
|
||||
else if( strequal(current_token, "sharpness") && material_open)
|
||||
{
|
||||
current_mtl->glossy = atof( strtok(NULL, " \t"));
|
||||
}
|
||||
//refract index
|
||||
else if( strequal(current_token, "Ni") && material_open)
|
||||
{
|
||||
current_mtl->refract_index = atof( strtok(NULL, " \t"));
|
||||
}
|
||||
// illumination type
|
||||
else if( strequal(current_token, "illum") && material_open)
|
||||
{
|
||||
}
|
||||
// texture map
|
||||
else if( strequal(current_token, "map_Ka") && material_open)
|
||||
{
|
||||
strncpy(current_mtl->texture_filename, strtok(NULL, " \t"), OBJ_FILENAME_LENGTH);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "Unknown command '%s' in material file %s at line %i:\n\t%s\n",
|
||||
current_token, filename, line_number, current_line);
|
||||
//return 0;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(mtl_file_stream);
|
||||
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
int obj_parse_obj_file(obj_growable_scene_data *growable_data, char *filename)
|
||||
{
|
||||
FILE* obj_file_stream;
|
||||
int current_material = -1;
|
||||
char *current_token = NULL;
|
||||
char current_line[OBJ_LINE_SIZE];
|
||||
int line_number = 0;
|
||||
// open scene
|
||||
obj_file_stream = fopen( filename, "r");
|
||||
if(obj_file_stream == 0)
|
||||
{
|
||||
fprintf(stderr, "Error reading file: %s\n", filename);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
extreme_dimensions[0].x = INFINITY; extreme_dimensions[0].y = INFINITY; extreme_dimensions[0].z = INFINITY;
|
||||
extreme_dimensions[1].x = -INFINITY; extreme_dimensions[1].y = -INFINITY; extreme_dimensions[1].z = -INFINITY;
|
||||
|
||||
if(v->x < extreme_dimensions[0].x) extreme_dimensions[0].x = v->x;
|
||||
if(v->x > extreme_dimensions[1].x) extreme_dimensions[1].x = v->x;
|
||||
if(v->y < extreme_dimensions[0].y) extreme_dimensions[0].y = v->y;
|
||||
if(v->y > extreme_dimensions[1].y) extreme_dimensions[1].y = v->y;
|
||||
if(v->z < extreme_dimensions[0].z) extreme_dimensions[0].z = v->z;
|
||||
if(v->z > extreme_dimensions[1].z) extreme_dimensions[1].z = v->z;*/
|
||||
|
||||
|
||||
//parser loop
|
||||
while( fgets(current_line, OBJ_LINE_SIZE, obj_file_stream) )
|
||||
{
|
||||
current_token = strtok( current_line, " \t\n\r");
|
||||
line_number++;
|
||||
|
||||
//skip comments
|
||||
if( current_token == NULL || current_token[0] == '#')
|
||||
continue;
|
||||
|
||||
//parse objects
|
||||
else if( strequal(current_token, "v") ) //process vertex
|
||||
{
|
||||
list_add_item(&growable_data->vertex_list, obj_parse_vector(), NULL);
|
||||
}
|
||||
|
||||
else if( strequal(current_token, "vn") ) //process vertex normal
|
||||
{
|
||||
list_add_item(&growable_data->vertex_normal_list, obj_parse_vector(), NULL);
|
||||
}
|
||||
|
||||
else if( strequal(current_token, "vt") ) //process vertex texture
|
||||
{
|
||||
list_add_item(&growable_data->vertex_texture_list, obj_parse_vector2(), NULL);
|
||||
}
|
||||
|
||||
else if( strequal(current_token, "f") ) //process face
|
||||
{
|
||||
obj_face *face = obj_parse_face(growable_data);
|
||||
face->material_index = current_material;
|
||||
list_add_item(&growable_data->face_list, face, NULL);
|
||||
}
|
||||
|
||||
else if( strequal(current_token, "sp") ) //process sphere
|
||||
{
|
||||
obj_sphere *sphr = obj_parse_sphere(growable_data);
|
||||
sphr->material_index = current_material;
|
||||
list_add_item(&growable_data->sphere_list, sphr, NULL);
|
||||
}
|
||||
|
||||
else if( strequal(current_token, "pl") ) //process plane
|
||||
{
|
||||
obj_plane *pl = obj_parse_plane(growable_data);
|
||||
pl->material_index = current_material;
|
||||
list_add_item(&growable_data->plane_list, pl, NULL);
|
||||
}
|
||||
|
||||
else if( strequal(current_token, "p") ) //process point
|
||||
{
|
||||
//make a small sphere to represent the point?
|
||||
}
|
||||
|
||||
else if( strequal(current_token, "lp") ) //light point source
|
||||
{
|
||||
obj_light_point *o = obj_parse_light_point(growable_data);
|
||||
o->material_index = current_material;
|
||||
list_add_item(&growable_data->light_point_list, o, NULL);
|
||||
}
|
||||
|
||||
else if( strequal(current_token, "ld") ) //process light disc
|
||||
{
|
||||
obj_light_disc *o = obj_parse_light_disc(growable_data);
|
||||
o->material_index = current_material;
|
||||
list_add_item(&growable_data->light_disc_list, o, NULL);
|
||||
}
|
||||
|
||||
else if( strequal(current_token, "lq") ) //process light quad
|
||||
{
|
||||
obj_light_quad *o = obj_parse_light_quad(growable_data);
|
||||
o->material_index = current_material;
|
||||
list_add_item(&growable_data->light_quad_list, o, NULL);
|
||||
}
|
||||
|
||||
else if( strequal(current_token, "c") ) //camera
|
||||
{
|
||||
growable_data->camera = (obj_camera*) malloc(sizeof(obj_camera));
|
||||
obj_parse_camera(growable_data, growable_data->camera);
|
||||
}
|
||||
|
||||
else if( strequal(current_token, "usemtl") ) // usemtl
|
||||
{
|
||||
current_material = list_find(&growable_data->material_list, strtok(NULL, WHITESPACE));
|
||||
}
|
||||
|
||||
else if( strequal(current_token, "mtllib") ) // mtllib
|
||||
{
|
||||
strncpy(growable_data->material_filename, strtok(NULL, WHITESPACE), OBJ_FILENAME_LENGTH);
|
||||
obj_parse_mtl_file(growable_data->material_filename, &growable_data->material_list);
|
||||
continue;
|
||||
}
|
||||
|
||||
else if( strequal(current_token, "o") ) //object name
|
||||
{
|
||||
obj_object* obj = obj_parse_object(growable_data);
|
||||
list_add_item(&growable_data->object_list, obj, NULL);
|
||||
|
||||
}
|
||||
else if( strequal(current_token, "s") ) //smoothing
|
||||
{ }
|
||||
else if( strequal(current_token, "g") ) // group
|
||||
{ }
|
||||
|
||||
else
|
||||
{
|
||||
printf("Unknown command '%s' in scene code at line %i: \"%s\".\n",
|
||||
current_token, line_number, current_line);
|
||||
}
|
||||
}
|
||||
|
||||
fclose(obj_file_stream);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
void obj_init_temp_storage(obj_growable_scene_data *growable_data)
|
||||
{
|
||||
list_make(&growable_data->vertex_list, 10, 1);
|
||||
list_make(&growable_data->vertex_normal_list, 10, 1);
|
||||
list_make(&growable_data->vertex_texture_list, 10, 1);
|
||||
|
||||
list_make(&growable_data->face_list, 10, 1);
|
||||
list_make(&growable_data->sphere_list, 10, 1);
|
||||
list_make(&growable_data->plane_list, 10, 1);
|
||||
|
||||
list_make(&growable_data->light_point_list, 10, 1);
|
||||
list_make(&growable_data->light_quad_list, 10, 1);
|
||||
list_make(&growable_data->light_disc_list, 10, 1);
|
||||
|
||||
list_make(&growable_data->object_list,10,1);
|
||||
|
||||
list_make(&growable_data->material_list, 10, 1);
|
||||
|
||||
growable_data->camera = NULL;
|
||||
}
|
||||
|
||||
void obj_free_temp_storage(obj_growable_scene_data *growable_data)
|
||||
{
|
||||
obj_free_half_list(&growable_data->vertex_list);
|
||||
obj_free_half_list(&growable_data->vertex_normal_list);
|
||||
obj_free_half_list(&growable_data->vertex_texture_list);
|
||||
|
||||
obj_free_half_list(&growable_data->face_list);
|
||||
obj_free_half_list(&growable_data->sphere_list);
|
||||
obj_free_half_list(&growable_data->plane_list);
|
||||
|
||||
obj_free_half_list(&growable_data->light_point_list);
|
||||
obj_free_half_list(&growable_data->light_quad_list);
|
||||
obj_free_half_list(&growable_data->light_disc_list);
|
||||
|
||||
obj_free_half_list(&growable_data->object_list);
|
||||
obj_free_half_list(&growable_data->material_list);
|
||||
}
|
||||
|
||||
void delete_obj_data(obj_scene_data *data_out)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i=0; i<data_out->vertex_count; i++)
|
||||
free(data_out->vertex_list[i]);
|
||||
free(data_out->vertex_list);
|
||||
for(i=0; i<data_out->vertex_normal_count; i++)
|
||||
free(data_out->vertex_normal_list[i]);
|
||||
free(data_out->vertex_normal_list);
|
||||
for(i=0; i<data_out->vertex_texture_count; i++)
|
||||
free(data_out->vertex_texture_list[i]);
|
||||
free(data_out->vertex_texture_list);
|
||||
|
||||
for(i=0; i<data_out->face_count; i++)
|
||||
free(data_out->face_list[i]);
|
||||
free(data_out->face_list);
|
||||
for(i=0; i<data_out->sphere_count; i++)
|
||||
free(data_out->sphere_list[i]);
|
||||
free(data_out->sphere_list);
|
||||
for(i=0; i<data_out->plane_count; i++)
|
||||
free(data_out->plane_list[i]);
|
||||
free(data_out->plane_list);
|
||||
|
||||
for(i=0; i<data_out->light_point_count; i++)
|
||||
free(data_out->light_point_list[i]);
|
||||
free(data_out->light_point_list);
|
||||
for(i=0; i<data_out->light_disc_count; i++)
|
||||
free(data_out->light_disc_list[i]);
|
||||
free(data_out->light_disc_list);
|
||||
for(i=0; i<data_out->light_quad_count; i++)
|
||||
free(data_out->light_quad_list[i]);
|
||||
free(data_out->light_quad_list);
|
||||
|
||||
for(i=0; i<data_out->object_count; i++)
|
||||
free(data_out->object_list[i]);
|
||||
free(data_out->object_list);
|
||||
|
||||
|
||||
for(i=0; i<data_out->material_count; i++)
|
||||
free(data_out->material_list[i]);
|
||||
free(data_out->material_list);
|
||||
|
||||
free(data_out->camera);
|
||||
}
|
||||
|
||||
void obj_copy_to_out_storage(obj_scene_data *data_out, obj_growable_scene_data *growable_data)
|
||||
{
|
||||
data_out->vertex_count = growable_data->vertex_list.item_count;
|
||||
data_out->vertex_normal_count = growable_data->vertex_normal_list.item_count;
|
||||
data_out->vertex_texture_count = growable_data->vertex_texture_list.item_count;
|
||||
|
||||
data_out->face_count = growable_data->face_list.item_count;
|
||||
data_out->sphere_count = growable_data->sphere_list.item_count;
|
||||
data_out->plane_count = growable_data->plane_list.item_count;
|
||||
|
||||
data_out->light_point_count = growable_data->light_point_list.item_count;
|
||||
data_out->light_disc_count = growable_data->light_disc_list.item_count;
|
||||
data_out->light_quad_count = growable_data->light_quad_list.item_count;
|
||||
|
||||
data_out->material_count = growable_data->material_list.item_count;
|
||||
|
||||
data_out->vertex_list = (obj_vector**)growable_data->vertex_list.items;
|
||||
data_out->vertex_normal_list = (obj_vector**)growable_data->vertex_normal_list.items;
|
||||
data_out->vertex_texture_list = (obj_vector**)growable_data->vertex_texture_list.items;
|
||||
|
||||
data_out->face_list = (obj_face**)growable_data->face_list.items;
|
||||
data_out->sphere_list = (obj_sphere**)growable_data->sphere_list.items;
|
||||
data_out->plane_list = (obj_plane**)growable_data->plane_list.items;
|
||||
|
||||
data_out->light_point_list = (obj_light_point**)growable_data->light_point_list.items;
|
||||
data_out->light_disc_list = (obj_light_disc**)growable_data->light_disc_list.items;
|
||||
data_out->light_quad_list = (obj_light_quad**)growable_data->light_quad_list.items;
|
||||
|
||||
data_out->object_list = (obj_object**)growable_data->object_list.items;
|
||||
data_out->object_count = growable_data->object_list.item_count;
|
||||
|
||||
data_out->material_list = (obj_material**)growable_data->material_list.items;
|
||||
|
||||
data_out->camera = growable_data->camera;
|
||||
}
|
||||
|
||||
int parse_obj_scene(obj_scene_data *data_out, char *filename)
|
||||
{
|
||||
obj_growable_scene_data growable_data;
|
||||
|
||||
obj_init_temp_storage(&growable_data);
|
||||
if( obj_parse_obj_file(&growable_data, filename) == 0)
|
||||
return 0;
|
||||
|
||||
//print_vector(NORMAL, "Max bounds are: ", &growable_data->extreme_dimensions[1]);
|
||||
//print_vector(NORMAL, "Min bounds are: ", &growable_data->extreme_dimensions[0]);
|
||||
|
||||
obj_copy_to_out_storage(data_out, &growable_data);
|
||||
obj_free_temp_storage(&growable_data);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -1,159 +0,0 @@
|
||||
#ifndef OBJ_PARSER_H
|
||||
#define OBJ_PARSER_H
|
||||
|
||||
#include "list.h"
|
||||
|
||||
#define OBJ_FILENAME_LENGTH 500
|
||||
#define MATERIAL_NAME_SIZE 255
|
||||
#define OBJECT_NAME_SIZE 255
|
||||
|
||||
#define OBJ_LINE_SIZE 500
|
||||
#define MAX_VERTEX_COUNT 4 //can only handle quads or triangles
|
||||
|
||||
|
||||
|
||||
typedef struct obj_face
|
||||
{
|
||||
int vertex_index[MAX_VERTEX_COUNT];
|
||||
int normal_index[MAX_VERTEX_COUNT];
|
||||
int texture_index[MAX_VERTEX_COUNT];
|
||||
int vertex_count;
|
||||
int material_index;
|
||||
};
|
||||
|
||||
typedef struct obj_sphere
|
||||
{
|
||||
int pos_index;
|
||||
int up_normal_index;
|
||||
int equator_normal_index;
|
||||
int texture_index[MAX_VERTEX_COUNT];
|
||||
int material_index;
|
||||
};
|
||||
|
||||
typedef struct obj_plane
|
||||
{
|
||||
int pos_index;
|
||||
int normal_index;
|
||||
int rotation_normal_index;
|
||||
int texture_index[MAX_VERTEX_COUNT];
|
||||
int material_index;
|
||||
};
|
||||
|
||||
typedef struct obj_vector
|
||||
{
|
||||
double e[3];
|
||||
};
|
||||
|
||||
typedef struct obj_material
|
||||
{
|
||||
char name[MATERIAL_NAME_SIZE];
|
||||
char texture_filename[OBJ_FILENAME_LENGTH];
|
||||
double amb[3];
|
||||
double diff[3];
|
||||
double spec[3];
|
||||
double reflect;
|
||||
double refract;
|
||||
double trans;
|
||||
double shiny;
|
||||
double glossy;
|
||||
double refract_index;
|
||||
};
|
||||
|
||||
typedef struct obj_camera
|
||||
{
|
||||
int camera_pos_index;
|
||||
int camera_look_point_index;
|
||||
int camera_up_norm_index;
|
||||
};
|
||||
|
||||
typedef struct obj_light_point
|
||||
{
|
||||
int pos_index;
|
||||
int material_index;
|
||||
};
|
||||
|
||||
typedef struct obj_light_disc
|
||||
{
|
||||
int pos_index;
|
||||
int normal_index;
|
||||
int material_index;
|
||||
};
|
||||
|
||||
typedef struct obj_light_quad
|
||||
{
|
||||
int vertex_index[MAX_VERTEX_COUNT];
|
||||
int material_index;
|
||||
};
|
||||
|
||||
typedef struct obj_object
|
||||
{
|
||||
int vertex_offset;
|
||||
int face_offset;
|
||||
char name[OBJECT_NAME_SIZE];
|
||||
};
|
||||
|
||||
typedef struct obj_growable_scene_data
|
||||
{
|
||||
// vector extreme_dimensions[2];
|
||||
char scene_filename[OBJ_FILENAME_LENGTH];
|
||||
char material_filename[OBJ_FILENAME_LENGTH];
|
||||
|
||||
list vertex_list;
|
||||
list vertex_normal_list;
|
||||
list vertex_texture_list;
|
||||
|
||||
list face_list;
|
||||
list sphere_list;
|
||||
list plane_list;
|
||||
|
||||
list light_point_list;
|
||||
list light_quad_list;
|
||||
list light_disc_list;
|
||||
|
||||
list material_list;
|
||||
|
||||
list object_list;
|
||||
|
||||
obj_camera *camera;
|
||||
};
|
||||
|
||||
typedef struct obj_scene_data
|
||||
{
|
||||
obj_vector **vertex_list;
|
||||
obj_vector **vertex_normal_list;
|
||||
obj_vector **vertex_texture_list;
|
||||
|
||||
obj_face **face_list;
|
||||
obj_sphere **sphere_list;
|
||||
obj_plane **plane_list;
|
||||
|
||||
obj_light_point **light_point_list;
|
||||
obj_light_quad **light_quad_list;
|
||||
obj_light_disc **light_disc_list;
|
||||
|
||||
obj_material **material_list;
|
||||
|
||||
obj_object** object_list;
|
||||
int object_count;
|
||||
|
||||
int vertex_count;
|
||||
int vertex_normal_count;
|
||||
int vertex_texture_count;
|
||||
|
||||
int face_count;
|
||||
int sphere_count;
|
||||
int plane_count;
|
||||
|
||||
int light_point_count;
|
||||
int light_quad_count;
|
||||
int light_disc_count;
|
||||
|
||||
int material_count;
|
||||
|
||||
obj_camera *camera;
|
||||
};
|
||||
|
||||
int parse_obj_scene(obj_scene_data *data_out, char *filename);
|
||||
void delete_obj_data(obj_scene_data *data_out);
|
||||
|
||||
#endif
|
||||
@@ -1,24 +1,23 @@
|
||||
|
||||
project "wavefrontObjLoader"
|
||||
|
||||
language "C++"
|
||||
|
||||
kind "ConsoleApp"
|
||||
targetdir "../../bin"
|
||||
|
||||
includedirs {
|
||||
".",
|
||||
}
|
||||
|
||||
project "App_WavefrontObjLoader"
|
||||
|
||||
files {
|
||||
"objTester.cpp",
|
||||
"string_extra.cpp",
|
||||
"string_extra.h",
|
||||
"objLoader.cpp",
|
||||
"objLoader.h",
|
||||
"obj_parser.cpp",
|
||||
"obj_parser.h",
|
||||
"list.cpp",
|
||||
"list.h"
|
||||
}
|
||||
kind "ConsoleApp"
|
||||
|
||||
-- defines { }
|
||||
|
||||
targetdir "../../bin"
|
||||
|
||||
includedirs
|
||||
{
|
||||
".","../../src"
|
||||
}
|
||||
|
||||
|
||||
links { "Bullet3Common" }
|
||||
|
||||
|
||||
files {
|
||||
"**.cpp",
|
||||
"**.h"
|
||||
}
|
||||
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
#include "string_extra.h"
|
||||
#include <string.h>
|
||||
|
||||
char strequal(const char *s1, const char *s2)
|
||||
{
|
||||
if(strcmp(s1, s2) == 0)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
char contains(const char *haystack, const char *needle)
|
||||
{
|
||||
if(strstr(haystack, needle) == NULL)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
#ifndef STRING_EXTRA_H
|
||||
#define STRING_EXTRA_H
|
||||
|
||||
char strequal(const char *s1, const char *s2);
|
||||
char contains(const char *haystack, const char *needle);
|
||||
|
||||
|
||||
#endif
|
||||
@@ -4,6 +4,7 @@
|
||||
// Licensed under 2-clause BSD liecense.
|
||||
//
|
||||
|
||||
// Erwin Coumans: improved performance, especially in debug mode on Visual Studio (25sec -> 4sec)
|
||||
//
|
||||
// version 0.9.5: Parse multiple group name.
|
||||
// Add support of specifying the base path to load material file.
|
||||
@@ -30,12 +31,15 @@
|
||||
namespace tinyobj {
|
||||
|
||||
struct vertex_index {
|
||||
int v_idx, vt_idx, vn_idx;
|
||||
vertex_index() {};
|
||||
vertex_index(int idx) : v_idx(idx), vt_idx(idx), vn_idx(idx) {};
|
||||
vertex_index(int vidx, int vtidx, int vnidx) : v_idx(vidx), vt_idx(vtidx), vn_idx(vnidx) {};
|
||||
|
||||
int v_idx, vt_idx, vn_idx, dummy;
|
||||
};
|
||||
struct MyIndices
|
||||
{
|
||||
int m_offset;
|
||||
int m_numIndices;
|
||||
};
|
||||
|
||||
|
||||
// for std::map
|
||||
static inline bool operator<(const vertex_index& a, const vertex_index& b)
|
||||
{
|
||||
@@ -46,11 +50,6 @@ static inline bool operator<(const vertex_index& a, const vertex_index& b)
|
||||
return false;
|
||||
}
|
||||
|
||||
struct obj_shape {
|
||||
std::vector<float> v;
|
||||
std::vector<float> vn;
|
||||
std::vector<float> vt;
|
||||
};
|
||||
|
||||
static inline bool isSpace(const char c) {
|
||||
return (c == ' ') || (c == '\t');
|
||||
@@ -119,7 +118,10 @@ static vertex_index parseTriple(
|
||||
int vnsize,
|
||||
int vtsize)
|
||||
{
|
||||
vertex_index vi(-1);
|
||||
vertex_index vi;
|
||||
vi.vn_idx = -1;
|
||||
vi.vt_idx = -1;
|
||||
vi.v_idx= -1;
|
||||
|
||||
vi.v_idx = fixIndex(atoi(token), vsize);
|
||||
token += strcspn(token, "/ \t\r");
|
||||
@@ -150,6 +152,7 @@ static vertex_index parseTriple(
|
||||
return vi;
|
||||
}
|
||||
|
||||
|
||||
static unsigned int
|
||||
updateVertex(
|
||||
std::map<vertex_index, unsigned int>& vertexCache,
|
||||
@@ -191,15 +194,18 @@ updateVertex(
|
||||
return idx;
|
||||
}
|
||||
|
||||
|
||||
static bool
|
||||
exportFaceGroupToShape(
|
||||
shape_t& shape,
|
||||
const std::vector<float> in_positions,
|
||||
const std::vector<float> in_normals,
|
||||
const std::vector<float> in_texcoords,
|
||||
const std::vector<std::vector<vertex_index> >& faceGroup,
|
||||
const std::vector<float>& in_positions,
|
||||
const std::vector<float>& in_normals,
|
||||
const std::vector<float>& in_texcoords,
|
||||
const std::vector<MyIndices >& faceGroup,
|
||||
const material_t material,
|
||||
const std::string name)
|
||||
const std::string name,
|
||||
std::vector<vertex_index>& allIndices
|
||||
)
|
||||
{
|
||||
if (faceGroup.empty()) {
|
||||
return false;
|
||||
@@ -213,28 +219,37 @@ exportFaceGroupToShape(
|
||||
std::vector<unsigned int> indices;
|
||||
|
||||
// Flatten vertices and indices
|
||||
for (size_t i = 0; i < faceGroup.size(); i++) {
|
||||
const std::vector<vertex_index>& face = faceGroup[i];
|
||||
for (size_t i = 0; i < faceGroup.size(); i++)
|
||||
{
|
||||
|
||||
vertex_index i0 = face[0];
|
||||
vertex_index i1(-1);
|
||||
vertex_index i2 = face[1];
|
||||
const MyIndices& face = faceGroup[i];
|
||||
|
||||
size_t npolys = face.size();
|
||||
vertex_index i0 = allIndices[face.m_offset];
|
||||
vertex_index i1;
|
||||
i1.vn_idx = -1;
|
||||
i1.vt_idx = -1;
|
||||
i1.v_idx= -1;
|
||||
vertex_index i2 = allIndices[face.m_offset+1];
|
||||
|
||||
// Polygon -> triangle fan conversion
|
||||
for (size_t k = 2; k < npolys; k++) {
|
||||
i1 = i2;
|
||||
i2 = face[k];
|
||||
size_t npolys = face.m_numIndices;//.size();
|
||||
|
||||
unsigned int v0 = updateVertex(vertexCache, positions, normals, texcoords, in_positions, in_normals, in_texcoords, i0);
|
||||
unsigned int v1 = updateVertex(vertexCache, positions, normals, texcoords, in_positions, in_normals, in_texcoords, i1);
|
||||
unsigned int v2 = updateVertex(vertexCache, positions, normals, texcoords, in_positions, in_normals, in_texcoords, i2);
|
||||
|
||||
indices.push_back(v0);
|
||||
indices.push_back(v1);
|
||||
indices.push_back(v2);
|
||||
}
|
||||
{
|
||||
// Polygon -> triangle fan conversion
|
||||
for (size_t k = 2; k < npolys; k++)
|
||||
{
|
||||
i1 = i2;
|
||||
i2 = allIndices[face.m_offset+k];
|
||||
|
||||
unsigned int v0 = updateVertex(vertexCache, positions, normals, texcoords, in_positions, in_normals, in_texcoords, i0);
|
||||
unsigned int v1 = updateVertex(vertexCache, positions, normals, texcoords, in_positions, in_normals, in_texcoords, i1);
|
||||
unsigned int v2 = updateVertex(vertexCache, positions, normals, texcoords, in_positions, in_normals, in_texcoords, i2);
|
||||
|
||||
indices.push_back(v0);
|
||||
indices.push_back(v1);
|
||||
indices.push_back(v2);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -253,6 +268,7 @@ exportFaceGroupToShape(
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void InitMaterial(material_t& material) {
|
||||
material.name = "";
|
||||
@@ -454,7 +470,11 @@ LoadObj(
|
||||
const char* mtl_basepath)
|
||||
{
|
||||
|
||||
shapes.clear();
|
||||
shapes.resize(0);
|
||||
std::vector<vertex_index> allIndices;
|
||||
allIndices.reserve(1024*1024);
|
||||
|
||||
MyIndices face;
|
||||
|
||||
std::stringstream err;
|
||||
|
||||
@@ -465,9 +485,14 @@ LoadObj(
|
||||
}
|
||||
|
||||
std::vector<float> v;
|
||||
v.reserve(1024*1024);
|
||||
std::vector<float> vn;
|
||||
vn.reserve(1024*1024);
|
||||
std::vector<float> vt;
|
||||
std::vector<std::vector<vertex_index> > faceGroup;
|
||||
vt.reserve(1024*1024);
|
||||
//std::vector<std::vector<vertex_index> > faceGroup;
|
||||
std::vector<MyIndices> faceGroup;
|
||||
faceGroup.reserve(1024*1024);
|
||||
std::string name;
|
||||
|
||||
// material
|
||||
@@ -540,16 +565,19 @@ LoadObj(
|
||||
token += 2;
|
||||
token += strspn(token, " \t");
|
||||
|
||||
std::vector<vertex_index> face;
|
||||
face.m_offset = allIndices.size();
|
||||
face.m_numIndices = 0;
|
||||
|
||||
while (!isNewLine(token[0])) {
|
||||
vertex_index vi = parseTriple(token, v.size() / 3, vn.size() / 3, vt.size() / 2);
|
||||
face.push_back(vi);
|
||||
allIndices.push_back(vi);
|
||||
face.m_numIndices++;
|
||||
int n = strspn(token, " \t\r");
|
||||
token += n;
|
||||
}
|
||||
|
||||
faceGroup.push_back(face);
|
||||
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -578,7 +606,7 @@ LoadObj(
|
||||
|
||||
std::string err_mtl = LoadMtl(material_map, namebuf, mtl_basepath);
|
||||
if (!err_mtl.empty()) {
|
||||
faceGroup.clear(); // for safety
|
||||
faceGroup.resize(0); // for safety
|
||||
return err_mtl;
|
||||
}
|
||||
continue;
|
||||
@@ -589,12 +617,12 @@ LoadObj(
|
||||
|
||||
// flush previous face group.
|
||||
shape_t shape;
|
||||
bool ret = exportFaceGroupToShape(shape, v, vn, vt, faceGroup, material, name);
|
||||
bool ret = exportFaceGroupToShape(shape, v, vn, vt, faceGroup, material, name,allIndices);
|
||||
if (ret) {
|
||||
shapes.push_back(shape);
|
||||
}
|
||||
|
||||
faceGroup.clear();
|
||||
faceGroup.resize(0);
|
||||
|
||||
std::vector<std::string> names;
|
||||
while (!isNewLine(token[0])) {
|
||||
@@ -620,12 +648,12 @@ LoadObj(
|
||||
|
||||
// flush previous face group.
|
||||
shape_t shape;
|
||||
bool ret = exportFaceGroupToShape(shape, v, vn, vt, faceGroup, material, name);
|
||||
bool ret = exportFaceGroupToShape(shape, v, vn, vt, faceGroup, material, name,allIndices);
|
||||
if (ret) {
|
||||
shapes.push_back(shape);
|
||||
}
|
||||
|
||||
faceGroup.clear();
|
||||
faceGroup.resize(0);
|
||||
|
||||
// @todo { multiple object name? }
|
||||
char namebuf[4096];
|
||||
@@ -641,12 +669,12 @@ LoadObj(
|
||||
}
|
||||
|
||||
shape_t shape;
|
||||
bool ret = exportFaceGroupToShape(shape, v, vn, vt, faceGroup, material, name);
|
||||
bool ret = exportFaceGroupToShape(shape, v, vn, vt, faceGroup, material, name,allIndices);
|
||||
if (ret) {
|
||||
shapes.push_back(shape);
|
||||
}
|
||||
faceGroup.clear(); // for safety
|
||||
|
||||
faceGroup.resize(0); // for safety
|
||||
|
||||
return err.str();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user