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  * $Revision$ *
45  * $Author$ *
46  * $Date$ *
47  * *
48 \*===========================================================================*/
49 
50 
51 
52 //=============================================================================
53 //
54 // CLASS FastMeshNode - IMPLEMENTATION
55 //
56 //=============================================================================
57 
58 
59 //== INCLUDES =================================================================
60 
61 
62 #include "OBJNode.hh"
63 
64 #include <cstdio>
65 
66 //== NAMESPACES ===============================================================
67 
68 namespace ACG {
69 namespace SceneGraph {
70 
71 
72 //== IMPLEMENTATION ==========================================================
73 
74 
75 void
77 boundingBox(Vec3d& _bbMin, Vec3d& _bbMax)
78 {
79  Vec3f bbMin(FLT_MAX,FLT_MAX,FLT_MAX);
80  Vec3f bbMax(-FLT_MAX,-FLT_MAX,-FLT_MAX);
81 
82  for(unsigned int i=0; i<vertices_.size(); ++i)
83  {
84  bbMin.minimize(vertices_[i]);
85  bbMax.maximize(vertices_[i]);
86  }
87 
88  Vec3d bbMind = ACG::Vec3d(bbMin);
89  Vec3d bbMaxd = ACG::Vec3d(bbMax);
90 
91  _bbMin.minimize(bbMind);
92  _bbMax.maximize(bbMaxd);
93 
94 }
95 
96 
97 //----------------------------------------------------------------------------
98 
99 
101 OBJNode::
103 {
104  return ( DrawModes::POINTS |
109 }
110 
111 
112 //----------------------------------------------------------------------------
113 
114 
115 void
116 OBJNode::
117 draw(GLState& _state, const DrawModes::DrawMode& _drawMode)
118 {
119  if (_drawMode & DrawModes::POINTS)
120  {
121  ACG::GLState::disable(GL_LIGHTING);
122  ACG::GLState::shadeModel(GL_FLAT);
123  glPolygonMode(GL_FRONT_AND_BACK, GL_POINT);
124  draw_obj();
125  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
126  }
127 
128 
129  if (_drawMode & DrawModes::WIREFRAME)
130  {
131  ACG::GLState::disable(GL_LIGHTING);
132  ACG::GLState::shadeModel(GL_FLAT);
133  glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
134  draw_obj();
135  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
136  }
137 
138 
139  else if (_drawMode & DrawModes::HIDDENLINE)
140  {
141  Vec4f base_color_backup = _state.base_color();
142 
143  ACG::GLState::disable(GL_LIGHTING);
144  ACG::GLState::shadeModel(GL_FLAT);
145 
146  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
147  glColor(_state.clear_color());
148  ACG::GLState::depthRange(0.01, 1.0);
149  draw_obj();
150 
151  glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
152  glColor(base_color_backup);
153  ACG::GLState::depthRange(0.0, 1.0);
154  draw_obj();
155 
156  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
157  }
158 
159 
160  else if (_drawMode & DrawModes::SOLID_FLAT_SHADED)
161  {
162  ACG::GLState::enable(GL_LIGHTING);
163  ACG::GLState::shadeModel(GL_FLAT);
164  draw_obj();
165  }
166 
167 
168  else if (_drawMode & DrawModes::SOLID_TEXTURED)
169  {
170  ACG::GLState::enable( GL_TEXTURE_2D );
171  ACG::GLState::disable(GL_LIGHTING);
172  ACG::GLState::shadeModel(GL_FLAT);
173  draw_obj_tex();
174  ACG::GLState::disable( GL_TEXTURE_2D );
175  }
176 }
177 
178 
179 //----------------------------------------------------------------------------
180 
181 
182 void
183 OBJNode::draw_obj() const
184 {
185  glBegin(GL_TRIANGLES);
186 
187  for(unsigned int i=0; i<faces_.size(); ++i)
188  {
189  glNormal(normals_[i]);
190  glVertex(vertices_[faces_[i].i0]);
191  glVertex(vertices_[faces_[i].i1]);
192  glVertex(vertices_[faces_[i].i2]);
193  }
194 
195  glEnd();
196 }
197 
198 
199 //----------------------------------------------------------------------------
200 
201 
202 void
203 OBJNode::draw_obj_tex() const
204 {
205  glBegin(GL_TRIANGLES);
206 
207  for(unsigned int i=0; i<faces_.size(); ++i)
208  {
209  glNormal(normals_[i]);
210  if (faces_[i].t0 != -1)
211  {
212  glTexCoord(texCoords_[faces_[i].t0]);
213  glVertex(vertices_[faces_[i].i0]);
214  glTexCoord(texCoords_[faces_[i].t1]);
215  glVertex(vertices_[faces_[i].i1]);
216  glTexCoord(texCoords_[faces_[i].t2]);
217  glVertex(vertices_[faces_[i].i2]);
218  }
219  else
220  {
221  glVertex(vertices_[faces_[i].i0]);
222  glVertex(vertices_[faces_[i].i1]);
223  glVertex(vertices_[faces_[i].i2]);
224  }
225  }
226 
227  glEnd();
228 }
229 
230 
231 //----------------------------------------------------------------------------
232 
233 
234 void
236 {
237  switch (_target)
238  {
239  case PICK_VERTEX:
240  {
241  break;
242  }
243  case PICK_EDGE:
244  {
245  break;
246  }
247  case PICK_ANYTHING:
248  case PICK_FACE:
249  {
250  _state.pick_set_maximum (1);
251  _state.pick_set_name (0);
252  draw_obj();
253  break;
254  }
255 
256  default: // avoid warning
257  break;
258  }
259 }
260 
261 
262 //----------------------------------------------------------------------------
263 
264 
265 bool
266 OBJNode::read(const std::string& _filename)
267 {
268  FILE* in = fopen(_filename.c_str(), "r");
269  if (!in) return false;
270 
271 
272  char s[200];
273  float x, y, z, u, v;
274 
275 
276  // clear mesh
277  vertices_.clear();
278  texCoords_.clear();
279  faces_.clear();
280 
281 
282 
283  while(!feof(in) && fgets(s, 200, in))
284  {
285  // comment
286  if (s[0] == '#') continue;
287 
288 
289  // vertex
290  else if (strncmp(s, "v ", 2) == 0)
291  {
292  if (sscanf(s, "v %30f %30f %30f", &x, &y, &z))
293  {
294  vertices_.push_back(Vec3f(x,y,z));
295  }
296  }
297 
298 
299  // texture coord
300  else if (strncmp(s, "vt ", 3) == 0)
301  {
302  if (sscanf(s, "vt %40f %40f", &u, &v))
303  texCoords_.push_back(Vec2f(u, v));
304  }
305 
306 
307  // face
308  else if (strncmp(s, "f ", 2) == 0)
309  {
310  std::vector<unsigned int> vIdx, tIdx;
311  int component(0), nV(0);
312  bool endOfVertex(false);
313  char* p1(s+2);
314 
315  vIdx.clear();
316  tIdx.clear();
317 
318 
319  while(p1)
320  {
321  char* p0 = p1;
322 
323  // overwrite next separator
324  if (p1)
325  {
326  while (*p1 != '/' && *p1 != '\r' && *p1 != '\n' &&
327  *p1 != ' ' && *p1 != '\0')
328  p1++;
329 
330  // detect end of vertex
331  if (*p1 != '/') endOfVertex = true;
332 
333  // replace separator by '\0'
334  if (*p1 != '\0')
335  {
336  *p1 = '\0';
337  p1++; // point to next token
338  }
339 
340  // detect end of line and break
341  if (*p1 == '\0' || *p1 == '\n')
342  p1 = 0;
343  }
344 
345  if (*p0 != '\0')
346  {
347  switch (component)
348  {
349  case 0: vIdx.push_back(atoi(p0)-1); break;
350  case 1: tIdx.push_back(atoi(p0)-1); break;
351  case 2: /* ignore vertex normals */ break;
352  }
353 
354  component++;
355 
356  if (endOfVertex)
357  {
358  component = 0;
359  nV++;
360  endOfVertex = false;
361  }
362  }
363  }
364 
365 
366  if (vIdx.size() >= 3)
367  {
368  // texture
369  if (vIdx.size() == tIdx.size())
370  {
371  for (unsigned int i1=1, i2=2; i2 < vIdx.size(); ++i1, ++i2)
372  faces_.push_back(Face(vIdx[0], vIdx[i1], vIdx[i2],
373  tIdx[0], tIdx[i1], tIdx[i2]));
374  }
375 
376  // no texture
377  else
378  {
379  for (unsigned int i1=1, i2=2; i2 < vIdx.size(); ++i1, ++i2)
380  {
381  faces_.push_back(Face(vIdx[0], vIdx[i1], vIdx[i2]));
382  }
383  }
384  }
385  }
386 
387 
388  s[0]=' ';
389  }
390 
391 
392  fclose(in);
393 
395 
396  return true;
397 }
398 
399 
400 //----------------------------------------------------------------------------
401 
402 
403 void
405 {
406  normals_.clear();
407  normals_.reserve(faces_.size());
408 
409  std::vector<Face>::const_iterator f_it(faces_.begin()), f_end(faces_.end());
410  for (; f_it!=f_end; ++f_it)
411  {
412  const Vec3f& v0(vertex(f_it->i0));
413  const Vec3f& v1(vertex(f_it->i1));
414  const Vec3f& v2(vertex(f_it->i2));
415  normals_.push_back(((v1-v0) % (v2-v0)).normalize());
416  }
417 }
418 
419 //=============================================================================
420 } // namespace SceneGraph
421 } // namespace ACG
422 //=============================================================================
VectorT< float, 2 > Vec2f
Definition: VectorT.hh:108
const Vec4f & clear_color() const
get background color
Definition: GLState.hh:924
void glColor(const Vec3f &_v)
Wrapper: glColor for Vec3f.
Definition: gl.hh:146
DrawMode HIDDENLINE
draw hidden line (2 rendering passes needed)
Definition: DrawModes.cc:86
DrawMode SOLID_FLAT_SHADED
draw flat shaded faces (requires face normals)
Definition: DrawModes.cc:87
bool read(const std::string &_filename)
Read from file. Implemented using OpenMesh loader and OBJNodeExporter.
Definition: OBJNode.cc:266
DrawMode WIREFRAME
draw wireframe
Definition: DrawModes.cc:84
void glNormal(const Vec3f &_n)
Wrapper: glNormal for Vec3f.
Definition: gl.hh:137
DrawModes::DrawMode availableDrawModes() const
return available draw modes
Definition: OBJNode.cc:102
void glVertex(const Vec2i &_v)
Wrapper: glVertex for Vec2i.
Definition: gl.hh:97
void update_face_normals()
Update face normals. Call when geometry changes.
Definition: OBJNode.cc:404
DrawMode POINTS
draw unlighted points using the default base color
Definition: DrawModes.cc:79
PickTarget
What target to use for picking.
Definition: BaseNode.hh:99
vector_type & maximize(const vector_type &_rhs)
maximize values: same as *this = max(*this, _rhs), but faster
Definition: Vector11T.hh:562
static void enable(GLenum _cap)
replaces glEnable, but supports locking
DrawMode SOLID_TEXTURED
draw textured faces
Definition: DrawModes.cc:94
VectorT< float, 3 > Vec3f
Definition: VectorT.hh:125
const Vec4f & base_color() const
get base color (used when lighting is off)
Definition: GLState.hh:929
bool pick_set_maximum(unsigned int _idx)
Set the maximal number of primitives/components of your object.
Definition: GLState.cc:1047
static void depthRange(GLclampd _zNear, GLclampd _zFar)
replaces glDepthRange, supports locking
static void disable(GLenum _cap)
replaces glDisable, but supports locking
Namespace providing different geometric functions concerning angles.
Definition: DBSCANT.cc:51
picks verices (may not be implemented for all nodes)
Definition: BaseNode.hh:108
void pick_set_name(unsigned int _idx)
sets the current name/color (like glLoadName(_idx))
Definition: GLState.cc:1057
picks edges (may not be implemented for all nodes)
Definition: BaseNode.hh:106
void glTexCoord(const Vec2f &_t)
Wrapper: glTexCoord for Vec2f.
Definition: gl.hh:118
void boundingBox(Vec3d &_bbMin, Vec3d &_bbMax)
update bounding box
Definition: OBJNode.cc:77
pick any of the prior targets (should be implemented for all nodes)
Definition: BaseNode.hh:110
void draw(GLState &_state, const DrawModes::DrawMode &_drawMode)
drawing the primitive
Definition: OBJNode.cc:117
vector_type & minimize(const vector_type &_rhs)
minimize values: same as *this = min(*this, _rhs), but faster
Definition: Vector11T.hh:534
Vec3f & vertex(unsigned int _i)
get i&#39;th vertex
Definition: OBJNode.hh:173
VectorT< double, 3 > Vec3d
Definition: VectorT.hh:127
picks faces (should be implemented for all nodes)
Definition: BaseNode.hh:104
static void shadeModel(GLenum _mode)
replaces glShadeModel, supports locking
void pick(GLState &_state, PickTarget _target)
picking
Definition: OBJNode.cc:235