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 #ifndef DepthSortCallback_INCLUDE_ONCE 00033 #define DepthSortCallback_INCLUDE_ONCE 00034 00035 #include <vlGraphics/Actor.hpp> 00036 #include <vlGraphics/Geometry.hpp> 00037 #include <vlGraphics/Camera.hpp> 00038 00039 namespace vl 00040 { 00074 class DepthSortCallback: public ActorEventCallback 00075 { 00076 VL_INSTRUMENT_CLASS(vl::DepthSortCallback, ActorEventCallback) 00077 00078 template<typename T> 00079 class Point 00080 { 00081 public: 00082 T A; 00083 }; 00084 template<typename T> 00085 class Line 00086 { 00087 public: 00088 T A,B; 00089 }; 00090 template<typename T> 00091 class Triangle 00092 { 00093 public: 00094 T A,B,C; 00095 }; 00096 template<typename T> 00097 class Quad 00098 { 00099 public: 00100 T A,B,C,D; 00101 }; 00102 typedef Point<unsigned int> PointUInt; 00103 typedef Line<unsigned int> LineUInt; 00104 typedef Triangle<unsigned int> TriangleUInt; 00105 typedef Quad<unsigned int> QuadUInt; 00106 00107 typedef Point<unsigned short> PointUShort; 00108 typedef Line<unsigned short> LineUShort; 00109 typedef Triangle<unsigned short> TriangleUShort; 00110 typedef Quad<unsigned short> QuadUShort; 00111 00112 typedef Point<unsigned char> PointUByte; 00113 typedef Line<unsigned char> LineUByte; 00114 typedef Triangle<unsigned char> TriangleUByte; 00115 typedef Quad<unsigned char> QuadUByte; 00116 00117 class PrimitiveZ 00118 { 00119 public: 00120 PrimitiveZ(int tri=0, float z=0.0f): mPrimitiveIndex(tri), mZ(z) {} 00121 unsigned int mPrimitiveIndex; 00122 float mZ; 00123 }; 00124 class Sorter_Back_To_Front 00125 { 00126 public: 00127 bool operator()(const PrimitiveZ& t1, const PrimitiveZ& t2) const { return t1.mZ < t2.mZ; } 00128 }; 00129 class Sorter_Front_To_Back 00130 { 00131 public: 00132 bool operator()(const PrimitiveZ& t1, const PrimitiveZ& t2) const { return t1.mZ > t2.mZ; } 00133 }; 00134 00135 public: 00137 DepthSortCallback() 00138 { 00139 VL_DEBUG_SET_OBJECT_NAME() 00140 setSortMode(SM_SortBackToFront); 00141 } 00142 00143 void onActorDelete(Actor*) {} 00144 00146 virtual void onActorRenderStarted(Actor* actor, real /*frame_clock*/, const Camera* cam, Renderable* renderable, const Shader*, int pass) 00147 { 00148 // need to sort only for the first pass 00149 if (pass > 0) 00150 return; 00151 00152 vl::mat4 matrix = cam->viewMatrix(); 00153 if (actor && actor->transform()) 00154 matrix *= actor->transform()->worldMatrix(); 00155 00156 if (matrix == mCacheMatrix) 00157 return; 00158 else 00159 mCacheMatrix = matrix; 00160 00161 // this works well with LOD 00162 Geometry* geometry = renderable->as<Geometry>(); 00163 00164 if (!geometry) 00165 return; 00166 00167 const ArrayAbstract* verts = geometry->vertexArray() ? geometry->vertexArray() : geometry->vertexAttribArray(vl::VA_Position) ? geometry->vertexAttribArray(vl::VA_Position)->data() : NULL; 00168 00169 if (!verts) 00170 return; 00171 00172 // computes eye-space vertex positions 00173 mat4 m; 00174 if (actor->transform()) 00175 m = cam->viewMatrix() * actor->transform()->worldMatrix(); 00176 else 00177 m = cam->viewMatrix(); 00178 mEyeSpaceVerts.resize( verts->size() ); 00179 // would be nice to optimize this with SEE2 00180 for(size_t i=0; i<verts->size(); ++i) 00181 mEyeSpaceVerts[i] = m * verts->getAsVec3(i); 00182 00183 geometry->setBufferObjectDirty(true); 00184 geometry->setDisplayListDirty(true); 00185 00186 for(int idraw=0; idraw<geometry->drawCalls()->size(); ++idraw) 00187 { 00188 DrawCall* dc = geometry->drawCalls()->at(idraw); 00189 if (dc->classType() == DrawElementsUInt::Type()) 00190 sort<unsigned int, DrawElementsUInt>(dc->as<DrawElementsUInt>(), mSortedPointsUInt, mSortedLinesUInt, mSortedTrianglesUInt, mSortedQuadsUInt); 00191 else 00192 if (dc->classType() == DrawElementsUShort::Type()) 00193 sort<unsigned short, DrawElementsUShort>(dc->as<DrawElementsUShort>(), mSortedPointsUShort, mSortedLinesUShort, mSortedTrianglesUShort, mSortedQuadsUShort); 00194 else 00195 if (dc->classType() == DrawElementsUByte::Type()) 00196 sort<unsigned char, DrawElementsUByte>(dc->as<DrawElementsUByte>(), mSortedPointsUByte, mSortedLinesUByte, mSortedTrianglesUByte, mSortedQuadsUByte); 00197 } 00198 } 00199 00200 template<typename T, typename deT> 00201 void sort(deT* polys, std::vector<Point<T> >& sorted_points, std::vector<Line<T> >& sorted_lines, std::vector<Triangle<T> >& sorted_triangles, std::vector<Quad<T> >& sorted_quads) 00202 { 00203 if (polys->primitiveType() == PT_QUADS) 00204 { 00205 // compute zetas 00206 mPrimitiveZ.resize( polys->indexBuffer()->size() / 4 ); 00207 if (mPrimitiveZ.empty()) 00208 return; 00209 00210 const typename deT::index_type* it = polys->indexBuffer()->begin(); 00211 const typename deT::index_type* end = polys->indexBuffer()->end(); 00212 for(unsigned iz=0; it != end; it+=4, ++iz) 00213 { 00214 mPrimitiveZ[iz].mZ = (float)(mEyeSpaceVerts[it[0]].z() + mEyeSpaceVerts[it[1]].z() + mEyeSpaceVerts[it[2]].z() + mEyeSpaceVerts[it[3]].z()); 00215 mPrimitiveZ[iz].mPrimitiveIndex = iz; 00216 } 00217 00218 // sort based on mPrimitiveZ 00219 if (sortMode() == SM_SortBackToFront) 00220 std::sort( mPrimitiveZ.begin(), mPrimitiveZ.end(), Sorter_Back_To_Front() ); 00221 else 00222 std::sort( mPrimitiveZ.begin(), mPrimitiveZ.end(), Sorter_Front_To_Back() ); 00223 00224 // regenerate the sorted indices 00225 sorted_quads.resize( polys->indexBuffer()->size() / 4 ); 00226 Quad<T>* tris = (Quad<T>*)polys->indexBuffer()->ptr(); 00227 for(unsigned int i=0; i<mPrimitiveZ.size(); ++i) 00228 sorted_quads[i] = tris[ mPrimitiveZ[i].mPrimitiveIndex ]; 00229 memcpy(&tris[0], &sorted_quads[0], sizeof(sorted_quads[0])*sorted_quads.size() ); 00230 } 00231 else 00232 if (polys->primitiveType() == PT_TRIANGLES) 00233 { 00234 // compute zetas 00235 mPrimitiveZ.resize( polys->indexBuffer()->size() / 3 ); 00236 if (mPrimitiveZ.empty()) 00237 return; 00238 00239 const typename deT::index_type* it = polys->indexBuffer()->begin(); 00240 const typename deT::index_type* end = polys->indexBuffer()->end(); 00241 for(unsigned iz=0; it != end; it+=3, ++iz) 00242 { 00243 mPrimitiveZ[iz].mZ = (float)(mEyeSpaceVerts[it[0]].z() + mEyeSpaceVerts[it[1]].z() + mEyeSpaceVerts[it[2]].z()); 00244 mPrimitiveZ[iz].mPrimitiveIndex = iz; 00245 } 00246 00247 // sort based on mPrimitiveZ 00248 if (sortMode() == SM_SortBackToFront) 00249 std::sort( mPrimitiveZ.begin(), mPrimitiveZ.end(), Sorter_Back_To_Front() ); 00250 else 00251 std::sort( mPrimitiveZ.begin(), mPrimitiveZ.end(), Sorter_Front_To_Back() ); 00252 00253 // regenerate the sorted indices 00254 sorted_triangles.resize( polys->indexBuffer()->size() / 3 ); 00255 Triangle<T>* tris = (Triangle<T>*)polys->indexBuffer()->ptr(); 00256 for(unsigned int i=0; i<mPrimitiveZ.size(); ++i) 00257 sorted_triangles[i] = tris[ mPrimitiveZ[i].mPrimitiveIndex ]; 00258 memcpy(&tris[0], &sorted_triangles[0], sizeof(sorted_triangles[0])*sorted_triangles.size() ); 00259 } 00260 else 00261 if (polys->primitiveType() == PT_LINES) 00262 { 00263 // compute zetas 00264 mPrimitiveZ.resize( polys->indexBuffer()->size() / 2 ); 00265 if (mPrimitiveZ.empty()) 00266 return; 00267 00268 const typename deT::index_type* it = polys->indexBuffer()->begin(); 00269 const typename deT::index_type* end = polys->indexBuffer()->end(); 00270 for(unsigned iz=0; it != end; it+=2, ++iz) 00271 { 00272 mPrimitiveZ[iz].mZ = (float)(mEyeSpaceVerts[it[0]].z() + mEyeSpaceVerts[it[1]].z()); 00273 mPrimitiveZ[iz].mPrimitiveIndex = iz; 00274 } 00275 00276 // sort based on mPrimitiveZ 00277 if (sortMode() == SM_SortBackToFront) 00278 std::sort( mPrimitiveZ.begin(), mPrimitiveZ.end(), Sorter_Back_To_Front() ); 00279 else 00280 std::sort( mPrimitiveZ.begin(), mPrimitiveZ.end(), Sorter_Front_To_Back() ); 00281 00282 // regenerate the sorted indices 00283 sorted_lines.resize( polys->indexBuffer()->size() / 2 ); 00284 Line<T>* tris = (Line<T>*)polys->indexBuffer()->ptr(); 00285 for(unsigned int i=0; i<mPrimitiveZ.size(); ++i) 00286 sorted_lines[i] = tris[ mPrimitiveZ[i].mPrimitiveIndex ]; 00287 memcpy(&tris[0], &sorted_lines[0], sizeof(sorted_lines[0])*sorted_lines.size() ); 00288 } 00289 else 00290 if (polys->primitiveType() == PT_POINTS) 00291 { 00292 // compute zetas 00293 mPrimitiveZ.resize( polys->indexBuffer()->size() ); 00294 if (mPrimitiveZ.empty()) 00295 return; 00296 00297 const typename deT::index_type* it = polys->indexBuffer()->begin(); 00298 const typename deT::index_type* end = polys->indexBuffer()->end(); 00299 for(unsigned iz=0; it != end; ++it, ++iz) 00300 { 00301 mPrimitiveZ[iz].mZ = (float)mEyeSpaceVerts[it[0]].z(); 00302 mPrimitiveZ[iz].mPrimitiveIndex = iz; 00303 } 00304 00305 // sort based on mPrimitiveZ 00306 if (sortMode() == SM_SortBackToFront) 00307 std::sort( mPrimitiveZ.begin(), mPrimitiveZ.end(), Sorter_Back_To_Front() ); 00308 else 00309 std::sort( mPrimitiveZ.begin(), mPrimitiveZ.end(), Sorter_Front_To_Back() ); 00310 00311 // regenerate the sorted indices 00312 sorted_points.resize( polys->indexBuffer()->size() ); 00313 Point<T>* tris = (Point<T>*)polys->indexBuffer()->ptr(); 00314 for(unsigned int i=0; i<mPrimitiveZ.size(); ++i) 00315 sorted_points[i] = tris[ mPrimitiveZ[i].mPrimitiveIndex ]; 00316 memcpy(&tris[0], &sorted_points[0], sizeof(sorted_points[0])*sorted_points.size() ); 00317 } 00318 00319 if (Has_BufferObject) 00320 { 00321 if (polys->indexBuffer()->bufferObject()->handle()) 00322 { 00323 if (polys->indexBuffer()->bufferObject()->usage() != vl::BU_DYNAMIC_DRAW) 00324 { 00325 polys->indexBuffer()->bufferObject()->setBufferData(vl::BU_DYNAMIC_DRAW); 00326 polys->indexBuffer()->setBufferObjectDirty(false); 00327 } 00328 else 00329 polys->indexBuffer()->setBufferObjectDirty(true); 00330 } 00331 } 00332 } 00333 00334 ESortMode sortMode() const { return mSortMode; } 00335 void setSortMode(ESortMode sort_mode) { mSortMode = sort_mode; } 00336 00340 void invalidateCache() { mCacheMatrix = vl::mat4(); } 00341 00342 protected: 00343 std::vector<vec3> mEyeSpaceVerts; 00344 std::vector<PrimitiveZ> mPrimitiveZ; 00345 00346 std::vector<PointUInt> mSortedPointsUInt; 00347 std::vector<LineUInt> mSortedLinesUInt; 00348 std::vector<TriangleUInt> mSortedTrianglesUInt; 00349 std::vector<QuadUInt> mSortedQuadsUInt; 00350 00351 std::vector<PointUShort> mSortedPointsUShort; 00352 std::vector<LineUShort> mSortedLinesUShort; 00353 std::vector<TriangleUShort> mSortedTrianglesUShort; 00354 std::vector<QuadUShort> mSortedQuadsUShort; 00355 00356 std::vector<PointUByte> mSortedPointsUByte; 00357 std::vector<LineUByte> mSortedLinesUByte; 00358 std::vector<TriangleUByte> mSortedTrianglesUByte; 00359 std::vector<QuadUByte> mSortedQuadsUByte; 00360 00361 vl::mat4 mCacheMatrix; 00362 00363 ESortMode mSortMode; 00364 }; 00365 } 00366 00367 #endif