]>
Dogcows Code - chaz/yoink/blob - src/moof/mesh.cc
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();
363 //unsigned mesh::read_vertex_line(std::istream& stream)
367 //vector2 uv = read_pair(stream);
368 //if (vert < face.triangles_uv.size())
370 //if (uv != face.triangles_uv[vert])
372 //obj->verts.push_back(obj->verts[vert]);
373 //face.triangles_uv.resize(obj->verts.size());
374 //vert = obj->verts.size() - 1;
377 //else face.triangles_uv.resize(vert + 1);
378 //face.triangles_uv[vert] = uv;
379 //face.triangles.push_back(vert);
384 mesh::mesh(const std::string
& path
)
386 std::ifstream
file(path
.c_str(), std::ifstream::in
|
387 std::ifstream::binary
);
388 if (!file
) throw std::runtime_error("cannot find mesh file");
390 // if we can read the header, the file isn't compressed
392 file
.get(magic
, sizeof(magic
));
393 if (strncmp(magic
, "AC3D", 4) == 0)
395 log_info("text mesh detected");
396 file
.seekg(std::ios::beg
);
402 log_info("compressed mesh detected");
403 file
.seekg(std::ios::beg
);
405 std::stringstream stream
;
406 char in
[ZLIB_BUF_SIZE
];
407 char out
[ZLIB_BUF_SIZE
];
411 zstream
.zalloc
= Z_NULL
;
412 zstream
.zfree
= Z_NULL
;
413 zstream
.opaque
= Z_NULL
;
414 zstream
.avail_in
= 0;
415 zstream
.next_in
= Z_NULL
;
417 int result
= inflateInit2(&zstream
, 32+MAX_WBITS
);
418 if (result
!= Z_OK
) throw std::runtime_error("zlib init error");
422 file
.read(in
, sizeof(in
));
423 zstream
.next_in
= (Bytef
*)in
;
424 zstream
.avail_in
= file
.gcount();
426 if (zstream
.avail_in
== 0) break;
430 zstream
.next_out
= (Bytef
*)out
;
431 zstream
.avail_out
= sizeof(out
);
433 result
= inflate(&zstream
, Z_NO_FLUSH
);
439 inflateEnd(&zstream
);
440 throw std::runtime_error("zlib inflate error");
442 throw std::runtime_error("zlib stream error");
445 int inflated
= sizeof(out
) - zstream
.avail_out
;
446 stream
.write(out
, inflated
);
448 while (zstream
.avail_out
== 0);
450 while(result
!= Z_STREAM_END
);
452 inflateEnd(&zstream
);
459 void mesh::draw(scalar alpha
) const
461 glEnableClientState(GL_VERTEX_ARRAY
);
463 std::vector
<object_ptr
>::const_iterator it
;
464 for (it
= objects_
.begin(); it
!= objects_
.end(); ++it
)
469 // TODO: disable vertex array?
473 void mesh::set_material(int index
) const
475 set_material(materials_
[index
]);
478 void mesh::set_material(const material
& material
) const
480 glColor(material
.diffuse
);
481 glMaterial(GL_FRONT
, GL_DIFFUSE
, material
.diffuse
);
482 glMaterial(GL_FRONT
, GL_AMBIENT
, material
.ambient
);
483 glMaterial(GL_FRONT
, GL_SPECULAR
, material
.specular
);
484 glMaterial(GL_FRONT
, GL_EMISSION
, material
.emissive
);
485 glMaterial(GL_FRONT
, GL_SHININESS
, material
.shininess
);
489 void mesh::object::draw(scalar alpha
, bool recurse
) const
491 glVertexPointer(verts
);
496 glEnableClientState(GL_TEXTURE_COORD_ARRAY
);
500 image::reset_binding();
501 glDisableClientState(GL_TEXTURE_COORD_ARRAY
);
504 for (size_t i
= 0; i
< faces
.size(); ++i
)
506 const material_group
& face
= faces
[i
];
507 if (face
.triangles
.size() == 0) continue;
509 mesh
.set_material(i
);
511 if (texture
) glTexCoordPointer(face
.triangles_uv
);
512 glDrawElements(GL_TRIANGLES
, face
.triangles
);
517 std::vector
<object_ptr
>::const_iterator jt
;
518 for (jt
= kids
.begin(); jt
!= kids
.end(); ++jt
)
526 //class mesh_resource_loader
530 //mesh_resource_loader()
532 //resource::register_type<mesh>("ac", "models");
535 //~mesh_resource_loader()
537 //resource::unregister_type("ac");
541 //static mesh_resource_loader loader;
This page took 0.061059 seconds and 4 git commands to generate.