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