Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
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 <vlCore/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
00068 void EdgeExtractor::extractEdges(Geometry* geom)
00069 {
00070 ArrayFloat3* verts = dynamic_cast<ArrayFloat3*>(geom->vertexArray());
00071
00072
00073
00074
00075 std::set<Edge> edges;
00076 if (!verts)
00077 {
00078 vl::Log::error("EdgeExtractor::extractEdges(geom): 'geom' must have a vertex array of type ArrayFloat3.\n");
00079 return;
00080 }
00081
00082
00083 for(int iprim=0; iprim<geom->drawCalls()->size(); ++iprim)
00084 {
00085 DrawCall* prim = geom->drawCalls()->at(iprim);
00086
00087 for(TriangleIterator trit = prim->triangleIterator(); !trit.isEnd(); 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
00095 fvec3 v0 = verts->at(a);
00096 fvec3 v1 = verts->at(b) - v0;
00097 fvec3 v2 = verts->at(c) - v0;
00098 fvec3 n = cross(v1,v2).normalize();
00099 if (n.isNull())
00100 continue;
00101 addEdge(edges, Edge( verts->at(a), verts->at(b) ), n );
00102 addEdge(edges, Edge( verts->at(b), verts->at(c) ), n );
00103 addEdge(edges, Edge( verts->at(c), verts->at(a) ), n );
00104 }
00105 }
00106
00107 for(std::set<Edge>::iterator it = edges.begin(); it != edges.end(); ++it)
00108 {
00109 Edge e = *it;
00110
00111 if (e.normal2().isNull())
00112 e.setIsCrease(true);
00113 else
00114
00115 {
00116 float cos1 = dot(e.normal1(), e.normal2());
00117 cos1 = vl::clamp(cos1,-1.0f,+1.0f);
00118
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->setColor(vl::black);
00131 geom->setVBOEnabled(false);
00132 ref<ArrayFloat3> vert_array = new ArrayFloat3;
00133 geom->setVertexArray(vert_array.get());
00134 #ifdef SHOW_NORMALS
00135 vert_array->resize(edges().size()*6);
00136 #else
00137 vert_array->resize(edges().size()*2);
00138 #endif
00139 for(unsigned i=0; i<edges().size(); ++i)
00140 {
00141 vert_array->at(i*2+0) = edges()[i].vertex1();
00142 vert_array->at(i*2+1) = edges()[i].vertex2();
00143 }
00144 #ifdef SHOW_NORMALS
00145 int start = edges().size()*2;
00146 for(unsigned i=0; i<edges().size(); ++i)
00147 {
00148 fvec3 v = (edges()[i].vertex1() + edges()[i].vertex2()) * 0.5f;
00149 vert_array->at(start+i*2+0) = v;
00150 vert_array->at(start+i*2+1) = v + edges()[i].normal1()*0.25f;
00151 }
00152 start = edges().size()*4;
00153 for(unsigned i=0; i<edges().size(); ++i)
00154 {
00155 fvec3 v = (edges()[i].vertex1() + edges()[i].vertex2()) * 0.5f;
00156 vert_array->at(start+i*2+0) = v;
00157 vert_array->at(start+i*2+1) = v + edges()[i].normal2()*0.25f;
00158 }
00159 #endif
00160 geom->drawCalls()->push_back( new vl::DrawArrays(vl::PT_LINES, 0, (int)vert_array->size()) );
00161 return geom;
00162 }
00163
00164 bool EdgeExtractor::extractEdges(Actor* actor)
00165 {
00166 Geometry* geom = dynamic_cast<Geometry*>(actor->lod(0).get());
00167 if (geom)
00168 extractEdges(geom);
00169 return geom != NULL;
00170 }
00171
00172 void EdgeExtractor::extractEdges(ActorCollection* actors)
00173 {
00174 for(int i=0; i<actors->size(); ++i)
00175 {
00176 Geometry* geom = dynamic_cast<Geometry*>(actors->at(i)->lod(0).get());
00177 if (geom)
00178 extractEdges(geom);
00179 }
00180 }
00181
00182 void EdgeExtractor::extractEdges(SceneManager* scene_manager)
00183 {
00184 ref<ActorCollection> actors = new ActorCollection;
00185 scene_manager->extractActors(*actors);
00186 extractEdges(actors.get());
00187 }
00188
00189 void EdgeExtractor::extractEdges(Rendering* rendering)
00190 {
00191 for(int i=0; i<rendering->sceneManagers()->size(); ++i)
00192 extractEdges(rendering->sceneManagers()->at(i));
00193 }
00194