]>
Dogcows Code - chaz/yoink/blob - src/moof/mesh.cc
023138b6df39fa8a79aa8f043b62bc5a5a58f5ea
2 /*] Copyright (c) 2009-2010, Charles McGarvey [**************************
3 **] All rights reserved.
7 * Distributable under the terms and conditions of the 2-clause BSD license;
8 * see the file COPYING for a complete text of the license.
10 **************************************************************************/
18 #include <boost/algorithm/string/trim.hpp>
21 #include <stlplus/strings/string_utilities.hpp>
28 // TODO: this file needs to be cleaned up
31 #define AC3D_FORMAT_VERSION (0x0b)
32 #define ZLIB_BUF_SIZE (262114)
38 MOOF_REGISTER_RESOURCE(mesh
, ac
, models
);
41 static std::string
read_string(std::istream
& stream
)
46 do // skip to the next non-space character
50 while (stream
&& std::isspace(atom
));
57 if (atom
== '"') break;
67 if (std::isspace(atom
)) break;
76 inline int read_hex(std::istream
& stream
)
79 std::ios::fmtflags flags
= stream
.flags();
80 stream
.setf(std::ios::hex
, std::ios::basefield
);
86 inline vector2
read_pair(std::istream
& stream
)
89 stream
>> triplet
[0] >> triplet
[1];
93 inline vector3
read_triplet(std::istream
& stream
)
96 stream
>> triplet
[0] >> triplet
[1] >> triplet
[2];
100 inline vector4
read_color(std::istream
& stream
)
103 stream
>> color
[0] >> color
[1] >> color
[2];
104 color
[3] = SCALAR(1.0);
109 void mesh::import(std::istream
& stream
)
114 std::stack
<int> kids
;
116 // read and verify the AC3D header
119 unsigned version
= 0;
121 stream
.get(magic
, sizeof(magic
));
122 if (!stream
|| strncmp(magic
, "AC3D", 4) != 0)
124 throw std::runtime_error("invalid mesh header");
127 version
= read_hex(stream
);
128 if (version
> AC3D_FORMAT_VERSION
)
130 throw std::runtime_error("wrong mesh file format version");
139 if (atom
== "MATERIAL")
141 materials_
.push_back(material(read_string(stream
)));
144 materials_
.back().diffuse
= read_color(stream
);
146 materials_
.back().ambient
= read_color(stream
);
148 materials_
.back().emissive
= read_color(stream
);
150 materials_
.back().specular
= read_color(stream
);
152 stream
>> atom
>> materials_
.back().shininess
;
153 stream
>> atom
>> materials_
.back().diffuse
[3];
154 materials_
.back().diffuse
[3] = SCALAR(1.0) -
155 materials_
.back().diffuse
[3];
157 else if (atom
== "OBJECT")
160 if (atom
!= "world" && atom
!= "group" && atom
!= "poly")
162 throw std::runtime_error("unexpected object type " + atom
);
165 object_ptr newObj
= object::alloc(*this);
169 obj
->kids
.push_back(newObj
);
170 newObj
->parent
= obj
;
174 objects_
.push_back(newObj
);
179 else if (atom
== "name")
183 obj
->name
= read_string(stream
);
184 object_ptr parent
= obj
->parent
.lock();
185 if (parent
) parent
->kids_byname
.insert(std::make_pair(obj
->name
, obj
));
187 else throw std::runtime_error("unexpected atom: " + atom
);
189 else if (atom
== "data")
191 std::getline(stream
, atom
);
192 std::getline(stream
, obj
? obj
->data
: atom
);
194 else if (atom
== "texture")
196 if (obj
) obj
->texture
= resource::load(read_string(stream
));
198 else if (atom
== "texrep")
200 if (obj
) obj
->texrep
= read_pair(stream
);
201 else throw std::runtime_error("unexpected atom: " + atom
);
203 else if (atom
== "rot")
206 std::getline(stream
, atom
);
208 else if (atom
== "loc")
211 std::getline(stream
, atom
);
213 else if (atom
== "url")
215 if (obj
) std::getline(stream
, obj
->url
);
216 else throw std::runtime_error("unexpected atom: " + atom
);
218 else if (atom
== "numvert")
220 if (!obj
) throw std::runtime_error("unexpected atom: " + atom
);
225 for (int i
= 0; i
< numvert
; ++i
)
227 obj
->verts
.push_back(read_triplet(stream
));
230 else if (atom
== "numsurf")
232 if (!obj
) throw std::runtime_error("unexpected atom: " + atom
);
237 for (int i
= 0; i
< numsurf
; ++i
)
240 if (atom
!= "SURF") throw std::runtime_error("uh oh");
246 if (atom
== "mat") stream
>> material
>> atom
;
250 throw std::runtime_error("blaaaaaaaahhh!!");
255 ASSERT(numrefs
>= 3);
257 if ((int)obj
->faces
.size() <= material
)
259 obj
->faces
.resize(material
+ 1);
261 material_group
& face
= obj
->faces
[material
];
265 vector2 uv
= read_pair(stream
);
266 if (vert
< face
.triangles_uv
.size())
268 if (uv
!= face
.triangles_uv
[vert
])
270 obj
->verts
.push_back(obj
->verts
[vert
]);
271 face
.triangles_uv
.resize(obj
->verts
.size());
272 vert
= obj
->verts
.size() - 1;
275 else face
.triangles_uv
.resize(vert
+ 1);
276 face
.triangles_uv
[vert
] = uv
;
277 face
.triangles
.push_back(vert
);
279 unsigned first
= vert
;
282 uv
= read_pair(stream
);
283 if (vert
< face
.triangles_uv
.size())
285 if (uv
!= face
.triangles_uv
[vert
])
287 obj
->verts
.push_back(obj
->verts
[vert
]);
288 face
.triangles_uv
.resize(obj
->verts
.size());
289 vert
= obj
->verts
.size() - 1;
292 else face
.triangles_uv
.resize(vert
+ 1);
293 face
.triangles_uv
[vert
] = uv
;
294 face
.triangles
.push_back(vert
);
297 uv
= read_pair(stream
);
298 if (vert
< face
.triangles_uv
.size())
300 if (uv
!= face
.triangles_uv
[vert
])
302 obj
->verts
.push_back(obj
->verts
[vert
]);
303 face
.triangles_uv
.resize(obj
->verts
.size());
304 vert
= obj
->verts
.size() - 1;
307 else face
.triangles_uv
.resize(vert
+ 1);
308 face
.triangles_uv
[vert
] = uv
;
309 face
.triangles
.push_back(vert
);
311 unsigned last
= vert
;
313 for (int j
= 3; j
< numrefs
; ++j
)
315 face
.triangles
.push_back(first
);
316 face
.triangles
.push_back(last
);
319 uv
= read_pair(stream
);
320 if (vert
< face
.triangles_uv
.size())
322 if (uv
!= face
.triangles_uv
[vert
])
324 obj
->verts
.push_back(obj
->verts
[vert
]);
325 face
.triangles_uv
.resize(obj
->verts
.size());
326 vert
= obj
->verts
.size() - 1;
329 else face
.triangles_uv
.resize(vert
+ 1);
330 face
.triangles_uv
[vert
] = uv
;
331 face
.triangles
.push_back(vert
);
333 last
= face
.triangles
.back();
337 else if (atom
== "kids")
339 //while (0 < kids.size())
341 //if (--kids.top() <= 0)
343 //ASSERT(obj && "should be an object");
352 if (0 < numkids
) kids
.push(numkids
);
355 if (0 < kids
.size() && 0 < --kids
.top()) kids
.pop();
356 obj
= obj
->parent
.lock();
361 log_warning("UNKNOWN ATOM:", atom
);
366 std::vector
<object_ptr
>::iterator meh
;
367 for (meh
= objects_
.begin(); meh
!= objects_
.end(); ++meh
)
369 object_ptr cow
= *meh
;
370 log_info("OBJ: -", cow
->name
, cow
->kids
.size());
372 std::vector
<object_ptr
>::iterator foo
;
373 for (foo
= cow
->kids
.begin(); foo
!= cow
->kids
.end(); ++foo
)
375 log_info("OBJ: -", (*foo
)->name
, (*foo
)->kids
.size());
380 //unsigned mesh::read_vertex_line(std::istream& stream)
384 //vector2 uv = read_pair(stream);
385 //if (vert < face.triangles_uv.size())
387 //if (uv != face.triangles_uv[vert])
389 //obj->verts.push_back(obj->verts[vert]);
390 //face.triangles_uv.resize(obj->verts.size());
391 //vert = obj->verts.size() - 1;
394 //else face.triangles_uv.resize(vert + 1);
395 //face.triangles_uv[vert] = uv;
396 //face.triangles.push_back(vert);
401 mesh::mesh(const std::string
& path
)
403 std::ifstream
file(path
.c_str(), std::ifstream::in
|
404 std::ifstream::binary
);
405 if (!file
) throw std::runtime_error("cannot find mesh file");
407 // if we can read the header, the file isn't compressed
409 file
.get(magic
, sizeof(magic
));
410 if (strncmp(magic
, "AC3D", 4) == 0)
412 log_info("text mesh detected");
413 file
.seekg(std::ios::beg
);
419 log_info("compressed mesh detected");
420 file
.seekg(std::ios::beg
);
422 std::stringstream stream
;
423 char in
[ZLIB_BUF_SIZE
];
424 char out
[ZLIB_BUF_SIZE
];
428 zstream
.zalloc
= Z_NULL
;
429 zstream
.zfree
= Z_NULL
;
430 zstream
.opaque
= Z_NULL
;
431 zstream
.avail_in
= 0;
432 zstream
.next_in
= Z_NULL
;
434 int result
= inflateInit2(&zstream
, 32+MAX_WBITS
);
435 if (result
!= Z_OK
) throw std::runtime_error("zlib init error");
439 file
.read(in
, sizeof(in
));
440 zstream
.next_in
= (Bytef
*)in
;
441 zstream
.avail_in
= file
.gcount();
443 if (zstream
.avail_in
== 0) break;
447 zstream
.next_out
= (Bytef
*)out
;
448 zstream
.avail_out
= sizeof(out
);
450 result
= inflate(&zstream
, Z_NO_FLUSH
);
456 inflateEnd(&zstream
);
457 throw std::runtime_error("zlib inflate error");
459 throw std::runtime_error("zlib stream error");
462 int inflated
= sizeof(out
) - zstream
.avail_out
;
463 stream
.write(out
, inflated
);
465 while (zstream
.avail_out
== 0);
467 while(result
!= Z_STREAM_END
);
469 inflateEnd(&zstream
);
476 void mesh::draw(scalar alpha
) const
478 glEnableClientState(GL_VERTEX_ARRAY
);
480 std::vector
<object_ptr
>::const_iterator it
;
481 for (it
= objects_
.begin(); it
!= objects_
.end(); ++it
)
486 // TODO: disable vertex array?
490 void mesh::set_material(int index
) const
492 set_material(materials_
[index
]);
495 void mesh::set_material(const material
& material
) const
497 glColor(material
.diffuse
);
498 glMaterial(GL_FRONT
, GL_DIFFUSE
, material
.diffuse
);
499 glMaterial(GL_FRONT
, GL_AMBIENT
, material
.ambient
);
500 glMaterial(GL_FRONT
, GL_SPECULAR
, material
.specular
);
501 glMaterial(GL_FRONT
, GL_EMISSION
, material
.emissive
);
502 glMaterial(GL_FRONT
, GL_SHININESS
, material
.shininess
);
506 void mesh::object::draw(scalar alpha
, bool recurse
) const
508 glVertexPointer(verts
);
513 glEnableClientState(GL_TEXTURE_COORD_ARRAY
);
517 image::reset_binding();
518 glDisableClientState(GL_TEXTURE_COORD_ARRAY
);
521 for (size_t i
= 0; i
< faces
.size(); ++i
)
523 const material_group
& face
= faces
[i
];
524 if (face
.triangles
.size() == 0) continue;
526 mesh
.set_material(i
);
528 if (texture
) glTexCoordPointer(face
.triangles_uv
);
529 glDrawElements(GL_TRIANGLES
, face
.triangles
);
534 std::vector
<object_ptr
>::const_iterator jt
;
535 for (jt
= kids
.begin(); jt
!= kids
.end(); ++jt
)
543 //class mesh_resource_loader
547 //mesh_resource_loader()
549 //resource::register_type<mesh>("ac", "models");
552 //~mesh_resource_loader()
554 //resource::unregister_type("ac");
558 //static mesh_resource_loader loader;
This page took 0.066706 seconds and 4 git commands to generate.