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/SceneManagerPortals.hpp> 00033 #include <vlGraphics/Geometry.hpp> 00034 #include <vlCore/Say.hpp> 00035 #include <vlGraphics/Camera.hpp> 00036 00037 using namespace vl; 00038 00039 //----------------------------------------------------------------------------- 00040 // Portal 00041 //----------------------------------------------------------------------------- 00042 bool Portal::computeNormal() 00043 { 00044 mNormal = 0; 00045 if (geometry().size() < 3) 00046 { 00047 vl::Log::error("Portal::computeNormal() error, no portal geometry defined.\n"); 00048 return false; 00049 } 00050 if (!mTargetSector) 00051 { 00052 vl::Log::error("Portal::computeNormal() error, no sector bound to this portal.\n"); 00053 return false; 00054 } 00055 00056 fvec3 v0 = geometry()[0]; 00057 fvec3 v1 = geometry()[1] - v0; 00058 fvec3 v2 = geometry()[2] - v0; 00059 mNormal = cross(v1,v2); 00060 00061 return true; 00062 } 00063 //----------------------------------------------------------------------------- 00064 // Sector 00065 //----------------------------------------------------------------------------- 00066 AABB Sector::computeBoundingBox() 00067 { 00068 AABB aabb; 00069 for(int i=0; i<actors()->size(); ++i) 00070 { 00071 actors()->at(i)->computeBounds(); 00072 aabb += actors()->at(i)->boundingBox(); 00073 } 00074 return aabb; 00075 } 00076 //----------------------------------------------------------------------------- 00077 void Sector::executeCallbacks(const Camera*cam,SceneManagerPortals* psm, Portal*p) 00078 { 00079 for(unsigned i=0; i<callbacks().size(); ++i) 00080 callbacks()[i]->operator()(cam,psm,this,p); 00081 } 00082 //----------------------------------------------------------------------------- 00083 // SceneManagerPortals 00084 //----------------------------------------------------------------------------- 00085 void SceneManagerPortals::initialize() 00086 { 00087 computePortalNormals(); 00088 for(unsigned i=0; i<mSectors.size(); ++i) 00089 { 00090 if (mSectors[i]->volumes().empty()) 00091 vl::Log::error( vl::Say("Sector #%n does not have any volume!\n") << i ); 00092 for(unsigned j=0; j<mSectors[i]->portals().size(); ++j) 00093 if (!mSectors[i]->portals()[j]->targetSector()) 00094 vl::Log::error( vl::Say("In Sector #%n Portal #%n does not have any target sector!\n") << i << j); 00095 } 00096 } 00097 //----------------------------------------------------------------------------- 00098 void SceneManagerPortals::renderPortal(Portal* portal) 00099 { 00100 std::map<Portal*, ref<Actor> >::iterator it = mPortalActorMap.find(portal); 00101 if (it == mPortalActorMap.end()) 00102 { 00103 const fvec4 portal_color = fvec4(1,0,0,0.25f); 00104 vl::ref<vl::Effect> portal_fx = new vl::Effect; 00105 /*portal_fx->shader()->enable(vl::EN_DEPTH_TEST); 00106 portal_fx->shader()->gocDepthFunc()->set(vl::FU_LEQUAL);*/ 00107 portal_fx->shader()->enable(vl::EN_BLEND); 00108 portal_fx->shader()->gocLineWidth()->set(2.0f); 00109 portal_fx->shader()->gocColor()->setValue(portal_color); 00110 00111 vl::ref<vl::Geometry> portal_geom = new vl::Geometry; 00112 vl::ref<vl::ArrayFloat3> vert_array = new vl::ArrayFloat3; 00113 portal_geom->setVertexArray(vert_array.get()); 00114 vert_array->resize(portal->geometry().size()); 00115 for(unsigned int i=0; i<portal->geometry().size(); ++i) 00116 vert_array->at(i) = portal->geometry()[i]; 00117 portal_geom->drawCalls()->push_back( new vl::DrawArrays(vl::PT_LINE_LOOP, 0, (int)vert_array->size()) ); 00118 #if defined(VL_OPENGL) 00119 portal_geom->drawCalls()->push_back( new vl::DrawArrays(vl::PT_POLYGON, 0, (int)vert_array->size()) ); 00120 #endif 00121 ref<Actor> actor = new vl::Actor(portal_geom.get(), portal_fx.get(), NULL); 00122 mPortalActorMap[portal] = actor; 00123 mTempActors.push_back(actor); 00124 } 00125 else 00126 mTempActors.push_back(it->second); 00127 } 00128 //----------------------------------------------------------------------------- 00129 void SceneManagerPortals::extractActors(ActorCollection& list) 00130 { 00131 for(unsigned i=0; i<mSectors.size(); ++i) 00132 for(int j=0; j<mSectors[i]->actors()->size(); ++j) 00133 list.push_back( mSectors[i]->actors()->at(j) ); 00134 } 00135 //----------------------------------------------------------------------------- 00136 void SceneManagerPortals::extractVisibleActors(ActorCollection& list, const Camera* camera) 00137 { 00138 if (cullingEnabled()) 00139 { 00140 Sector* start = computeStartingSector(camera); 00141 if (!start) 00142 extractActors(list); 00143 else 00144 { 00145 ++mVisitTick; 00146 mTempActors.clear(); 00147 mFrustumStack.clear(); 00148 00149 mFrustumStack.push_back(camera->frustum()); 00150 start->executeCallbacks(camera,this,NULL); 00151 visitSector(NULL, start, camera->modelingMatrix().getT(), camera); 00152 00153 // remove duplicates 00154 std::sort(mTempActors.begin(), mTempActors.end()); 00155 std::vector< ref<Actor> >::iterator new_end = std::unique(mTempActors.begin(), mTempActors.end()); 00156 for(std::vector< ref<Actor> >::iterator it = mTempActors.begin(); it != new_end; ++it) 00157 list.push_back(it->get()); 00158 } 00159 } 00160 else 00161 extractActors(list); 00162 } 00163 //----------------------------------------------------------------------------- 00164 void SceneManagerPortals::visitSector(Sector* prev, Sector* sector, const vec3& eye, const Camera* camera) 00165 { 00166 // this sector is visible so we add the visible objects 00167 for(int j=0; j<sector->actors()->size(); ++j) 00168 { 00169 if (isEnabled(sector->actors()->at(j))) 00170 { 00171 sector->actors()->at(j)->computeBounds(); 00172 bool visible = true; 00173 for(unsigned i=0; visible && i<mFrustumStack.size(); ++i) 00174 visible = visible & !mFrustumStack[i].cull( sector->actors()->at(j)->boundingBox() ); 00175 if( visible ) 00176 mTempActors.push_back( sector->actors()->at(j) ); 00177 } 00178 } 00179 // check the visible portals 00180 for(unsigned j=0; j<sector->portals().size(); ++j) 00181 { 00182 if(showPortals()) 00183 renderPortal(sector->portals()[j].get()); 00184 00185 // open/closed portals. 00186 if(!sector->portals()[j]->isOpen()) 00187 continue; 00188 00189 if (sector->portals()[j]->mVisitTick == mVisitTick) 00190 continue; 00191 else 00192 sector->portals()[j]->mVisitTick = mVisitTick; 00193 00194 Sector* target_sec = sector->portals()[j]->targetSector(); 00195 VL_CHECK(target_sec != sector) 00196 if ( target_sec != prev ) 00197 { 00198 bool visible = true; 00199 for(unsigned i=0; visible && i<mFrustumStack.size(); ++i) 00200 visible = visible & !mFrustumStack[i].cull( sector->portals()[j]->geometry() ); 00201 00202 if (visible) 00203 { 00204 // make visiting_portal_frustum 00205 Frustum portal_frustum; 00206 portal_frustum.planes().resize(sector->portals()[j]->geometry().size()); 00207 bool flip = dot((fvec3)eye - sector->portals()[j]->geometry()[0], sector->portals()[j]->normal()) < 0; 00208 for(unsigned i=0; i<sector->portals()[j]->geometry().size(); ++i) 00209 { 00210 int i2 = (i+1) % sector->portals()[j]->geometry().size(); 00211 vec3 v1 = (vec3)sector->portals()[j]->geometry()[i] - eye; 00212 vec3 v2 = (vec3)sector->portals()[j]->geometry()[i2] - eye; 00213 vec3 n = cross(v1,v2); 00214 n.normalize(); 00215 if (flip) 00216 n = -n; 00217 portal_frustum.setPlane(i, Plane(dot(n,eye),n)); 00218 } 00219 00220 mFrustumStack.push_back(portal_frustum); 00221 sector->executeCallbacks(camera,this,sector->portals()[j].get()); 00222 visitSector(sector, sector->portals()[j]->targetSector(), eye, camera); 00223 mFrustumStack.pop_back(); 00224 } 00225 } 00226 } 00227 } 00228 //----------------------------------------------------------------------------- 00229 void SceneManagerPortals::computePortalNormals() 00230 { 00231 for(unsigned i=0; i<mSectors.size(); ++i) 00232 for(unsigned j=0; j<mSectors[i]->portals().size(); ++j) 00233 mSectors[i]->portals()[j]->computeNormal(); 00234 } 00235 //----------------------------------------------------------------------------- 00236 Sector* SceneManagerPortals::computeStartingSector(const Camera* camera) 00237 { 00238 vec3 eye = camera->modelingMatrix().getT(); 00239 for(unsigned i=0; i<mSectors.size(); ++i) 00240 { 00241 for(unsigned j=0; j<mSectors[i]->volumes().size(); ++j) 00242 { 00243 if (sectors()[i]->volumes()[j].isInside(eye)) 00244 return sectors()[i].get(); 00245 } 00246 } 00247 return externalSector(); 00248 } 00249 //-----------------------------------------------------------------------------