Visualization Library v1.0.3A lightweight C++ OpenGL middleware for 2D/3D graphics |
[Download] [Tutorials] [All Classes] [Grouped Classes] |
00001 /**************************************************************************************/ 00002 /* */ 00003 /* Visualization Library */ 00004 /* http://visualizationlibrary.org */ 00005 /* */ 00006 /* Copyright (c) 2005-2010, Michele Bosi */ 00007 /* All rights reserved. */ 00008 /* */ 00009 /* Redistribution and use in source and binary forms, with or without modification, */ 00010 /* are permitted provided that the following conditions are met: */ 00011 /* */ 00012 /* - Redistributions of source code must retain the above copyright notice, this */ 00013 /* list of conditions and the following disclaimer. */ 00014 /* */ 00015 /* - Redistributions in binary form must reproduce the above copyright notice, this */ 00016 /* list of conditions and the following disclaimer in the documentation and/or */ 00017 /* other materials provided with the distribution. */ 00018 /* */ 00019 /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND */ 00020 /* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED */ 00021 /* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE */ 00022 /* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR */ 00023 /* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES */ 00024 /* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; */ 00025 /* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON */ 00026 /* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ 00027 /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ 00028 /* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ 00029 /* */ 00030 /**************************************************************************************/ 00031 00032 #include <vlGraphics/EdgeExtractor.hpp> 00033 #include <vlGraphics/Rendering.hpp> 00034 #include <vlGraphics/SceneManager.hpp> 00035 #include <vlGraphics/RenderQueue.hpp> 00036 #include <vlCore/Log.hpp> 00037 #include <vlGraphics/Array.hpp> 00038 #include <vlGraphics/Geometry.hpp> 00039 00040 using namespace vl; 00041 00042 //----------------------------------------------------------------------------- 00043 void EdgeExtractor::addEdge(std::set<EdgeExtractor::Edge>& edges, const EdgeExtractor::Edge& e, const fvec3& n) 00044 { 00045 std::set<EdgeExtractor::Edge>::iterator it = edges.find(e); 00046 if (it != edges.end()) 00047 { 00048 VL_CHECK(!it->normal1().isNull()) 00049 if (mWarnNonManifold && !it->normal2().isNull()) 00050 vl::Log::error("EdgeExtractor: non-manifold mesh detected!\n"); 00051 EdgeExtractor::Edge edge = e; 00052 edge.setNormal1(it->normal1()); 00053 edge.setNormal2(n); 00054 edges.erase( it ); 00055 edges.insert(edge); 00056 } 00057 else 00058 { 00059 VL_CHECK(!n.isNull()); 00060 EdgeExtractor::Edge edge = e; 00061 edge.setNormal1(n); 00062 edges.insert(edge); 00063 } 00064 } 00065 //----------------------------------------------------------------------------- 00067 void EdgeExtractor::extractEdges(Geometry* geom) 00068 { 00069 ArrayAbstract* verts = geom->vertexArray() ? geom->vertexArray() : geom->vertexAttribArray(vl::VA_Position) ? geom->vertexAttribArray(vl::VA_Position)->data() : NULL; 00070 00071 // mic fixme: 00072 // here the bottle-neck seems to be the continuous allocation/deallocation and insertion/search time, 00073 // maybe a memory-pool-managed hash table would help? 00074 if (!verts) 00075 { 00076 vl::Log::error("EdgeExtractor::extractEdges(geom): 'geom' must have a vertex array of type ArrayFloat3.\n"); 00077 return; 00078 } 00079 00080 std::set<Edge> edges; 00081 00082 // iterate all primitives 00083 for(int iprim=0; iprim<geom->drawCalls()->size(); ++iprim) 00084 { 00085 DrawCall* prim = geom->drawCalls()->at(iprim); 00086 // iterate triangles (if present) 00087 for(TriangleIterator trit = prim->triangleIterator(); trit.hasNext(); trit.next()) 00088 { 00089 size_t a = trit.a(); 00090 size_t b = trit.b(); 00091 size_t c = trit.c(); 00092 if (a == b || b == c || c == a) 00093 continue; 00094 // compute normal 00095 fvec3 v0 = (fvec3)verts->getAsVec3(a); 00096 fvec3 v1 = (fvec3)verts->getAsVec3(b) - v0; 00097 fvec3 v2 = (fvec3)verts->getAsVec3(c) - v0; 00098 fvec3 n = cross(v1,v2).normalize(); 00099 if (n.isNull()) 00100 continue; 00101 addEdge(edges, Edge( (fvec3)verts->getAsVec3(a), (fvec3)verts->getAsVec3(b) ), n ); 00102 addEdge(edges, Edge( (fvec3)verts->getAsVec3(b), (fvec3)verts->getAsVec3(c) ), n ); 00103 addEdge(edges, Edge( (fvec3)verts->getAsVec3(c), (fvec3)verts->getAsVec3(a) ), n ); 00104 } 00105 } 00106 00107 for(std::set<Edge>::iterator it = edges.begin(); it != edges.end(); ++it) 00108 { 00109 Edge e = *it; 00110 // boundary edge 00111 if (e.normal2().isNull()) 00112 e.setIsCrease(true); 00113 else 00114 // crease edge 00115 { 00116 float cos1 = dot(e.normal1(), e.normal2()); 00117 cos1 = vl::clamp(cos1,-1.0f,+1.0f); 00118 // return value in the interval [0,pi] radians 00119 float a1 = acos(cos1) / fPi * 180.0f; 00120 if( a1 > creaseAngle() ) 00121 e.setIsCrease(true); 00122 } 00123 mEdges.push_back(e); 00124 } 00125 } 00126 //----------------------------------------------------------------------------- 00127 ref<Geometry> EdgeExtractor::generateEdgeGeometry() const 00128 { 00129 ref<Geometry> geom = new Geometry; 00130 geom->setBufferObjectEnabled(false); 00131 ref<ArrayFloat3> vert_array = new ArrayFloat3; 00132 geom->setVertexArray(vert_array.get()); 00133 #ifdef SHOW_NORMALS 00134 vert_array->resize(edges().size()*6); 00135 #else 00136 vert_array->resize(edges().size()*2); 00137 #endif 00138 for(unsigned i=0; i<edges().size(); ++i) 00139 { 00140 vert_array->at(i*2+0) = edges()[i].vertex1(); 00141 vert_array->at(i*2+1) = edges()[i].vertex2(); 00142 } 00143 #ifdef SHOW_NORMALS 00144 int start = edges().size()*2; 00145 for(unsigned i=0; i<edges().size(); ++i) 00146 { 00147 fvec3 v = (edges()[i].vertex1() + edges()[i].vertex2()) * 0.5f; 00148 vert_array->at(start+i*2+0) = v; 00149 vert_array->at(start+i*2+1) = v + edges()[i].normal1()*0.25f; 00150 } 00151 start = edges().size()*4; 00152 for(unsigned i=0; i<edges().size(); ++i) 00153 { 00154 fvec3 v = (edges()[i].vertex1() + edges()[i].vertex2()) * 0.5f; 00155 vert_array->at(start+i*2+0) = v; 00156 vert_array->at(start+i*2+1) = v + edges()[i].normal2()*0.25f; 00157 } 00158 #endif 00159 geom->drawCalls()->push_back( new vl::DrawArrays(vl::PT_LINES, 0, (int)vert_array->size()) ); 00160 return geom; 00161 } 00162 //----------------------------------------------------------------------------- 00163 bool EdgeExtractor::extractEdges(Actor* actor) 00164 { 00165 Geometry* geom = cast<Geometry>(actor->lod(0)); 00166 if (geom) 00167 extractEdges(geom); 00168 return geom != NULL; 00169 } 00170 //----------------------------------------------------------------------------- 00171 void EdgeExtractor::extractEdges(ActorCollection* actors) 00172 { 00173 for(int i=0; i<actors->size(); ++i) 00174 { 00175 Geometry* geom = cast<Geometry>(actors->at(i)->lod(0)); 00176 if (geom) 00177 extractEdges(geom); 00178 } 00179 } 00180 //----------------------------------------------------------------------------- 00181 void EdgeExtractor::extractEdges(SceneManager* scene_manager) 00182 { 00183 ref<ActorCollection> actors = new ActorCollection; 00184 scene_manager->extractActors(*actors); 00185 extractEdges(actors.get()); 00186 } 00187 //----------------------------------------------------------------------------- 00188 void EdgeExtractor::extractEdges(Rendering* rendering) 00189 { 00190 for(int i=0; i<rendering->sceneManagers()->size(); ++i) 00191 extractEdges(rendering->sceneManagers()->at(i)); 00192 } 00193 //-----------------------------------------------------------------------------