Developer Documentation
OBJNode.cc
1 /*===========================================================================*\
2  * *
3  * OpenFlipper *
4  * Copyright (c) 2001-2015, RWTH-Aachen University *
5  * Department of Computer Graphics and Multimedia *
6  * All rights reserved. *
7  * www.openflipper.org *
8  * *
9  *---------------------------------------------------------------------------*
10  * This file is part of OpenFlipper. *
11  *---------------------------------------------------------------------------*
12  * *
13  * Redistribution and use in source and binary forms, with or without *
14  * modification, are permitted provided that the following conditions *
15  * are met: *
16  * *
17  * 1. Redistributions of source code must retain the above copyright notice, *
18  * this list of conditions and the following disclaimer. *
19  * *
20  * 2. Redistributions in binary form must reproduce the above copyright *
21  * notice, this list of conditions and the following disclaimer in the *
22  * documentation and/or other materials provided with the distribution. *
23  * *
24  * 3. Neither the name of the copyright holder nor the names of its *
25  * contributors may be used to endorse or promote products derived from *
26  * this software without specific prior written permission. *
27  * *
28  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
29  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
30  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
31  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
32  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
33  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
34  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
35  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
36  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
37  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
38  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
39  * *
40 \*===========================================================================*/
41 
42 
43 
44 
45 
46 //=============================================================================
47 //
48 // CLASS FastMeshNode - IMPLEMENTATION
49 //
50 //=============================================================================
51 
52 
53 //== INCLUDES =================================================================
54 
55 
56 #include "OBJNode.hh"
57 
58 #include <cstdio>
59 
60 //== NAMESPACES ===============================================================
61 
62 namespace ACG {
63 namespace SceneGraph {
64 
65 
66 //== IMPLEMENTATION ==========================================================
67 
68 
69 void
71 boundingBox(Vec3d& _bbMin, Vec3d& _bbMax)
72 {
73  Vec3f bbMin(FLT_MAX,FLT_MAX,FLT_MAX);
74  Vec3f bbMax(-FLT_MAX,-FLT_MAX,-FLT_MAX);
75 
76  for(unsigned int i=0; i<vertices_.size(); ++i)
77  {
78  bbMin.minimize(vertices_[i]);
79  bbMax.maximize(vertices_[i]);
80  }
81 
82  Vec3d bbMind = ACG::Vec3d(bbMin);
83  Vec3d bbMaxd = ACG::Vec3d(bbMax);
84 
85  _bbMin.minimize(bbMind);
86  _bbMax.maximize(bbMaxd);
87 
88 }
89 
90 
91 //----------------------------------------------------------------------------
92 
93 
97 {
98  return ( DrawModes::POINTS |
103 }
104 
105 
106 //----------------------------------------------------------------------------
107 
108 
109 void
110 OBJNode::
111 draw(GLState& _state, const DrawModes::DrawMode& _drawMode)
112 {
113  if (_drawMode & DrawModes::POINTS)
114  {
115  ACG::GLState::disable(GL_LIGHTING);
116  ACG::GLState::shadeModel(GL_FLAT);
117  glPolygonMode(GL_FRONT_AND_BACK, GL_POINT);
118  draw_obj();
119  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
120  }
121 
122 
123  if (_drawMode & DrawModes::WIREFRAME)
124  {
125  ACG::GLState::disable(GL_LIGHTING);
126  ACG::GLState::shadeModel(GL_FLAT);
127  glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
128  draw_obj();
129  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
130  }
131 
132 
133  else if (_drawMode & DrawModes::HIDDENLINE)
134  {
135  Vec4f base_color_backup = _state.base_color();
136 
137  ACG::GLState::disable(GL_LIGHTING);
138  ACG::GLState::shadeModel(GL_FLAT);
139 
140  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
141  glColor(_state.clear_color());
142  ACG::GLState::depthRange(0.01, 1.0);
143  draw_obj();
144 
145  glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
146  glColor(base_color_backup);
147  ACG::GLState::depthRange(0.0, 1.0);
148  draw_obj();
149 
150  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
151  }
152 
153 
154  else if (_drawMode & DrawModes::SOLID_FLAT_SHADED)
155  {
156  ACG::GLState::enable(GL_LIGHTING);
157  ACG::GLState::shadeModel(GL_FLAT);
158  draw_obj();
159  }
160 
161 
162  else if (_drawMode & DrawModes::SOLID_TEXTURED)
163  {
164  ACG::GLState::enable( GL_TEXTURE_2D );
165  ACG::GLState::disable(GL_LIGHTING);
166  ACG::GLState::shadeModel(GL_FLAT);
167  draw_obj_tex();
168  ACG::GLState::disable( GL_TEXTURE_2D );
169  }
170 }
171 
172 
173 //----------------------------------------------------------------------------
174 
175 
176 void
177 OBJNode::draw_obj() const
178 {
179  glBegin(GL_TRIANGLES);
180 
181  for(unsigned int i=0; i<faces_.size(); ++i)
182  {
183  glNormal(normals_[i]);
184  glVertex(vertices_[faces_[i].i0]);
185  glVertex(vertices_[faces_[i].i1]);
186  glVertex(vertices_[faces_[i].i2]);
187  }
188 
189  glEnd();
190 }
191 
192 
193 //----------------------------------------------------------------------------
194 
195 
196 void
197 OBJNode::draw_obj_tex() const
198 {
199  glBegin(GL_TRIANGLES);
200 
201  for(unsigned int i=0; i<faces_.size(); ++i)
202  {
203  glNormal(normals_[i]);
204  if (faces_[i].t0 != -1)
205  {
206  glTexCoord(texCoords_[faces_[i].t0]);
207  glVertex(vertices_[faces_[i].i0]);
208  glTexCoord(texCoords_[faces_[i].t1]);
209  glVertex(vertices_[faces_[i].i1]);
210  glTexCoord(texCoords_[faces_[i].t2]);
211  glVertex(vertices_[faces_[i].i2]);
212  }
213  else
214  {
215  glVertex(vertices_[faces_[i].i0]);
216  glVertex(vertices_[faces_[i].i1]);
217  glVertex(vertices_[faces_[i].i2]);
218  }
219  }
220 
221  glEnd();
222 }
223 
224 
225 //----------------------------------------------------------------------------
226 
227 
228 void
230 {
231  switch (_target)
232  {
233  case PICK_VERTEX:
234  {
235  break;
236  }
237  case PICK_EDGE:
238  {
239  break;
240  }
241  case PICK_ANYTHING:
242  case PICK_FACE:
243  {
244  _state.pick_set_maximum (1);
245  _state.pick_set_name (0);
246  draw_obj();
247  break;
248  }
249 
250  default: // avoid warning
251  break;
252  }
253 }
254 
255 
256 //----------------------------------------------------------------------------
257 
258 
259 bool
260 OBJNode::read(const std::string& _filename)
261 {
262  FILE* in = fopen(_filename.c_str(), "r");
263  if (!in) return false;
264 
265 
266  char s[200];
267  float x, y, z, u, v;
268 
269 
270  // clear mesh
271  vertices_.clear();
272  texCoords_.clear();
273  faces_.clear();
274 
275 
276 
277  while(!feof(in) && fgets(s, 200, in))
278  {
279  // comment
280  if (s[0] == '#') continue;
281 
282 
283  // vertex
284  else if (strncmp(s, "v ", 2) == 0)
285  {
286  if (sscanf(s, "v %30f %30f %30f", &x, &y, &z))
287  {
288  vertices_.push_back(Vec3f(x,y,z));
289  }
290  }
291 
292 
293  // texture coord
294  else if (strncmp(s, "vt ", 3) == 0)
295  {
296  if (sscanf(s, "vt %40f %40f", &u, &v))
297  texCoords_.push_back(Vec2f(u, v));
298  }
299 
300 
301  // face
302  else if (strncmp(s, "f ", 2) == 0)
303  {
304  std::vector<unsigned int> vIdx, tIdx;
305  int component(0), nV(0);
306  bool endOfVertex(false);
307  char* p1(s+2);
308 
309  vIdx.clear();
310  tIdx.clear();
311 
312 
313  while(p1)
314  {
315  char* p0 = p1;
316 
317  // overwrite next separator
318  if (p1)
319  {
320  while (*p1 != '/' && *p1 != '\r' && *p1 != '\n' &&
321  *p1 != ' ' && *p1 != '\0')
322  p1++;
323 
324  // detect end of vertex
325  if (*p1 != '/') endOfVertex = true;
326 
327  // replace separator by '\0'
328  if (*p1 != '\0')
329  {
330  *p1 = '\0';
331  p1++; // point to next token
332  }
333 
334  // detect end of line and break
335  if (*p1 == '\0' || *p1 == '\n')
336  p1 = 0;
337  }
338 
339  if (*p0 != '\0')
340  {
341  switch (component)
342  {
343  case 0: vIdx.push_back(atoi(p0)-1); break;
344  case 1: tIdx.push_back(atoi(p0)-1); break;
345  case 2: /* ignore vertex normals */ break;
346  }
347 
348  component++;
349 
350  if (endOfVertex)
351  {
352  component = 0;
353  nV++;
354  endOfVertex = false;
355  }
356  }
357  }
358 
359 
360  if (vIdx.size() >= 3)
361  {
362  // texture
363  if (vIdx.size() == tIdx.size())
364  {
365  for (unsigned int i1=1, i2=2; i2 < vIdx.size(); ++i1, ++i2)
366  faces_.push_back(Face(vIdx[0], vIdx[i1], vIdx[i2],
367  tIdx[0], tIdx[i1], tIdx[i2]));
368  }
369 
370  // no texture
371  else
372  {
373  for (unsigned int i1=1, i2=2; i2 < vIdx.size(); ++i1, ++i2)
374  {
375  faces_.push_back(Face(vIdx[0], vIdx[i1], vIdx[i2]));
376  }
377  }
378  }
379  }
380 
381 
382  s[0]=' ';
383  }
384 
385 
386  fclose(in);
387 
389 
390  return true;
391 }
392 
393 
394 //----------------------------------------------------------------------------
395 
396 
397 void
399 {
400  normals_.clear();
401  normals_.reserve(faces_.size());
402 
403  std::vector<Face>::const_iterator f_it(faces_.begin()), f_end(faces_.end());
404  for (; f_it!=f_end; ++f_it)
405  {
406  const Vec3f& v0(vertex(f_it->i0));
407  const Vec3f& v1(vertex(f_it->i1));
408  const Vec3f& v2(vertex(f_it->i2));
409  normals_.push_back(((v1-v0) % (v2-v0)).normalize());
410  }
411 }
412 
413 //=============================================================================
414 } // namespace SceneGraph
415 } // namespace ACG
416 //=============================================================================
static void enable(GLenum _cap, bool _warnRemoved=true)
replaces glEnable, but supports locking
Definition: GLState.cc:1507
void glTexCoord(const Vec2f &_t)
Wrapper: glTexCoord for Vec2f.
Definition: gl.hh:116
void glColor(const Vec3f &_v)
Wrapper: glColor for Vec3f.
Definition: gl.hh:144
static void shadeModel(GLenum _mode)
replaces glShadeModel, supports locking
Definition: GLState.cc:1729
picks edges (may not be implemented for all nodes)
Definition: PickTarget.hh:80
void glNormal(const Vec3f &_n)
Wrapper: glNormal for Vec3f.
Definition: gl.hh:135
picks faces (should be implemented for all nodes)
Definition: PickTarget.hh:78
VectorT< float, 2 > Vec2f
Definition: VectorT.hh:102
Namespace providing different geometric functions concerning angles.
const Vec4f & base_color() const
get base color (used when lighting is off)
Definition: GLState.hh:951
DrawMode HIDDENLINE
draw hidden line (2 rendering passes needed)
Definition: DrawModes.cc:80
vector_type & maximize(const vector_type &_rhs)
maximize values: same as *this = max(*this, _rhs), but faster
Definition: Vector11T.hh:587
Vec3f & vertex(unsigned int _i)
get i&#39;th vertex
Definition: OBJNode.hh:167
static void depthRange(GLclampd _zNear, GLclampd _zFar)
replaces glDepthRange, supports locking
Definition: GLState.cc:1757
PickTarget
What target to use for picking.
Definition: PickTarget.hh:73
static void disable(GLenum _cap, bool _warnRemoved=true)
replaces glDisable, but supports locking
Definition: GLState.cc:1527
VectorT< float, 3 > Vec3f
Definition: VectorT.hh:119
pick any of the prior targets (should be implemented for all nodes)
Definition: PickTarget.hh:84
bool pick_set_maximum(size_t _idx)
Set the maximal number of primitives/components of your object.
Definition: GLState.cc:1051
DrawMode SOLID_TEXTURED
draw textured faces
Definition: DrawModes.cc:88
void draw(GLState &_state, const DrawModes::DrawMode &_drawMode) override
drawing the primitive
Definition: OBJNode.cc:111
picks verices (may not be implemented for all nodes)
Definition: PickTarget.hh:82
vector_type & minimize(const vector_type &_rhs)
minimize values: same as *this = min(*this, _rhs), but faster
Definition: Vector11T.hh:559
DrawModes::DrawMode availableDrawModes() const override
return available draw modes
Definition: OBJNode.cc:96
void update_face_normals()
Update face normals. Call when geometry changes.
Definition: OBJNode.cc:398
void glVertex(const Vec2i &_v)
Wrapper: glVertex for Vec2i.
Definition: gl.hh:95
DrawMode POINTS
draw unlighted points using the default base color
Definition: DrawModes.cc:73
DrawMode SOLID_FLAT_SHADED
draw flat shaded faces (requires face normals)
Definition: DrawModes.cc:81
DrawMode WIREFRAME
draw wireframe
Definition: DrawModes.cc:78
void pick_set_name(size_t _idx)
sets the current name/color (like glLoadName(_idx))
Definition: GLState.cc:1061
void pick(GLState &_state, PickTarget _target) override
picking
Definition: OBJNode.cc:229
bool read(const std::string &_filename)
Read from file. Implemented using OpenMesh loader and OBJNodeExporter.
Definition: OBJNode.cc:260
const Vec4f & clear_color() const
get background color
Definition: GLState.hh:946
void boundingBox(Vec3d &_bbMin, Vec3d &_bbMax) override
update bounding box
Definition: OBJNode.cc:71
VectorT< double, 3 > Vec3d
Definition: VectorT.hh:121