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/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
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
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
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
00106
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
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
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
00180 for(unsigned j=0; j<sector->portals().size(); ++j)
00181 {
00182 if(showPortals())
00183 renderPortal(sector->portals()[j].get());
00184
00185
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
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