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
70 OBJNode::
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
94 DrawModes::DrawMode
95 OBJNode::
96 availableDrawModes() const
97 {
98 return ( DrawModes::POINTS |
99 DrawModes::WIREFRAME |
100 DrawModes::HIDDENLINE |
101 DrawModes::SOLID_FLAT_SHADED |
102 DrawModes::SOLID_TEXTURED );
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
229 OBJNode::pick(GLState& _state, PickTarget _target)
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
388 update_face_normals();
389
390 return true;
391 }
392
393
394 //----------------------------------------------------------------------------
395
396
397 void
398 OBJNode::update_face_normals()
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 //=============================================================================
ACG::SceneGraph::OBJNode::vertex
Vec3f & vertex(unsigned int _i)
get i&#39;th vertex
Definition: OBJNode.hh:167
OpenMesh::VectorT::maximize
vector_type & maximize(const vector_type &_rhs)
maximize values: same as *this = max(*this, _rhs), but faster
Definition: Vector11T.hh:563
ACG::SceneGraph::DrawModes::WIREFRAME
DrawMode WIREFRAME
draw wireframe
Definition: DrawModes.cc:78
ACG
Namespace providing different geometric functions concerning angles.
Definition: BaseObjectData.hh:68
ACG::SceneGraph::PICK_ANYTHING
pick any of the prior targets (should be implemented for all nodes)
Definition: PickTarget.hh:84
ACG::Vec3f
VectorT< float, 3 > Vec3f
Definition: VectorT.hh:119
ACG::SceneGraph::ACG::GLState::enable
static void enable(GLenum _cap, bool _warnRemoved=true)
replaces glEnable, but supports locking
ACG::SceneGraph::OBJNode::read
bool read(const std::string &_filename)
Read from file. Implemented using OpenMesh loader and OBJNodeExporter.
Definition: OBJNode.cc:260
ACG::SceneGraph::ACG::GLState::disable
static void disable(GLenum _cap, bool _warnRemoved=true)
replaces glDisable, but supports locking
ACG::GLState::clear_color
const Vec4f & clear_color() const
get background color
Definition: GLState.hh:921
ACG::SceneGraph::OBJNode::pick
void pick(GLState &_state, PickTarget _target)
picking
Definition: OBJNode.cc:229
ACG::SceneGraph::ACG::GLState::depthRange
static void depthRange(GLclampd _zNear, GLclampd _zFar)
replaces glDepthRange, supports locking
ACG::glNormal
void glNormal(const Vec3f &_n)
Wrapper: glNormal for Vec3f.
Definition: gl.hh:125
ACG::glVertex
void glVertex(const Vec2i &_v)
Wrapper: glVertex for Vec2i.
Definition: gl.hh:85
ACG::GLState
Definition: GLState.hh:213
ACG::Vec2f
VectorT< float, 2 > Vec2f
Definition: VectorT.hh:102
ACG::SceneGraph::DrawModes::HIDDENLINE
DrawMode HIDDENLINE
draw hidden line (2 rendering passes needed)
Definition: DrawModes.cc:80
ACG::Vec3d
VectorT< double, 3 > Vec3d
Definition: VectorT.hh:121
ACG::SceneGraph::ACG::GLState::shadeModel
static void shadeModel(GLenum _mode)
replaces glShadeModel, supports locking
ACG::SceneGraph::OBJNode::Face
Definition: OBJNode.hh:111
ACG::GLState::base_color
const Vec4f & base_color() const
get base color (used when lighting is off)
Definition: GLState.hh:926
ACG::SceneGraph::PICK_EDGE
picks edges (may not be implemented for all nodes)
Definition: PickTarget.hh:80
ACG::SceneGraph::DrawModes::DrawMode
Specifies a DrawMode.
Definition: DrawModes.hh:288
ACG::SceneGraph::OBJNode::boundingBox
void boundingBox(Vec3d &_bbMin, Vec3d &_bbMax)
update bounding box
Definition: OBJNode.cc:71
SceneGraph
Definition: QtPrincipalAxisDialog.hh:67
ACG::SceneGraph::PickTarget
PickTarget
What target to use for picking.
Definition: PickTarget.hh:73
OpenMesh::VectorT::minimize
vector_type & minimize(const vector_type &_rhs)
minimize values: same as *this = min(*this, _rhs), but faster
Definition: Vector11T.hh:535
OpenMesh::VectorT
Definition: Vector11T.hh:83
ACG::SceneGraph::DrawModes::SOLID_FLAT_SHADED
DrawMode SOLID_FLAT_SHADED
draw flat shaded faces (requires face normals)
Definition: DrawModes.cc:81
ACG::SceneGraph::PICK_FACE
picks faces (should be implemented for all nodes)
Definition: PickTarget.hh:78
ACG::glTexCoord
void glTexCoord(const Vec2f &_t)
Wrapper: glTexCoord for Vec2f.
Definition: gl.hh:106
ACG::SceneGraph::DrawModes::SOLID_TEXTURED
DrawMode SOLID_TEXTURED
draw textured faces
Definition: DrawModes.cc:88
ACG::SceneGraph::OBJNode::availableDrawModes
DrawModes::DrawMode availableDrawModes() const
return available draw modes
Definition: OBJNode.cc:96
ACG::glColor
void glColor(const Vec3f &_v)
Wrapper: glColor for Vec3f.
Definition: gl.hh:134
ACG::SceneGraph::PICK_VERTEX
picks verices (may not be implemented for all nodes)
Definition: PickTarget.hh:82
ACG::SceneGraph::DrawModes::POINTS
DrawMode POINTS
draw unlighted points using the default base color
Definition: DrawModes.cc:73
ACG::SceneGraph::OBJNode::update_face_normals
void update_face_normals()
Update face normals. Call when geometry changes.
Definition: OBJNode.cc:398
ACG::GLState::pick_set_maximum
bool pick_set_maximum(size_t _idx)
Set the maximal number of primitives/components of your object.
Definition: GLState.cc:1051
ACG::GLState::pick_set_name
void pick_set_name(size_t _idx)
sets the current name/color (like glLoadName(_idx))
Definition: GLState.cc:1061
ACG::SceneGraph::OBJNode::draw
void draw(GLState &_state, const DrawModes::DrawMode &_drawMode)
drawing the primitive
Definition: OBJNode.cc:111