Developer Documentation

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
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
76 OBJNode::
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
100 DrawModes::DrawMode
101 OBJNode::
102 availableDrawModes() const
103 {
104 return ( DrawModes::POINTS |
105 DrawModes::WIREFRAME |
106 DrawModes::HIDDENLINE |
107 DrawModes::SOLID_FLAT_SHADED |
108 DrawModes::SOLID_TEXTURED );
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
235 OBJNode::pick(GLState& _state, PickTarget _target)
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
394 update_face_normals();
395
396 return true;
397 }
398
399
400 //----------------------------------------------------------------------------
401
402
403 void
404 OBJNode::update_face_normals()
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 //=============================================================================
ACG::Vec2f
VectorT< float, 2 > Vec2f
Definition: VectorT.hh:108
ACG
Namespace providing different geometric functions concerning angles.
Definition: DBSCANT.cc:51
ACG::SceneGraph::ACG::GLState::enable
static void enable(GLenum _cap)
replaces glEnable, but supports locking
ACG::SceneGraph::DrawModes::HIDDENLINE
DrawMode HIDDENLINE
draw hidden line (2 rendering passes needed)
Definition: DrawModes.cc:86
ACG::GLState::pick_set_name
void pick_set_name(unsigned int _idx)
sets the current name/color (like glLoadName(_idx))
Definition: GLState.cc:1057
ACG::SceneGraph::PickTarget
PickTarget
What target to use for picking.
Definition: BaseNode.hh:99
ACG::GLState::clear_color
const Vec4f & clear_color() const
get background color
Definition: GLState.hh:924
ACG::SceneGraph::ACG::GLState::disable
static void disable(GLenum _cap)
replaces glDisable, but supports locking
ACG::GLState::pick_set_maximum
bool pick_set_maximum(unsigned int _idx)
Set the maximal number of primitives/components of your object.
Definition: GLState.cc:1047
ACG::SceneGraph::OBJNode::vertex
Vec3f & vertex(unsigned int _i)
get i'th vertex
Definition: OBJNode.hh:173
ACG::SceneGraph::PICK_FACE
picks faces (should be implemented for all nodes)
Definition: BaseNode.hh:104
ACG::SceneGraph::PICK_ANYTHING
pick any of the prior targets (should be implemented for all nodes)
Definition: BaseNode.hh:110
ACG::SceneGraph::DrawModes::SOLID_FLAT_SHADED
DrawMode SOLID_FLAT_SHADED
draw flat shaded faces (requires face normals)
Definition: DrawModes.cc:87
ACG::SceneGraph::ACG::GLState::shadeModel
static void shadeModel(GLenum _mode)
replaces glShadeModel, supports locking
ACG::Vec3d
VectorT< double, 3 > Vec3d
Definition: VectorT.hh:127
ACG::GLState
Definition: GLState.hh:220
ACG::glColor
void glColor(const Vec3f &_v)
Wrapper: glColor for Vec3f.
Definition: gl.hh:146
ACG::SceneGraph::PICK_VERTEX
picks verices (may not be implemented for all nodes)
Definition: BaseNode.hh:108
ACG::SceneGraph::PICK_EDGE
picks edges (may not be implemented for all nodes)
Definition: BaseNode.hh:106
ACG::SceneGraph::DrawModes::DrawMode
Specifies a DrawMode.
Definition: DrawModes.hh:294
ACG::glTexCoord
void glTexCoord(const Vec2f &_t)
Wrapper: glTexCoord for Vec2f.
Definition: gl.hh:118
ACG::Vec3f
VectorT< float, 3 > Vec3f
Definition: VectorT.hh:125
OpenMesh::VectorT
Definition: Vector11T.hh:83
ACG::SceneGraph::DrawModes::POINTS
DrawMode POINTS
draw unlighted points using the default base color
Definition: DrawModes.cc:79
ACG::SceneGraph::OBJNode::draw
void draw(GLState &_state, const DrawModes::DrawMode &_drawMode)
drawing the primitive
Definition: OBJNode.cc:117
ACG::glNormal
void glNormal(const Vec3f &_n)
Wrapper: glNormal for Vec3f.
Definition: gl.hh:137
ACG::SceneGraph::DrawModes::SOLID_TEXTURED
DrawMode SOLID_TEXTURED
draw textured faces
Definition: DrawModes.cc:94
ACG::SceneGraph::OBJNode::boundingBox
void boundingBox(Vec3d &_bbMin, Vec3d &_bbMax)
update bounding box
Definition: OBJNode.cc:77
ACG::SceneGraph::OBJNode::update_face_normals
void update_face_normals()
Update face normals. Call when geometry changes.
Definition: OBJNode.cc:404
ACG::SceneGraph::OBJNode::Face
Definition: OBJNode.hh:117
ACG::SceneGraph::DrawModes::WIREFRAME
DrawMode WIREFRAME
draw wireframe
Definition: DrawModes.cc:84
ACG::SceneGraph::ACG::GLState::depthRange
static void depthRange(GLclampd _zNear, GLclampd _zFar)
replaces glDepthRange, supports locking
ACG::SceneGraph::OBJNode::availableDrawModes
DrawModes::DrawMode availableDrawModes() const
return available draw modes
Definition: OBJNode.cc:102
ACG::GLState::base_color
const Vec4f & base_color() const
get base color (used when lighting is off)
Definition: GLState.hh:929
ACG::glVertex
void glVertex(const Vec2i &_v)
Wrapper: glVertex for Vec2i.
Definition: gl.hh:97
ACG::SceneGraph::OBJNode::pick
void pick(GLState &_state, PickTarget _target)
picking
Definition: OBJNode.cc:235
ACG::SceneGraph::OBJNode::read
bool read(const std::string &_filename)
Read from file. Implemented using OpenMesh loader and OBJNodeExporter.
Definition: OBJNode.cc:266