Visualization Library 2.1.0

A lightweight C++ OpenGL middleware for 2D/3D graphics

VL     Star     Watch     Fork     Issue

[Download] [Tutorials] [All Classes] [Grouped Classes]
EdgeExtractor.cpp
Go to the documentation of this file.
1 /**************************************************************************************/
2 /* */
3 /* Visualization Library */
4 /* http://visualizationlibrary.org */
5 /* */
6 /* Copyright (c) 2005-2020, Michele Bosi */
7 /* All rights reserved. */
8 /* */
9 /* Redistribution and use in source and binary forms, with or without modification, */
10 /* are permitted provided that the following conditions are met: */
11 /* */
12 /* - Redistributions of source code must retain the above copyright notice, this */
13 /* list of conditions and the following disclaimer. */
14 /* */
15 /* - Redistributions in binary form must reproduce the above copyright notice, this */
16 /* list of conditions and the following disclaimer in the documentation and/or */
17 /* other materials provided with the distribution. */
18 /* */
19 /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND */
20 /* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED */
21 /* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE */
22 /* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR */
23 /* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES */
24 /* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; */
25 /* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON */
26 /* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */
27 /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */
28 /* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
29 /* */
30 /**************************************************************************************/
31 
33 #include <vlGraphics/Rendering.hpp>
36 #include <vlCore/Log.hpp>
37 #include <vlGraphics/Array.hpp>
38 #include <vlGraphics/Geometry.hpp>
39 
40 using namespace vl;
41 
42 //-----------------------------------------------------------------------------
43 void EdgeExtractor::addEdge(std::set<EdgeExtractor::Edge>& edges, const EdgeExtractor::Edge& e, const fvec3& n)
44 {
45  std::set<EdgeExtractor::Edge>::iterator it = edges.find(e);
46  if (it != edges.end())
47  {
48  VL_CHECK(!it->normal1().isNull())
49  if (mWarnNonManifold && !it->normal2().isNull())
50  {
51  vl::Log::error("EdgeExtractor: non-manifold mesh detected!\n");
52  }
53  EdgeExtractor::Edge edge = e;
54  edge.setNormal1(it->normal1());
55  edge.setNormal2(n);
56  edges.erase( it );
57  edges.insert(edge);
58  }
59  else
60  {
61  VL_CHECK(!n.isNull());
62  EdgeExtractor::Edge edge = e;
63  edge.setNormal1(n);
64  edges.insert(edge);
65  }
66 }
67 //-----------------------------------------------------------------------------
70 {
71  ArrayAbstract* verts = geom->vertexArray();
72 
73  // mic fixme:
74  // here the bottle-neck seems to be the continuous allocation/deallocation and insertion/search time,
75  // maybe a memory-pool-managed hash table would help?
76  if (!verts)
77  {
78  vl::Log::error("EdgeExtractor::extractEdges(geom): 'geom' must have a vertex array of type ArrayFloat3.\n");
79  return;
80  }
81 
82  std::set<Edge> edges;
83 
84  // iterate all primitives
85  for(size_t iprim=0; iprim<geom->drawCalls().size(); ++iprim)
86  {
87  DrawCall* prim = geom->drawCalls().at(iprim);
88  // iterate triangles (if present)
89  for(TriangleIterator trit = prim->triangleIterator(); trit.hasNext(); trit.next())
90  {
91  size_t a = trit.a();
92  size_t b = trit.b();
93  size_t c = trit.c();
94  if (a == b || b == c || c == a)
95  continue;
96  // compute normal
97  fvec3 v0 = (fvec3)verts->getAsVec3(a);
98  fvec3 v1 = (fvec3)verts->getAsVec3(b) - v0;
99  fvec3 v2 = (fvec3)verts->getAsVec3(c) - v0;
100  fvec3 n = cross(v1,v2).normalize();
101  if (n.isNull())
102  continue;
103  addEdge(edges, Edge( (fvec3)verts->getAsVec3(a), (fvec3)verts->getAsVec3(b) ), n );
104  addEdge(edges, Edge( (fvec3)verts->getAsVec3(b), (fvec3)verts->getAsVec3(c) ), n );
105  addEdge(edges, Edge( (fvec3)verts->getAsVec3(c), (fvec3)verts->getAsVec3(a) ), n );
106  }
107  }
108 
109  for(std::set<Edge>::iterator it = edges.begin(); it != edges.end(); ++it)
110  {
111  Edge e = *it;
112  // boundary edge
113  if (e.normal2().isNull())
114  e.setIsCrease(true);
115  else
116  // crease edge
117  {
118  float cos1 = dot(e.normal1(), e.normal2());
119  cos1 = vl::clamp(cos1,-1.0f,+1.0f);
120  // return value in the interval [0,pi] radians
121  float a1 = acos(cos1) / fPi * 180.0f;
122  if( a1 > creaseAngle() )
123  e.setIsCrease(true);
124  }
125  mEdges.push_back(e);
126  }
127 }
128 //-----------------------------------------------------------------------------
130 {
131  ref<Geometry> geom = new Geometry;
132  geom->setBufferObjectEnabled(false);
133  ref<ArrayFloat3> vert_array = new ArrayFloat3;
134  geom->setVertexArray(vert_array.get());
135  #ifdef SHOW_NORMALS
136  vert_array->resize(edges().size()*6);
137  #else
138  vert_array->resize(edges().size()*2);
139  #endif
140  for(unsigned i=0; i<edges().size(); ++i)
141  {
142  vert_array->at(i*2+0) = edges()[i].vertex1();
143  vert_array->at(i*2+1) = edges()[i].vertex2();
144  }
145  #ifdef SHOW_NORMALS
146  int start = edges().size()*2;
147  for(unsigned i=0; i<edges().size(); ++i)
148  {
149  fvec3 v = (edges()[i].vertex1() + edges()[i].vertex2()) * 0.5f;
150  vert_array->at(start+i*2+0) = v;
151  vert_array->at(start+i*2+1) = v + edges()[i].normal1()*0.25f;
152  }
153  start = edges().size()*4;
154  for(unsigned i=0; i<edges().size(); ++i)
155  {
156  fvec3 v = (edges()[i].vertex1() + edges()[i].vertex2()) * 0.5f;
157  vert_array->at(start+i*2+0) = v;
158  vert_array->at(start+i*2+1) = v + edges()[i].normal2()*0.25f;
159  }
160  #endif
161  geom->drawCalls().push_back( new vl::DrawArrays(vl::PT_LINES, 0, (int)vert_array->size()) );
162  return geom;
163 }
164 //-----------------------------------------------------------------------------
166 {
167  Geometry* geom = cast<Geometry>(actor->lod(0));
168  if (geom)
169  extractEdges(geom);
170  return geom != NULL;
171 }
172 //-----------------------------------------------------------------------------
174 {
175  for(size_t i=0; i<actors->size(); ++i)
176  {
177  Geometry* geom = cast<Geometry>(actors->at(i)->lod(0));
178  if (geom)
179  extractEdges(geom);
180  }
181 }
182 //-----------------------------------------------------------------------------
184 {
186  scene_manager->extractVisibleActors( *actors, NULL );
187  extractEdges(actors.get());
188 }
189 //-----------------------------------------------------------------------------
191 {
192  for(size_t i=0; i<rendering->sceneManagers()->size(); ++i) {
193  extractEdges( rendering->sceneManagers()->at(i) );
194  }
195 }
196 //-----------------------------------------------------------------------------
The ArrayAbstract class defines an abstract interface to conveniently manipulate data stored in a Buf...
Definition: Array.hpp:58
const fvec3 & normal2() const
Associates a Renderable object to an Effect and Transform.
Definition: Actor.hpp:130
bool hasNext()
Returns false if the iterator has reached the end of the triangle list.
const Renderable * lod(int lod_index) const
Returns the Renderable object representing the LOD level specifed by lod_index.
Definition: Actor.hpp:173
float clamp(float x, float minval, float maxval)
Definition: Vector2.hpp:316
const fvec3 & normal1() const
const Vector3 & normalize(T_Scalar *len=NULL)
Definition: Vector3.hpp:228
Vector3< float > fvec3
A 3 components vector with float precision.
Definition: Vector3.hpp:253
const T * get() const
Definition: Object.hpp:128
void setNormal2(const fvec3 &v)
float creaseAngle() const
The minimum angle (in degrees) considered to generate crease-edges.
const ArrayAbstract * vertexArray() const
Conventional vertex array.
Definition: Geometry.hpp:248
static void error(const String &message)
Use this function to provide information about run-time errors: file not found, out of memory...
Definition: Log.cpp:165
void setVertexArray(ArrayAbstract *data)
Conventional vertex array.
Definition: Geometry.cpp:155
virtual void extractVisibleActors(ActorCollection &list, const Camera *camera)=0
Extracts all the enabled and visible Actors contained in the ActorTree hierarchy and appends them to ...
void resize(size_t dim)
Definition: Array.hpp:233
void extractEdges(Geometry *geom)
Extracts the edges from the given Geometry and appends them to edges().
fvec3 cross(const fvec3 &v1, const fvec3 &v2)
Definition: Vector3.hpp:278
virtual vec3 getAsVec3(size_t vector_index) const =0
Returns a vector from the buffer as a vec3 value.
const T * at(size_t i) const
Definition: Collection.hpp:103
size_t size() const
Returns the number of elements of an array.
Definition: Array.hpp:235
The Geometry class is a Renderable that implements a polygonal mesh made of polygons, lines and points.
Definition: Geometry.hpp:66
Visualization Library main namespace.
const float fPi
Greek Pi constant using float precision.
Definition: std_types.hpp:71
float dot(float a, float b)
Definition: glsl_math.hpp:1111
void setIsCrease(bool iscrease)
virtual TriangleIterator triangleIterator() const =0
Returns a TriangleIterator used to iterate through the triangles of a DrawCall.
void setNormal1(const fvec3 &v)
The SceneManager class is the base class for all the scene managers.
Iterator used to extract the indices of every single triangle of a DrawCall regardless of the primiti...
A single edge as extracted from the EdgeExtractor class.
#define NULL
Definition: OpenGLDefs.hpp:81
The Rendering class collects all the information to perform the rendering of a scene.
Definition: Rendering.hpp:68
T_VectorType & at(size_t i)
Definition: Array.hpp:255
Defined as a simple subclass of Collection<Actor>, see Collection for more information.
Definition: Actor.hpp:479
const std::vector< Edge > & edges() const
The base class of DrawArrays, DrawElements, MultiDrawElements and DrawRangeElements.
Definition: DrawCall.hpp:90
std::vector< Edge > mEdges
The ref<> class is used to reference-count an Object.
Definition: Object.hpp:55
bool isNull() const
Definition: Vector3.hpp:227
An array of vl::fvec3.
Definition: Array.hpp:414
T acos(T a)
Definition: glsl_math.hpp:329
Wraps the OpenGL function glDrawArrays().
Definition: DrawArrays.hpp:57
ref< Geometry > generateEdgeGeometry() const
void setBufferObjectEnabled(bool enabled)
Enable/disable BufferObject (vertex buffer object) (enabled by default).
Definition: Renderable.hpp:208
#define VL_CHECK(expr)
Definition: checks.hpp:73
void addEdge(std::set< EdgeExtractor::Edge > &edges, const EdgeExtractor::Edge &e, const fvec3 &n)
size_t size() const
Definition: Collection.hpp:85
Collection< SceneManager > * sceneManagers()
Returns the list of SceneManager[s] containing the Actor[s] to be rendered.
Definition: Rendering.hpp:136
Collection< DrawCall > & drawCalls()
Returns the list of DrawCall objects bound to a Geometry.
Definition: Geometry.hpp:102