zenilib  0.5.3.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
Model.cpp
Go to the documentation of this file.
1 /* This file is part of the Zenipex Library (zenilib).
2  * Copyright (C) 2011 Mitchell Keith Bloch (bazald).
3  *
4  * zenilib is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU Lesser General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * zenilib is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public License
15  * along with zenilib. If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #include <zeni_graphics.h>
19 
20 #include <lib3ds.h>
21 
22 #if defined(_DEBUG) && defined(_WINDOWS)
23 #define DEBUG_NEW new(_NORMAL_BLOCK, __FILE__, __LINE__)
24 #define new DEBUG_NEW
25 #endif
26 
27 namespace Zeni {
28 
30  : lower_bound(0, 0, 0),
31  upper_bound(0, 0, 0),
32  started(false)
33  {
34  }
35 
36  class Model_Renderer : public Model_Visitor {
37  public:
38  virtual void operator()(const Model &model, Lib3dsMeshInstanceNode * const &node, Lib3dsMesh * const &mesh);
39 
40  void create_vertex_buffer(Vertex_Buffer * const &user_p, const Model &model, Lib3dsMeshInstanceNode * const &node, Lib3dsMesh * const &mesh);
41  };
42 
43  void Model_Renderer::create_vertex_buffer(Vertex_Buffer * const &user_p, const Model &model, Lib3dsMeshInstanceNode * const &node, Lib3dsMesh * const &mesh) {
44 #ifndef TEMP_DISABLE
45  assert(mesh);
46  assert(user_p);
47 
48  mesh->user_ptr = user_p;
49  user_p->do_normal_alignment(model.will_do_normal_alignment());
50 
51  struct l3dsv {
52  ~l3dsv() {free(normals);}
53  float (*normals)[3];
54  } ptr = {(float(*)[3])malloc(sizeof(float) * 9 * mesh->nfaces)};
55  float (*normal)[3] = ptr.normals;
56 
58 
59  /*** BEGIN NEW FLIP-TEST ***/
60 
61  const Vector3f scl_track(node ? node->scl_track.keys->value[0] : 1.0f,
62  node ? node->scl_track.keys->value[1] : 1.0f,
63  node ? node->scl_track.keys->value[2] : 1.0f);
64  const bool flip_order = scl_track.i * scl_track.j * scl_track.k < 0.0f;
65 
66  /*** END NEW FLIP-TEST ***/
67 
68  for(unsigned int i = 0; i < mesh->nfaces; ++i) {
69  Lib3dsFace *face = &mesh->faces[i];
70 
71  Lib3dsMaterial *material = 0;
72  if(face->material != -1) {
73  material = model.thun_get_file()->materials[face->material];
74  if(!material)
75  throw Model_Render_Failure();
76  }
77 
78  Material mat;
79  bool textured = false;
80 
81  if(material) {
82  const float opacity = 1.0f - material->transparency;
83  textured = material->texture1_map.name[0] != '\0' && mesh->texcos;
84 
85  if(textured) {
86  mat.ambient.a = opacity;
87  mat.diffuse.a = opacity;
88  mat.set_Texture(material->texture1_map.name);
89  }
90  else {
91  mat.ambient = Color(opacity, material->ambient[0], material->ambient[1], material->ambient[2]);
92  mat.diffuse = Color(opacity, material->diffuse[0], material->diffuse[1], material->diffuse[2]);
93  }
94 
95  mat.specular = Color(opacity, material->specular[0], material->specular[1], material->specular[2]);
96  mat.emissive = Color(opacity, 0.0f, 0.0f, 0.0f).interpolate_to(material->self_illum, mat.diffuse);
97  mat.set_shininess(material->shininess);
98  }
99 
100  const Point2f tex_offset((material ? material->texture1_map.offset[0] : 0.0f) + 0.5f,
101  (material ? material->texture1_map.offset[1] : 0.0f) + 0.5f);
102  const Point2f tex_scale(material ? material->texture1_map.scale[0] : 1.0f,
103  material ? material->texture1_map.scale[1] : 1.0f);
104 
105  Point3f pa(mesh->vertices[face->index[0]][0], mesh->vertices[face->index[0]][1], mesh->vertices[face->index[0]][2]);
106  const Point3f pb(mesh->vertices[face->index[1]][0], mesh->vertices[face->index[1]][1], mesh->vertices[face->index[1]][2]);
107  Point3f pc(mesh->vertices[face->index[2]][0], mesh->vertices[face->index[2]][1], mesh->vertices[face->index[2]][2]);
108 
109  Vector3f na(normal[0][0], normal[0][1], normal[0][2]);
110  Vector3f nb(normal[1][0], normal[1][1], normal[1][2]);
111  Vector3f nc(normal[2][0], normal[2][1], normal[2][2]);
112 
113  if(flip_order) {
114  std::swap(pa, pc);
115  std::swap(na, nc);
116 
117  na *= -1;
118  nb *= -1;
119  nc *= -1;
120  }
121 
122  if(textured) {
123  Point2f ta(0.5f - tex_scale.x * (tex_offset.x - mesh->texcos[face->index[0]][0]), 0.5f - tex_scale.y * (tex_offset.y + mesh->texcos[face->index[0]][1]));
124  const Point2f tb(0.5f - tex_scale.x * (tex_offset.x - mesh->texcos[face->index[1]][0]), 0.5f - tex_scale.y * (tex_offset.y + mesh->texcos[face->index[1]][1]));
125  Point2f tc(0.5f - tex_scale.x * (tex_offset.x - mesh->texcos[face->index[2]][0]), 0.5f - tex_scale.y * (tex_offset.y + mesh->texcos[face->index[2]][1]));
126 
127  if(flip_order)
128  std::swap(ta, tc);
129 
130  Triangle<Vertex3f_Texture> triangle(Vertex3f_Texture(pa, na, ta),
131  Vertex3f_Texture(pb, nb, tb),
132  Vertex3f_Texture(pc, nc, tc));
133  triangle.fax_Material(&mat);
134 
135  user_p->fax_Triangle(&triangle);
136  }
137  else {
138  const Uint32 argb = mat.diffuse.get_argb();
139 
140  Triangle<Vertex3f_Color> triangle(Vertex3f_Color(pa, na, argb),
141  Vertex3f_Color(pb, nb, argb),
142  Vertex3f_Color(pc, nc, argb));
143  triangle.fax_Material(&mat);
144 
145  user_p->fax_Triangle(&triangle);
146  }
147 
148  normal+=3;
149  }
150 #endif
151  }
152 
153  class Model_Unrenderer : public Model_Visitor {
154  public:
155  virtual void operator()(const Model &model, Lib3dsMeshInstanceNode * const &node, Lib3dsMesh * const &mesh);
156  };
157 
158  void Model_Unrenderer::operator()(const Model & /*model*/ , Lib3dsMeshInstanceNode * const & /*node*/ , Lib3dsMesh * const &mesh) {
159  assert(mesh);
160 
161  if(mesh->user_ptr) {
162  Vertex_Buffer *user_p = reinterpret_cast<Vertex_Buffer *>(mesh->user_ptr);
163  delete user_p;
164  mesh->user_ptr = 0;
165  }
166  }
167 
168 #ifndef TEMP_DISABLE
169 #ifdef _WINDOWS
170 #pragma warning( push )
171 #pragma warning( disable : 4355 )
172 #endif
173  Model::Model(const String &filename, const bool align_normals_)
174  : m_filename(filename),
175  m_file(0),
176  m_keyframe(0.0f),
177  m_align_normals(align_normals_),
178  m_unrenderer(0),
179  m_scale(1.0f, 1.0f, 1.0f),
180  m_rotate(0.0f, 0.0f, 1.0f),
181  m_translate(0.0f, 0.0f, 0.0f),
182  m_rotate_angle(0.0f)
183 // m_loader(*this),
184 // m_loader_op(m_loader)
185  {
186  load();
187  }
188 
189  Model::Model(const Model &rhs)
190  : m_filename(rhs.m_filename),
191  m_file(0),
192  m_keyframe(rhs.m_keyframe),
193  m_align_normals(rhs.m_align_normals),
194  m_unrenderer(0),
195  m_scale(rhs.m_scale),
196  m_rotate(rhs.m_rotate),
197  m_translate(rhs.m_translate),
198  m_rotate_angle(rhs.m_rotate_angle)
199 // m_loader(*this),
200 // m_loader_op(m_loader)
201  {
202  load();
203  }
204 #ifdef _WINDOWS
205 #pragma warning( pop )
206 #endif
207 
209  if(m_unrenderer)
210  visit_meshes(*m_unrenderer);
211  delete m_unrenderer;
212 
213  if(m_file)
214  lib3ds_file_free(m_file);
215  }
216 
217  Model & Model::operator =(const Model &rhs) {
218  Model *lhs = 0;
219 
220  try {
221 // GUARANTEED_FINISHED_BEGIN(rhs.m_loader);
222  lhs = new Model(rhs);
223 // GUARANTEED_FINISHED_END();
224 
225 // GUARANTEED_FINISHED_BEGIN(lhs->m_loader);
226 // GUARANTEED_FINISHED_BEGIN(m_loader);
227  std::swap(m_filename, lhs->m_filename);
228  std::swap(m_file, lhs->m_file);
229  std::swap(m_keyframe, lhs->m_keyframe);
230  std::swap(m_unrenderer, lhs->m_unrenderer);
231  std::swap(m_scale, lhs->m_scale);
232  std::swap(m_rotate, lhs->m_rotate);
233  std::swap(m_translate, lhs->m_translate);
234  std::swap(m_rotate_angle, lhs->m_rotate_angle);
235 // GUARANTEED_FINISHED_END();
236 // GUARANTEED_FINISHED_END();
237  }
238  catch(...) {
239  delete lhs;
240  throw;
241  }
242 
243  delete lhs;
244 
245  return *this;
246  }
247 
249 // GUARANTEED_FINISHED_BEGIN(m_loader);
250  return m_translate + m_scale.multiply_by(Quaternion::Axis_Angle(m_rotate, m_rotate_angle) * Vector3f(m_position));
251 // GUARANTEED_FINISHED_END();
252  }
253 
254  float Model::get_keyframes() const {
255 // GUARANTEED_FINISHED_BEGIN(m_loader);
256  return float(m_file->frames);
257 // GUARANTEED_FINISHED_END();
258  }
259 
260  void Model::set_keyframe(const float &keyframe) {
261 // GUARANTEED_FINISHED_BEGIN(m_loader);
262  m_keyframe = keyframe;
263  lib3ds_file_eval(m_file, keyframe);
264 // GUARANTEED_FINISHED_END();
265  }
266 
267  void Model::visit_nodes(Model_Visitor &mv, Lib3dsNode *node) const {
268  if(!node) {
269  for(node=m_file->nodes; node; node=node->next)
270  visit_nodes(mv, node);
271  return;
272  }
273 
274  for(Lib3dsNode *child=node->childs; child; child=child->next)
275  visit_nodes(mv, child);
276 
277  mv(*this, node);
278  }
279 
280  void Model::visit_meshes(Model_Visitor &mv, Lib3dsNode * node, Lib3dsMesh * const &mesh) const {
281  if(!node) {
282  if(!mesh) {
283  if(m_file->nodes)
284  for(node = m_file->nodes; node; node = node->next)
285  visit_meshes(mv, node);
286  else
287  for(Lib3dsMesh *mesh = *m_file->meshes, *end = mesh + m_file->nmeshes;
288  mesh != end;
289  ++mesh)
290  {
291  visit_meshes(mv, node, mesh);
292  }
293 
294  return;
295  }
296  }
297  else
298  for(Lib3dsNode *child=node->childs; child; child=child->next)
299  visit_meshes(mv, child);
300 
301  if(!node) {
302  if(!mesh)
303  throw Model_Render_Failure();
304 
305  mv(*this, 0, mesh);
306  }
307  else if(node->type == LIB3DS_NODE_MESH_INSTANCE &&
308  strcmp(node->name, "$$$DUMMY"))
309  {
310  Lib3dsMesh * node_mesh = m_file->meshes[lib3ds_file_mesh_by_name(m_file, node->name)];
311 
312  if(!node_mesh)
313  throw Model_Render_Failure();
314 
315  mv(*this, reinterpret_cast<Lib3dsMeshInstanceNode * const>(node), node_mesh);
316  }
317  }
318 
319  void Model::render() const {
320 // GUARANTEED_FINISHED_BEGIN(m_loader);
321 
322  if(!m_unrenderer)
323  m_unrenderer = new Model_Unrenderer();
324 
325  Video &vr = get_Video();
326 
327  vr.push_world_stack();
328 
329  vr.translate_scene(Vector3f(m_translate));
330  vr.rotate_scene(m_rotate, m_rotate_angle);
331  vr.scale_scene(m_scale);
332 
333  Model_Renderer mr;
334  visit_meshes(mr);
335 
336  vr.pop_world_stack();
337 
338 // GUARANTEED_FINISHED_END();
339  }
340 #endif
341 
342  void Model_Renderer::operator()(const Model &model, Lib3dsMeshInstanceNode * const &node, Lib3dsMesh * const &mesh) {
343  Video &vr = get_Video();
344 
345  if(!mesh || !mesh->user_ptr)
346  create_vertex_buffer(new Vertex_Buffer(), model, node, mesh);
347 
348  Vertex_Buffer * user_p = reinterpret_cast<Vertex_Buffer *>(mesh->user_ptr);
349  if(!user_p)
350  throw Model_Render_Failure();
351 
352  vr.push_world_stack();
353 
354  if(node) {
355  vr.transform_scene(reinterpret_cast<const Matrix4f &>(node->base.matrix));
356  vr.translate_scene(Vector3f(-node->pivot[0],
357  -node->pivot[1],
358  -node->pivot[2]));
359  }
360  vr.transform_scene(reinterpret_cast<const Matrix4f &>(mesh->matrix).inverted());
361 
362  //user_p->debug_render(); ///HACK
363  user_p->render();
364 
365  vr.pop_world_stack();
366  }
367 
368  void Model_Extents::operator()(const Model & /*model*/ , Lib3dsMeshInstanceNode * const & /*node*/ , Lib3dsMesh * const &mesh) {
369  for(float (*vertex)[3] = &mesh->vertices[0], (*end)[3] = vertex + mesh->nvertices; vertex != end; ++vertex)
370  if(vertex) {
371  float (&point)[3] = *vertex;
372 
373  if(lower_bound.x > point[0] || !started)
374  lower_bound.x = point[0];
375  if(lower_bound.y > point[1] || !started)
376  lower_bound.y = point[1];
377  if(lower_bound.z > point[2] || !started)
378  lower_bound.z = point[2];
379 
380  if(upper_bound.x < point[0] || !started)
381  upper_bound.x = point[0];
382  if(upper_bound.y < point[1] || !started)
383  upper_bound.y = point[1];
384  if(upper_bound.z < point[2] || !started)
385  upper_bound.z = point[2];
386 
387  started = true;
388  }
389  }
390 
391 // int Model::Loader::function() {
392 // m_model.load();
393 // return 0;
394 // }
395 
396 #ifndef TEMP_DISABLE
397  void Model::load() {
398  m_file = lib3ds_file_open(m_filename.c_str());
399  if(!m_file)
400  throw Model_Init_Failure();
401 
402  lib3ds_file_eval(m_file, m_keyframe);
403 
404  visit_meshes(m_extents);
405 
406  m_position = m_extents.upper_bound.interpolate_to(0.5f, m_extents.lower_bound);
407  }
408 #endif
409 
410 }
Lib3dsNode * nodes
Definition: lib3ds.h:554
unsigned short nfaces
Definition: lib3ds.h:370
An Abstraction of a 3D Model.
Definition: Model.h:105
unsigned short nvertices
Definition: lib3ds.h:366
float specular[3]
Definition: lib3ds.h:230
float transparency
Definition: lib3ds.h:235
The Video Rendering Singleton.
Definition: Video.h:71
Point3f get_position() const
Get the position of the Model.
Definition: Model.cpp:248
virtual void scale_scene(const Vector3f &factor)=0
Scale the scene.
GLclampf f
Definition: glew.h:3390
float scale[2]
Definition: lib3ds.h:197
static Quaternion Axis_Angle(const Vector3f &v, const float &theta)
Create a Quaternion from an Axis/Angle pair.
Definition: Quaternion.cpp:56
Lib3dsNodeType type
Definition: lib3ds.h:411
int frames
Definition: lib3ds.h:538
SDL_EventEntry * free
Definition: SDL_events.c:80
float(* vertices)[3]
Definition: lib3ds.h:367
float value[4]
Definition: lib3ds.h:434
Lib3dsTextureMap texture1_map
Definition: lib3ds.h:249
void visit_meshes(Model_Visitor &mv, Lib3dsNode *node=0, Lib3dsMesh *const &mesh=0) const
Visit all meshes.
Definition: Model.cpp:280
Lib3dsKey * keys
Definition: lib3ds.h:459
const char * c_str() const
Definition: String.cpp:467
Vector3f multiply_by(const Vector3f &rhs) const
Multiply corresponding members.
Definition: Vector3f.hxx:170
LIB3DSAPI int lib3ds_file_mesh_by_name(Lib3dsFile *file, const char *name)
Definition: lib3ds_file.c:1057
virtual void operator()(const Model &, Lib3dsNode *const &)
Definition: Model.h:88
Lib3dsFace * faces
Definition: lib3ds.h:371
#define assert(x)
Definition: SDL_malloc.c:1234
const GLfloat * tc
Definition: glew.h:14921
unsigned short index[3]
Definition: lib3ds.h:352
float self_illum
Definition: lib3ds.h:239
virtual void transform_scene(const Matrix4f &transformation)=0
Transform the scene.
int nmeshes
Definition: lib3ds.h:552
LIB3DSAPI void lib3ds_file_eval(Lib3dsFile *file, float t)
Definition: lib3ds_file.c:214
LIB3DSAPI void lib3ds_file_free(Lib3dsFile *file)
Definition: lib3ds_file.c:187
float get_keyframes() const
Get the number of keyframes; may be higher than you expect.
Definition: Model.cpp:254
A 3D Point represented with floats.
Definition: Coordinate.h:133
uint32_t Uint32
An unsigned 32-bit integer type.
Definition: SDL_stdinc.h:145
void set_keyframe(const float &keyframe)
Set the current (key)frame; interpolation is automatic.
Definition: Model.cpp:260
A Featureful 3-Space Vector Class.
Definition: Vector3f.h:58
struct Lib3dsNode * next
Definition: lib3ds.h:408
float diffuse[3]
Definition: lib3ds.h:229
Model(const String &filename, const bool align_normals_=false)
The only way to create a Model.
Definition: Model.cpp:173
virtual void pop_world_stack()=0
Pop a model view matrix off the stack.
virtual void rotate_scene(const Vector3f &about, const float &radians)=0
Rotate the scene.
GLenum face
Definition: gl2ext.h:1490
void visit_nodes(Model_Visitor &mv, Lib3dsNode *node=0) const
Visit all nodes.
Definition: Model.cpp:267
A visitor base class.
Definition: Model.h:82
Lib3dsMesh ** meshes
Definition: lib3ds.h:553
void * user_ptr
Definition: lib3ds.h:361
A Vertex_Buffer that accepts Triangle and Quadrilaterals.
Definition: Vertex_Buffer.h:85
virtual void push_world_stack()=0
Push a model view matrix onto the stack.
float(* texcos)[2]
Definition: lib3ds.h:368
float matrix[4][4]
Definition: lib3ds.h:415
#define malloc
Definition: SDL_malloc.c:635
float offset[2]
Definition: lib3ds.h:198
virtual void operator()(const Model &model, Lib3dsMeshInstanceNode *const &node, Lib3dsMesh *const &mesh)
Definition: Model.cpp:368
virtual void translate_scene(const Vector3f &direction)=0
Translate the scene.
struct Lib3dsNode * childs
Definition: lib3ds.h:409
LIB3DSAPI void lib3ds_mesh_calculate_vertex_normals(Lib3dsMesh *mesh, float(*normals)[3])
Definition: lib3ds_mesh.c:163
void swap(Zeni::String &lhs, Zeni::String &rhs)
Definition: String.cpp:578
void render() const
Definition: Model.cpp:319
char name[64]
Definition: lib3ds.h:193
Point3f lower_bound
Definition: Model.h:100
float shininess
Definition: lib3ds.h:231
Lib3dsTrack scl_track
Definition: lib3ds.h:482
GLuint GLuint end
Definition: glew.h:1239
void render()
Render the Vertex_Buffer.
int material
Definition: lib3ds.h:354
LIB3DSAPI Lib3dsFile * lib3ds_file_open(const char *filename)
Definition: lib3ds_file.c:83
Point3f upper_bound
The bounding box of model, first frame only if animated.
Definition: Model.h:100
float ambient[3]
Definition: lib3ds.h:228
Video & get_Video()
Get access to the singleton.
Definition: Video.cpp:149
int i
Definition: pngrutil.c:1377
float matrix[4][4]
Definition: lib3ds.h:365
char name[64]
Definition: lib3ds.h:413
Point3f interpolate_to(const float &rhs_part, const Point3f &rhs) const
Definition: Coordinate.cpp:41
Lib3dsNode base
Definition: lib3ds.h:469
#define false
Definition: ftrandom.c:50
Model & operator=(const Model &rhs)
Definition: Model.cpp:217