Project::OSiRiON - Git repositories
Project::OSiRiON
News . About . Screenshots . Downloads . Forum . Wiki . Tracker . Git
summaryrefslogtreecommitdiff
path: root/src/model
diff options
context:
space:
mode:
authorStijn Buys <ingar@osirion.org>2009-11-02 17:15:51 +0000
committerStijn Buys <ingar@osirion.org>2009-11-02 17:15:51 +0000
commita2dbf6d70f4868165bd412aa50eb8943f99b80ba (patch)
treeb66bff69466e8d8cfffbd94750eeaee64f8ed8d7 /src/model
parenta1e67a1a6cf677a1eb937fc12954a06aa4a41c34 (diff)
ASE loader: support for multiple *GEOM objects and multiple materials
Diffstat (limited to 'src/model')
-rw-r--r--src/model/asefile.cc256
-rw-r--r--src/model/asefile.h47
2 files changed, 237 insertions, 66 deletions
diff --git a/src/model/asefile.cc b/src/model/asefile.cc
index 3bf0d59..06e10dc 100644
--- a/src/model/asefile.cc
+++ b/src/model/asefile.cc
@@ -20,14 +20,20 @@ ASEFile::ASEFile(std::string const &name)
{
asefile_name.append(name);
asefile_name.append(".ase");
-
asefile_ifs.open(asefile_name);
for (int i = 0; i < 3; i++) {
- ase_minbbox[i] = MAX_BOUNDS;
- ase_maxbbox[i] = -MAX_BOUNDS;
+ ase_minbbox[i] = 0;
+ ase_maxbbox[i] = 0;
}
+ // a single fragmentgroup wil contain all the model triangles
+ ase_fragmentgroup = new FragmentGroup();
+ ase_fragmentgroup->set_type(FragmentGroup::None);
+
+ // reset counters
+ ase_vertexcount = 0;
+ ase_facecount = 0 ;
}
ASEFile::~ASEFile()
@@ -47,6 +53,11 @@ ASEFile::~ASEFile()
}
ase_facelist.clear();
+ for (MaterialList::iterator it = ase_materiallist.begin(); it != ase_materiallist.end(); it++) {
+ (*it).second = 0;
+ }
+ ase_materiallist.clear();
+
if (asefile_ifs.is_open())
asefile_ifs.close();
}
@@ -75,10 +86,91 @@ bool ASEFile::read_header(std::istream &is)
return true;
}
-bool ASEFile::read_mesh_vertex_list(std::istream &is)
+Material *ASEFile::read_material(std::istream &is)
{
- size_t count = 0;
+ Material *material = 0;
+ char data[1024];
+ memset(data, 0, sizeof(data));
+ int level = 1;
+
+ while (is.getline(data, sizeof(data) - 1)) {
+
+ std::istringstream line(data);
+ std::string word;
+ line >> word;
+
+ if ((level == 1) && (word.compare("*MATERIAL_NAME") == 0)) {
+ // read material name
+ std::string n;
+ char c;
+ while ((line.get(c)) && (c != '"'));
+ while ((line.get(c)) && (c != '"'))
+ n += c;
+
+ // find material
+ material = Material::find(n);
+ if (!material) {
+ material = new Material(n);
+ Material::add(material);
+ material->set_texture(material->name());
+ }
+
+ } else {
+ do {
+ if (word.compare("{") == 0) {
+ level++;
+ } else if (word.compare("}") == 0) {
+ level--;
+ }
+ } while (line >> word);
+ }
+
+ if (level == 0)
+ return material;
+ }
+
+ return material;
+}
+bool ASEFile::read_material_list(std::istream &is)
+{
+ char data[1024];
+ memset(data, 0, sizeof(data));
+ int level = 1;
+
+ while (is.getline(data, sizeof(data) - 1)) {
+
+ std::istringstream line(data);
+ std::string word;
+ size_t index;
+ line >> word;
+
+ if ((level == 1) && (word.compare("*MATERIAL") == 0)) {
+ if ((line >> index) && (line >> word) && (word.compare("{") == 0)) {
+ // add material to the ase material list
+ ase_materiallist[index] = read_material(is);
+ con_debug << " " << name() << " " << "*MATERIAL " << index << " " << ase_materiallist[index]->name() << std::endl;
+ }
+
+ } else {
+ do {
+ if (word.compare("{") == 0) {
+ level++;
+ } else if (word.compare("}") == 0) {
+ level--;
+ }
+ } while (line >> word);
+ }
+
+ if (level == 0)
+ return true;
+ }
+
+ return false;
+}
+
+bool ASEFile::read_mesh_vertex_list(std::istream &is)
+{
char data[1024];
memset(data, 0, sizeof(data));
@@ -89,8 +181,6 @@ bool ASEFile::read_mesh_vertex_list(std::istream &is)
line >> firstword;
if (firstword.compare("}") == 0) {
- //con_debug << " " << count << " mesh vertices" << std::endl;
-
return true;
} else if (firstword.compare("*MESH_VERTEX") == 0) {
@@ -108,7 +198,7 @@ bool ASEFile::read_mesh_vertex_list(std::istream &is)
ase_minbbox[i] = (*v)[i];
}
}
- count++;
+ ase_vertexcount++;
}
}
}
@@ -118,8 +208,6 @@ bool ASEFile::read_mesh_vertex_list(std::istream &is)
bool ASEFile::read_mesh_face_list(std::istream &is)
{
- size_t count = 0;
-
char data[1024];
memset(data, 0, sizeof(data));
@@ -130,7 +218,6 @@ bool ASEFile::read_mesh_face_list(std::istream &is)
line >> word;
if (word.compare("}") == 0) {
- //con_debug << " " << count << " mesh faces" << std::endl;
return true;
} else if (word.compare("*MESH_FACE") == 0) {
@@ -152,7 +239,7 @@ bool ASEFile::read_mesh_face_list(std::istream &is)
Triangle *triangle = new Triangle(*ase_vertexlist[a], *ase_vertexlist[b], *ase_vertexlist[c]);
ase_facelist[index] = triangle;
}
- count++;
+ ase_facecount++;
}
}
@@ -227,7 +314,7 @@ bool ASEFile::read_mesh_tvertex_list(std::istream &is)
line >> firstword;
if (firstword.compare("}") == 0) {
- //con_debug << " " << count << " texture vertices" << std::endl;
+ con_debug << " " << count << " texture vertices" << std::endl;
return true;
} else if (firstword.compare("*MESH_TVERT") == 0) {
@@ -258,10 +345,11 @@ bool ASEFile::read_mesh_tface_list(std::istream &is)
line >> firstword;
if (firstword.compare("}") == 0) {
- //con_debug << " " << count << " face texture coordinates" << std::endl;
+ con_debug << " " << count << " face texture coordinates" << std::endl;
return true;
} else if (firstword.compare("*MESH_TFACE") == 0) {
+ // face texture coordinates
size_t index, a, b, c;
if (line >> index >> a >> b >> c) {
Triangle *triangle = ase_facelist[index];
@@ -300,31 +388,31 @@ bool ASEFile::read_mesh(std::istream &is)
if ((level == 1) && (word.compare("*MESH_VERTEX_LIST") == 0)) {
if ((line >> word) && (word.compare("{") == 0)) {
- //con_debug << " " << name() << " *MESH_VERTEX_LIST" << std::endl;
+ con_debug << " " << name() << " *MESH_VERTEX_LIST" << std::endl;
read_mesh_vertex_list(is);
}
} else if ((level == 1) && (word.compare("*MESH_FACE_LIST") == 0)) {
if ((line >> word) && (word.compare("{") == 0)) {
- //con_debug << " " << name() << " *MESH_FACE_LIST" << std::endl;
+ con_debug << " " << name() << " *MESH_FACE_LIST" << std::endl;
read_mesh_face_list(is);
}
} else if ((level == 1) && (word.compare("*MESH_NORMALS") == 0)) {
if ((line >> word) && (word.compare("{") == 0)) {
- //con_debug << " " << name() << " *MESH_NORMALS" << std::endl;
+ con_debug << " " << name() << " *MESH_NORMALS" << std::endl;
read_mesh_normals(is);
}
} else if ((level == 1) && (word.compare("*MESH_TVERTLIST") == 0)) {
if ((line >> word) && (word.compare("{") == 0)) {
- //con_debug << " " << name() << " *MESH_TVERTLIST" << std::endl;
+ con_debug << " " << name() << " *MESH_TVERTLIST" << std::endl;
read_mesh_tvertex_list(is);
}
} else if ((level == 1) && (word.compare("*MESH_TFACELIST") == 0)) {
if ((line >> word) && (word.compare("{") == 0)) {
- //con_debug << " " << name() << " *MESH_TFACELIST" << std::endl;
+ con_debug << " " << name() << " *MESH_TFACELIST" << std::endl;
read_mesh_tface_list(is);
}
@@ -346,24 +434,59 @@ bool ASEFile::read_mesh(std::istream &is)
return false;
}
+bool ASEFile::clear_geom()
+{
+ // delete texture vertices
+ for (VertexList::iterator it = ase_tvertexlist.begin(); it != ase_tvertexlist.end(); it++) {
+ delete(*it).second;
+ }
+ ase_tvertexlist.clear();
+
+ // delete geometry vertices
+ for (VertexList::iterator it = ase_vertexlist.begin(); it != ase_vertexlist.end(); it++) {
+ delete(*it).second;
+ }
+ ase_vertexlist.clear();
+
+ // delete faces
+ for (FaceList::iterator it = ase_facelist.begin(); it != ase_facelist.end(); it++) {
+ delete(*it).second;
+ }
+ ase_facelist.clear();
+
+ return true;
+}
+
bool ASEFile::read_geom(std::istream &is)
{
char data[1024];
memset(data, 0, sizeof(data));
int level = 1;
+ Material *material = 0;
while (is.getline(data, sizeof(data) - 1)) {
std::istringstream line(data);
std::string word;
+ size_t index;
line >> word;
if ((level == 1) && (word.compare("*MESH") == 0)) {
if ((line >> word) && (word.compare("{") == 0)) {
- //con_debug << " " << name() << " " << "*MESH" << std::endl;
+ con_debug << " " << name() << " " << "*MESH" << std::endl;
read_mesh(is);
}
-
+ } else if ((level == 1) && (word.compare("*MATERIAL_REF") == 0)) {
+ // the material to use for this GEOMOBJECT
+ if (line >> index) {
+ con_debug << " " << name() << " " << "*MATERIAL_REF " << index << std::endl;
+
+ // find the Material for index
+ MaterialList::iterator it = ase_materiallist.find(index);
+ if (it != ase_materiallist.end()) {
+ material = (*it).second;
+ }
+ }
} else {
do {
if (word.compare("{") == 0) {
@@ -374,10 +497,29 @@ bool ASEFile::read_geom(std::istream &is)
} while (line >> word);
}
- if (level == 0)
+ if (level == 0) {
+
+ // import only if the material is defined and there actually are triangles to import
+ if (material && ase_facelist.size()) {
+ // load GEOMOBJECT triangles in a model fragment
+ Fragment *fragment = new Fragment(Fragment::Triangles, material);
+ ase_fragmentgroup->add_fragment(fragment);
+
+ for (FaceList::iterator it = ase_facelist.begin(); it != ase_facelist.end(); it++) {
+ Triangle *triangle = (*it).second;
+ fragment->add_vertex((triangle->v0() * SCALE) , triangle->n0(), triangle->t0(), false);
+ fragment->add_vertex((triangle->v1() * SCALE) , triangle->n1(), triangle->t1(), false);
+ fragment->add_vertex((triangle->v2() * SCALE) , triangle->n2(), triangle->t2(), false);
+ }
+ }
+
+ // clear geometry data
+ clear_geom();
return true;
+ }
}
+ clear_geom();
return false;
}
@@ -400,16 +542,22 @@ bool ASEFile::read()
if (word.compare("*GEOMOBJECT") == 0) {
if ((line >> word) && (word.compare("{") == 0)) {
- //con_debug << " " << name() << " " << "*GEOMOBJECT" << std::endl;
+ con_debug << " " << name() << " " << "*GEOMOBJECT" << std::endl;
read_geom(asefile_ifs);
}
+ } else if (word.compare("*MATERIAL_LIST") == 0) {
+
+ if ((line >> word) && (word.compare("{") == 0)) {
+ con_debug << " " << name() << " " << "*MATERIAL_LIST" << std::endl;
+ read_material_list(asefile_ifs);
+ }
}
}
return true;
}
-Model * ASEFile::load(const std::string &name)
+Model *ASEFile::load(const std::string &name)
{
ASEFile asefile(name);
@@ -421,55 +569,31 @@ Model * ASEFile::load(const std::string &name)
return 0;
}
+ /* this is cleared by clear_geom()
if (!asefile.ase_facelist.size())
return 0;
-
+ */
+
+ // create a new model
Model *model = new Model(name);
- // default material
- Material *material = Material::find(name);
- if (!material) {
- material = new Material(name);
- Material::add(material);
- //material->set_flags(Material::Texture);
- material->set_texture(material->name());
+ // set bounding box properties
+ math::Vector3f origin(0.0f, 0.0f, 0.0f);
+ model->set_origin(origin);
+ model->model_minbbox.assign (asefile.ase_minbbox * SCALE);
+ model->model_maxbbox.assign (asefile.ase_maxbbox * SCALE);
+ model->set_radius(math::max(model->model_minbbox.length(), model->model_maxbbox.length()));
+
+ for (FragmentGroup::iterator fit = asefile.fragmentgroup()->begin(); fit != asefile.fragmentgroup()->end(); fit++) {
+ Fragment *fragment = (*fit);
+ model->model_tris_count += fragment->structural_size() + fragment->detail_size();
}
+ model->add_group(asefile.fragmentgroup());
- // a single fragment for all the model triangles
- Fragment *fragment = new Fragment(Fragment::Triangles, material);
- FragmentGroup *group = new FragmentGroup();
- group->set_type(FragmentGroup::None);
- group->add_fragment(fragment);
-
- // calculate model center
- math::Vector3f center((asefile.ase_minbbox + asefile.ase_maxbbox) * 0.5f);
-
- const float scale = SCALE;
- //const float scale = 0.125f;
-
- // caculate bounding box
- model->model_minbbox = (asefile.ase_minbbox - center) * scale;
- model->model_maxbbox = (asefile.ase_maxbbox - center) * scale;
- model->set_radius(model->model_maxbbox.length());
- model->set_origin(center * scale);
-
- // load the model faces into the fragment
- for (FaceList::iterator it = asefile.ase_facelist.begin(); it != asefile.ase_facelist.end(); it++) {
- Triangle *triangle = (*it).second;
-
- fragment->add_vertex((triangle->v0() - center) * scale , triangle->n0(), triangle->t0(), false);
- fragment->add_vertex((triangle->v1() - center) * scale , triangle->n1(), triangle->t1(), false);
- fragment->add_vertex((triangle->v2() - center) * scale , triangle->n2(), triangle->t2(), false);
-
- model->model_tris_count++;
- }
-
- model->add_group(group);
-
- con_debug << " " << asefile.name() << " " << asefile.ase_vertexlist.size() << " vertices " <<
- model->model_tris_detail_count << "/" << model->model_tris_count << " detail/tris" << std::endl;
-
+ con_debug << " " << asefile.name() << " " << asefile.vertexcount() << " vertices " << asefile.facecount() << " faces " << std::endl;
+
return model;
}
} // namespace model
+
diff --git a/src/model/asefile.h b/src/model/asefile.h
index e129ec0..d8e3aea 100644
--- a/src/model/asefile.h
+++ b/src/model/asefile.h
@@ -10,11 +10,14 @@
#include "math/vector3f.h"
#include "model/model.h"
+#include "model/material.h"
+#include "model/fragment.h"
#include "model/triangle.h"
#include "filesystem/filestream.h"
#include <string>
#include <map>
+#include <vector>
namespace model
{
@@ -31,15 +34,35 @@ public:
static Model *load(std::string const &name);
private:
+ /**
+ * @brief type definition for a list of materials in the ASE file
+ */
+ typedef std::map<size_t, Material *> MaterialList;
+ /**
+ * @brief type definition for a list of vertices in a GEOMOBJECT
+ */
typedef std::map<size_t, math::Vector3f *> VertexList;
+ /**
+ * @brief type definition for a list of faces in a GEOMOBJECT
+ */
typedef std::map<size_t, Triangle *> FaceList;
ASEFile(std::string const &name);
~ASEFile();
/**
+ * @brief read *MATERIAL
+ */
+ Material *read_material(std::istream &is);
+
+ /**
+ * @brief read *MATERIAL_LIST
+ */
+ bool read_material_list(std::istream &is);
+
+ /**
* @brief read *MESH_NORMALS
*/
bool read_mesh_normals(std::istream &is);
@@ -75,6 +98,11 @@ private:
bool read_geom(std::istream &is);
/**
+ * @brief clear *GEOMOBJECT
+ */
+ bool clear_geom();
+
+ /**
* @brief read the .ase header
*/
bool read_header(std::istream &is);
@@ -92,6 +120,18 @@ private:
return asefile_ifs.is_open();
}
+ inline size_t vertexcount() const {
+ return ase_vertexcount;
+ }
+
+ inline size_t facecount() const {
+ return ase_facecount;
+ }
+
+ inline FragmentGroup *fragmentgroup() {
+ return ase_fragmentgroup;
+ }
+
std::string asefile_name;
filesystem::IFileStream asefile_ifs;
@@ -102,9 +142,16 @@ private:
FaceList ase_facelist;
+ MaterialList ase_materiallist;
+
math::Vector3f ase_maxbbox;
math::Vector3f ase_minbbox;
+
+ FragmentGroup *ase_fragmentgroup;
+
+ size_t ase_vertexcount;
+ size_t ase_facecount;
};
} // namespace model