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 if (mPortalActorMap.find(portal) == mPortalActorMap.end())
00101 {
00102 const fvec4 portal_color = fvec4(1,0,0,0.25f);
00103 vl::ref<vl::Effect> portal_fx = new vl::Effect;
00104
00105
00106 portal_fx->shader()->enable(vl::EN_BLEND);
00107 portal_fx->shader()->gocLineWidth()->set(2.0f);
00108
00109 vl::ref<vl::Geometry> portal_geom = new vl::Geometry;
00110 vl::ref<vl::ArrayFloat3> vert_array = new vl::ArrayFloat3;
00111 portal_geom->setVertexArray(vert_array.get());
00112 portal_geom->setColor(portal_color);
00113 vert_array->resize(portal->geometry().size());
00114 for(unsigned int i=0; i<portal->geometry().size(); ++i)
00115 vert_array->at(i) = portal->geometry()[i];
00116 portal_geom->drawCalls()->push_back( new vl::DrawArrays(vl::PT_LINE_LOOP, 0, (int)vert_array->size()) );
00117 portal_geom->drawCalls()->push_back( new vl::DrawArrays(vl::PT_LINE_LOOP, 0, (int)vert_array->size()) );
00118 portal_geom->drawCalls()->push_back( new vl::DrawArrays(vl::PT_LINE_LOOP, 0, (int)vert_array->size()) );
00119 portal_geom->drawCalls()->push_back( new vl::DrawArrays(vl::PT_POLYGON, 0, (int)vert_array->size()) );
00120 mTempActors.push_back( new vl::Actor(portal_geom.get(), portal_fx.get(), NULL) );
00121 mPortalActorMap[portal] = mTempActors.back();
00122 }
00123 }
00124
00125 void SceneManagerPortals::extractActors(ActorCollection& list)
00126 {
00127 for(unsigned i=0; i<mSectors.size(); ++i)
00128 for(int j=0; j<mSectors[i]->actors()->size(); ++j)
00129 list.push_back( mSectors[i]->actors()->at(j) );
00130 }
00131
00132 void SceneManagerPortals::extractVisibleActors(ActorCollection& list, const Camera* camera)
00133 {
00134 if (cullingEnabled())
00135 {
00136 Sector* start = computeStartingSector(camera);
00137 if (!start)
00138 extractActors(list);
00139 else
00140 {
00141 ++mVisitTick;
00142 mTempActors.clear();
00143 mPortalActorMap.clear();
00144 mFrustumStack.clear();
00145
00146 mFrustumStack.push_back(camera->frustum());
00147 start->executeCallbacks(camera,this,NULL);
00148 visitSector(NULL, start, camera->inverseViewMatrix().getT(), camera);
00149
00150
00151 std::sort(mTempActors.begin(), mTempActors.end());
00152 std::vector< ref<Actor> >::iterator new_end = std::unique(mTempActors.begin(), mTempActors.end());
00153 for(std::vector< ref<Actor> >::iterator it = mTempActors.begin(); it != new_end; ++it)
00154 list.push_back(it->get());
00155 }
00156 }
00157 else
00158 extractActors(list);
00159 }
00160
00161 void SceneManagerPortals::visitSector(Sector* prev, Sector* sector, const vec3& eye, const Camera* camera)
00162 {
00163
00164 for(int j=0; j<sector->actors()->size(); ++j)
00165 {
00166 if (isEnabled(sector->actors()->at(j)))
00167 {
00168 sector->actors()->at(j)->computeBounds();
00169 bool visible = true;
00170 for(unsigned i=0; visible && i<mFrustumStack.size(); ++i)
00171 visible = visible & !mFrustumStack[i].cull( sector->actors()->at(j)->boundingBox() );
00172 if( visible )
00173 mTempActors.push_back( sector->actors()->at(j) );
00174 }
00175 }
00176
00177 for(unsigned j=0; j<sector->portals().size(); ++j)
00178 {
00179 if(showPortals())
00180 renderPortal(sector->portals()[j].get());
00181
00182
00183 if(!sector->portals()[j]->isOpen())
00184 continue;
00185
00186 if (sector->portals()[j]->mVisitTick == mVisitTick)
00187 continue;
00188 else
00189 sector->portals()[j]->mVisitTick = mVisitTick;
00190
00191 Sector* target_sec = sector->portals()[j]->targetSector();
00192 VL_CHECK(target_sec != sector)
00193 if ( target_sec != prev )
00194 {
00195 bool visible = true;
00196 for(unsigned i=0; visible && i<mFrustumStack.size(); ++i)
00197 visible = visible & !mFrustumStack[i].cull( sector->portals()[j]->geometry() );
00198
00199 if (visible)
00200 {
00201
00202 Frustum portal_frustum;
00203 portal_frustum.planes().resize(sector->portals()[j]->geometry().size());
00204 bool flip = dot((fvec3)eye - sector->portals()[j]->geometry()[0], sector->portals()[j]->normal()) < 0;
00205 for(unsigned i=0; i<sector->portals()[j]->geometry().size(); ++i)
00206 {
00207 int i2 = (i+1) % sector->portals()[j]->geometry().size();
00208 vec3 v1 = (vec3)sector->portals()[j]->geometry()[i] - eye;
00209 vec3 v2 = (vec3)sector->portals()[j]->geometry()[i2] - eye;
00210 vec3 n = cross(v1,v2);
00211 n.normalize();
00212 if (flip)
00213 n = -n;
00214 portal_frustum.setPlane(i, Plane(dot(n,eye),n));
00215 }
00216
00217 mFrustumStack.push_back(portal_frustum);
00218 sector->executeCallbacks(camera,this,sector->portals()[j].get());
00219 visitSector(sector, sector->portals()[j]->targetSector(), eye, camera);
00220 mFrustumStack.pop_back();
00221 }
00222 }
00223 }
00224 }
00225
00226 void SceneManagerPortals::computePortalNormals()
00227 {
00228 for(unsigned i=0; i<mSectors.size(); ++i)
00229 for(unsigned j=0; j<mSectors[i]->portals().size(); ++j)
00230 mSectors[i]->portals()[j]->computeNormal();
00231 }
00232
00233 Sector* SceneManagerPortals::computeStartingSector(const Camera* camera)
00234 {
00235 vec3 eye = camera->inverseViewMatrix().getT();
00236 for(unsigned i=0; i<mSectors.size(); ++i)
00237 {
00238 for(unsigned j=0; j<mSectors[i]->volumes().size(); ++j)
00239 {
00240 if (sectors()[i]->volumes()[j].isInside(eye))
00241 return sectors()[i].get();
00242 }
00243 }
00244 return externalSector();
00245 }
00246