]>
Dogcows Code - chaz/yoink/blob - src/moof/mesh.cc
32550f7fcfb3361aff55ea7e2748c0c2c62531df
2 /*] Copyright (c) 2009-2011, Charles McGarvey [*****************************
3 **] All rights reserved.
5 * Distributable under the terms and conditions of the 2-clause BSD license;
6 * see the file COPYING for a complete text of the license.
8 *****************************************************************************/
16 #include <boost/algorithm/string/trim.hpp>
24 // TODO: this file needs to be cleaned up
26 #define AC3D_FORMAT_VERSION 0x0b
27 #define ZLIB_BUF_SIZE 262114
33 MOOF_REGISTER_RESOURCE(mesh
, ac
, models
);
35 static std::string
read_string(std::istream
& stream
)
41 while (stream
&& std::isspace(atom
));
47 if (atom
== '"') break;
56 if (std::isspace(atom
)) break;
65 static int read_hex(std::istream
& stream
)
68 std::ios::fmtflags flags
= stream
.flags();
69 stream
.setf(std::ios::hex
, std::ios::basefield
);
75 static vector2
read_pair(std::istream
& stream
)
78 stream
>> triplet
[0] >> triplet
[1];
82 static vector3
read_triplet(std::istream
& stream
)
85 stream
>> triplet
[0] >> triplet
[1] >> triplet
[2];
89 static vector4
read_color(std::istream
& stream
)
92 stream
>> color
[0] >> color
[1] >> color
[2];
93 color
[3] = SCALAR(1.0);
97 void mesh::import(std::istream
& stream
)
101 std::stack
<int> kids
;
103 // read and verify the AC3D header
106 unsigned version
= 0;
108 stream
.get(magic
, sizeof(magic
));
109 if (!stream
|| strncmp(magic
, "AC3D", 4) != 0)
111 throw std::runtime_error("invalid mesh header");
114 version
= read_hex(stream
);
115 if (version
> AC3D_FORMAT_VERSION
)
117 throw std::runtime_error("wrong mesh file format version");
126 if (atom
== "MATERIAL")
128 materials_
.push_back(material(read_string(stream
)));
131 materials_
.back().diffuse
= read_color(stream
);
133 materials_
.back().ambient
= read_color(stream
);
135 materials_
.back().emissive
= read_color(stream
);
137 materials_
.back().specular
= read_color(stream
);
139 stream
>> atom
>> materials_
.back().shininess
;
140 stream
>> atom
>> materials_
.back().diffuse
[3];
141 materials_
.back().diffuse
[3] = SCALAR(1.0) -
142 materials_
.back().diffuse
[3];
144 else if (atom
== "OBJECT")
147 if (atom
!= "world" && atom
!= "group" && atom
!= "poly")
149 throw std::runtime_error("unexpected object type " + atom
);
152 object_ptr newObj
= object::alloc(*this);
156 obj
->kids
.push_back(newObj
);
157 newObj
->parent
= obj
;
161 objects_
.push_back(newObj
);
166 else if (atom
== "name")
170 obj
->name
= read_string(stream
);
171 object_ptr parent
= obj
->parent
.lock();
172 if (parent
) parent
->kids_byname
.insert(std::make_pair(obj
->name
, obj
));
174 else throw std::runtime_error("unexpected atom: " + atom
);
176 else if (atom
== "data")
178 std::getline(stream
, atom
);
179 std::getline(stream
, obj
? obj
->data
: atom
);
181 else if (atom
== "texture")
183 if (obj
) obj
->texture
= resource::load(read_string(stream
));
185 else if (atom
== "texrep")
187 if (obj
) obj
->texrep
= read_pair(stream
);
188 else throw std::runtime_error("unexpected atom: " + atom
);
190 else if (atom
== "rot")
193 std::getline(stream
, atom
);
195 else if (atom
== "loc")
198 std::getline(stream
, atom
);
200 else if (atom
== "url")
202 if (obj
) std::getline(stream
, obj
->url
);
203 else throw std::runtime_error("unexpected atom: " + atom
);
205 else if (atom
== "numvert")
207 if (!obj
) throw std::runtime_error("unexpected atom: " + atom
);
212 for (int i
= 0; i
< numvert
; ++i
)
214 obj
->verts
.push_back(read_triplet(stream
));
217 else if (atom
== "numsurf")
219 if (!obj
) throw std::runtime_error("unexpected atom: " + atom
);
224 for (int i
= 0; i
< numsurf
; ++i
)
227 if (atom
!= "SURF") throw std::runtime_error("uh oh");
233 if (atom
== "mat") stream
>> material
>> atom
;
237 throw std::runtime_error("blaaaaaaaahhh!!");
242 ASSERT(numrefs
>= 3);
244 if ((int)obj
->faces
.size() <= material
)
246 obj
->faces
.resize(material
+ 1);
248 material_group
& face
= obj
->faces
[material
];
252 vector2 uv
= read_pair(stream
);
253 if (vert
< face
.triangles_uv
.size())
255 if (uv
!= face
.triangles_uv
[vert
])
257 obj
->verts
.push_back(obj
->verts
[vert
]);
258 face
.triangles_uv
.resize(obj
->verts
.size());
259 vert
= obj
->verts
.size() - 1;
262 else face
.triangles_uv
.resize(vert
+ 1);
263 face
.triangles_uv
[vert
] = uv
;
264 face
.triangles
.push_back(vert
);
266 unsigned first
= vert
;
269 uv
= read_pair(stream
);
270 if (vert
< face
.triangles_uv
.size())
272 if (uv
!= face
.triangles_uv
[vert
])
274 obj
->verts
.push_back(obj
->verts
[vert
]);
275 face
.triangles_uv
.resize(obj
->verts
.size());
276 vert
= obj
->verts
.size() - 1;
279 else face
.triangles_uv
.resize(vert
+ 1);
280 face
.triangles_uv
[vert
] = uv
;
281 face
.triangles
.push_back(vert
);
284 uv
= read_pair(stream
);
285 if (vert
< face
.triangles_uv
.size())
287 if (uv
!= face
.triangles_uv
[vert
])
289 obj
->verts
.push_back(obj
->verts
[vert
]);
290 face
.triangles_uv
.resize(obj
->verts
.size());
291 vert
= obj
->verts
.size() - 1;
294 else face
.triangles_uv
.resize(vert
+ 1);
295 face
.triangles_uv
[vert
] = uv
;
296 face
.triangles
.push_back(vert
);
298 unsigned last
= vert
;
300 for (int j
= 3; j
< numrefs
; ++j
)
302 face
.triangles
.push_back(first
);
303 face
.triangles
.push_back(last
);
306 uv
= read_pair(stream
);
307 if (vert
< face
.triangles_uv
.size())
309 if (uv
!= face
.triangles_uv
[vert
])
311 obj
->verts
.push_back(obj
->verts
[vert
]);
312 face
.triangles_uv
.resize(obj
->verts
.size());
313 vert
= obj
->verts
.size() - 1;
316 else face
.triangles_uv
.resize(vert
+ 1);
317 face
.triangles_uv
[vert
] = uv
;
318 face
.triangles
.push_back(vert
);
320 last
= face
.triangles
.back();
324 else if (atom
== "kids")
326 //while (0 < kids.size())
328 //if (--kids.top() <= 0)
330 //ASSERT(obj && "should be an object");
339 if (0 < numkids
) kids
.push(numkids
);
342 if (0 < kids
.size() && 0 < --kids
.top()) kids
.pop();
343 obj
= obj
->parent
.lock();
350 //unsigned mesh::read_vertex_line(std::istream& stream)
354 //vector2 uv = read_pair(stream);
355 //if (vert < face.triangles_uv.size())
357 //if (uv != face.triangles_uv[vert])
359 //obj->verts.push_back(obj->verts[vert]);
360 //face.triangles_uv.resize(obj->verts.size());
361 //vert = obj->verts.size() - 1;
364 //else face.triangles_uv.resize(vert + 1);
365 //face.triangles_uv[vert] = uv;
366 //face.triangles.push_back(vert);
369 mesh::mesh(const std::string
& path
)
371 std::ifstream
file(path
.c_str(), std::ifstream::in
|
372 std::ifstream::binary
);
373 if (!file
) throw std::runtime_error("cannot find mesh file");
375 // if we can read the header, the file isn't compressed
377 file
.get(magic
, sizeof(magic
));
378 if (strncmp(magic
, "AC3D", 4) == 0)
380 log_info("text mesh detected");
381 file
.seekg(std::ios::beg
);
386 log_info("compressed mesh detected");
387 file
.seekg(std::ios::beg
);
389 std::stringstream stream
;
390 char in
[ZLIB_BUF_SIZE
];
391 char out
[ZLIB_BUF_SIZE
];
395 zstream
.zalloc
= Z_NULL
;
396 zstream
.zfree
= Z_NULL
;
397 zstream
.opaque
= Z_NULL
;
398 zstream
.avail_in
= 0;
399 zstream
.next_in
= Z_NULL
;
401 int result
= inflateInit2(&zstream
, 32+MAX_WBITS
);
403 throw std::runtime_error("zlib init error");
406 file
.read(in
, sizeof(in
));
407 zstream
.next_in
= (Bytef
*)in
;
408 zstream
.avail_in
= file
.gcount();
410 if (zstream
.avail_in
== 0) break;
413 zstream
.next_out
= (Bytef
*)out
;
414 zstream
.avail_out
= sizeof(out
);
416 result
= inflate(&zstream
, Z_NO_FLUSH
);
422 inflateEnd(&zstream
);
423 throw std::runtime_error("zlib inflate error");
425 throw std::runtime_error("zlib stream error");
428 int inflated
= sizeof(out
) - zstream
.avail_out
;
429 stream
.write(out
, inflated
);
431 while (zstream
.avail_out
== 0);
433 while(result
!= Z_STREAM_END
);
435 inflateEnd(&zstream
);
440 void mesh::draw(scalar alpha
) const
442 glEnableClientState(GL_VERTEX_ARRAY
);
444 std::vector
<object_ptr
>::const_iterator it
;
445 for (it
= objects_
.begin(); it
!= objects_
.end(); ++it
)
450 // TODO: disable vertex array?
453 void mesh::set_material(int index
) const
455 set_material(materials_
[index
]);
458 void mesh::set_material(const material
& material
) const
460 glColor(material
.diffuse
);
461 glMaterial(GL_FRONT
, GL_DIFFUSE
, material
.diffuse
);
462 glMaterial(GL_FRONT
, GL_AMBIENT
, material
.ambient
);
463 glMaterial(GL_FRONT
, GL_SPECULAR
, material
.specular
);
464 glMaterial(GL_FRONT
, GL_EMISSION
, material
.emissive
);
465 glMaterial(GL_FRONT
, GL_SHININESS
, material
.shininess
);
468 void mesh::object::draw(scalar alpha
, bool recurse
) const
470 glVertexPointer(verts
);
475 glEnableClientState(GL_TEXTURE_COORD_ARRAY
);
479 image::reset_binding();
480 glDisableClientState(GL_TEXTURE_COORD_ARRAY
);
483 for (size_t i
= 0; i
< faces
.size(); ++i
)
485 const material_group
& face
= faces
[i
];
486 if (face
.triangles
.size() == 0) continue;
488 mesh
.set_material(i
);
490 if (texture
) glTexCoordPointer(face
.triangles_uv
);
491 glDrawElements(GL_TRIANGLES
, face
.triangles
);
496 std::vector
<object_ptr
>::const_iterator jt
;
497 for (jt
= kids
.begin(); jt
!= kids
.end(); ++jt
)
502 //class mesh_resource_loader
506 //mesh_resource_loader()
508 //resource::register_type<mesh>("ac", "models");
511 //~mesh_resource_loader()
513 //resource::unregister_type("ac");
517 //static mesh_resource_loader loader;
This page took 0.049747 seconds and 3 git commands to generate.