Visualization Library 2.0.0

A lightweight C++ OpenGL middleware for 2D/3D graphics

VL     Star     Watch     Fork     Issue

[Download] [Tutorials] [All Classes] [Grouped Classes]
SceneManagerPortals.cpp
Go to the documentation of this file.
1 /**************************************************************************************/
2 /* */
3 /* Visualization Library */
4 /* http://visualizationlibrary.org */
5 /* */
6 /* Copyright (c) 2005-2020, Michele Bosi */
7 /* All rights reserved. */
8 /* */
9 /* Redistribution and use in source and binary forms, with or without modification, */
10 /* are permitted provided that the following conditions are met: */
11 /* */
12 /* - Redistributions of source code must retain the above copyright notice, this */
13 /* list of conditions and the following disclaimer. */
14 /* */
15 /* - Redistributions in binary form must reproduce the above copyright notice, this */
16 /* list of conditions and the following disclaimer in the documentation and/or */
17 /* other materials provided with the distribution. */
18 /* */
19 /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND */
20 /* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED */
21 /* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE */
22 /* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR */
23 /* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES */
24 /* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; */
25 /* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON */
26 /* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */
27 /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */
28 /* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
29 /* */
30 /**************************************************************************************/
31 
33 #include <vlGraphics/Geometry.hpp>
34 #include <vlCore/Say.hpp>
35 #include <vlGraphics/Camera.hpp>
36 
37 using namespace vl;
38 
39 //-----------------------------------------------------------------------------
40 // Portal
41 //-----------------------------------------------------------------------------
43 {
44  mNormal = 0;
45  if (geometry().size() < 3)
46  {
47  vl::Log::error("Portal::computeNormal() error, no portal geometry defined.\n");
48  return false;
49  }
50  if (!mTargetSector)
51  {
52  vl::Log::error("Portal::computeNormal() error, no sector bound to this portal.\n");
53  return false;
54  }
55 
56  fvec3 v0 = geometry()[0];
57  fvec3 v1 = geometry()[1] - v0;
58  fvec3 v2 = geometry()[2] - v0;
59  mNormal = cross(v1,v2);
60 
61  return true;
62 }
63 //-----------------------------------------------------------------------------
64 // Sector
65 //-----------------------------------------------------------------------------
67 {
68  AABB aabb;
69  for(int i=0; i<actors()->size(); ++i)
70  {
71  actors()->at(i)->computeBounds();
72  aabb += actors()->at(i)->boundingBox();
73  }
74  return aabb;
75 }
76 //-----------------------------------------------------------------------------
78 {
79  for(unsigned i=0; i<callbacks().size(); ++i)
80  callbacks()[i]->operator()(cam,psm,this,p);
81 }
82 //-----------------------------------------------------------------------------
83 // SceneManagerPortals
84 //-----------------------------------------------------------------------------
86 {
87  computePortalNormals();
88  for(unsigned i=0; i<mSectors.size(); ++i)
89  {
90  if (mSectors[i]->volumes().empty())
91  vl::Log::error( vl::Say("Sector #%n does not have any volume!\n") << i );
92  for(unsigned j=0; j<mSectors[i]->portals().size(); ++j)
93  if (!mSectors[i]->portals()[j]->targetSector())
94  vl::Log::error( vl::Say("In Sector #%n Portal #%n does not have any target sector!\n") << i << j);
95  }
96 }
97 //-----------------------------------------------------------------------------
99 {
100  std::map<Portal*, ref<Actor> >::iterator it = mPortalActorMap.find(portal);
101  if (it == mPortalActorMap.end())
102  {
103  const fvec4 portal_color = fvec4(1,0,0,0.25f);
104  vl::ref<vl::Effect> portal_fx = new vl::Effect;
105  /*portal_fx->shader()->enable(vl::EN_DEPTH_TEST);
106  portal_fx->shader()->gocDepthFunc()->set(vl::FU_LEQUAL);*/
107  portal_fx->shader()->enable(vl::EN_BLEND);
108  portal_fx->shader()->gocLineWidth()->set(2.0f);
109  portal_fx->shader()->gocColor()->setValue(portal_color);
110 
111  vl::ref<vl::Geometry> portal_geom = new vl::Geometry;
112  vl::ref<vl::ArrayFloat3> vert_array = new vl::ArrayFloat3;
113  portal_geom->setVertexArray(vert_array.get());
114  vert_array->resize(portal->geometry().size());
115  for(unsigned int i=0; i<portal->geometry().size(); ++i)
116  vert_array->at(i) = portal->geometry()[i];
117  portal_geom->drawCalls().push_back( new vl::DrawArrays(vl::PT_LINE_LOOP, 0, (int)vert_array->size()) );
118 #if defined(VL_OPENGL)
119  portal_geom->drawCalls().push_back( new vl::DrawArrays(vl::PT_POLYGON, 0, (int)vert_array->size()) );
120 #endif
121  ref<Actor> actor = new vl::Actor(portal_geom.get(), portal_fx.get(), NULL);
122  mPortalActorMap[portal] = actor;
123  mTempActors.push_back(actor);
124  }
125  else
126  mTempActors.push_back(it->second);
127 }
128 //-----------------------------------------------------------------------------
130 {
131  for(unsigned i=0; i<mSectors.size(); ++i)
132  for(int j=0; j<mSectors[i]->actors()->size(); ++j)
133  list.push_back( mSectors[i]->actors()->at(j) );
134 }
135 //-----------------------------------------------------------------------------
137 {
138  if (cullingEnabled())
139  {
140  Sector* start = computeStartingSector(camera);
141  if (!start)
142  extractActors(list);
143  else
144  {
145  ++mVisitTick;
146  mTempActors.clear();
147  mFrustumStack.clear();
148 
149  mFrustumStack.push_back(camera->frustum());
150  start->executeCallbacks(camera,this,NULL);
151  visitSector(NULL, start, camera->modelingMatrix().getT(), camera);
152 
153  // remove duplicates
154  std::sort(mTempActors.begin(), mTempActors.end());
155  std::vector< ref<Actor> >::iterator new_end = std::unique(mTempActors.begin(), mTempActors.end());
156  for(std::vector< ref<Actor> >::iterator it = mTempActors.begin(); it != new_end; ++it)
157  list.push_back(it->get());
158  }
159  }
160  else
161  extractActors(list);
162 }
163 //-----------------------------------------------------------------------------
164 void SceneManagerPortals::visitSector(Sector* prev, Sector* sector, const vec3& eye, const Camera* camera)
165 {
166  // this sector is visible so we add the visible objects
167  for(int j=0; j<sector->actors()->size(); ++j)
168  {
169  if (isEnabled(sector->actors()->at(j)))
170  {
171  sector->actors()->at(j)->computeBounds();
172  bool visible = true;
173  for(unsigned i=0; visible && i<mFrustumStack.size(); ++i)
174  visible = visible & !mFrustumStack[i].cull( sector->actors()->at(j)->boundingBox() );
175  if( visible )
176  mTempActors.push_back( sector->actors()->at(j) );
177  }
178  }
179  // check the visible portals
180  for(unsigned j=0; j<sector->portals().size(); ++j)
181  {
182  if(showPortals())
183  renderPortal(sector->portals()[j].get());
184 
185  // open/closed portals.
186  if(!sector->portals()[j]->isOpen())
187  continue;
188 
189  if (sector->portals()[j]->mVisitTick == mVisitTick)
190  continue;
191  else
192  sector->portals()[j]->mVisitTick = mVisitTick;
193 
194  Sector* target_sec = sector->portals()[j]->targetSector();
195  VL_CHECK(target_sec != sector)
196  if ( target_sec != prev )
197  {
198  bool visible = true;
199  for(unsigned i=0; visible && i<mFrustumStack.size(); ++i)
200  visible = visible & !mFrustumStack[i].cull( sector->portals()[j]->geometry() );
201 
202  if (visible)
203  {
204  // make visiting_portal_frustum
205  Frustum portal_frustum;
206  portal_frustum.planes().resize(sector->portals()[j]->geometry().size());
207  bool flip = dot((fvec3)eye - sector->portals()[j]->geometry()[0], sector->portals()[j]->normal()) < 0;
208  for(unsigned i=0; i<sector->portals()[j]->geometry().size(); ++i)
209  {
210  int i2 = (i+1) % sector->portals()[j]->geometry().size();
211  vec3 v1 = (vec3)sector->portals()[j]->geometry()[i] - eye;
212  vec3 v2 = (vec3)sector->portals()[j]->geometry()[i2] - eye;
213  vec3 n = cross(v1,v2);
214  n.normalize();
215  if (flip)
216  n = -n;
217  portal_frustum.setPlane(i, Plane(dot(n,eye),n));
218  }
219 
220  mFrustumStack.push_back(portal_frustum);
221  sector->executeCallbacks(camera,this,sector->portals()[j].get());
222  visitSector(sector, sector->portals()[j]->targetSector(), eye, camera);
223  mFrustumStack.pop_back();
224  }
225  }
226  }
227 }
228 //-----------------------------------------------------------------------------
230 {
231  for(unsigned i=0; i<mSectors.size(); ++i)
232  for(unsigned j=0; j<mSectors[i]->portals().size(); ++j)
233  mSectors[i]->portals()[j]->computeNormal();
234 }
235 //-----------------------------------------------------------------------------
237 {
238  vec3 eye = camera->modelingMatrix().getT();
239  for(unsigned i=0; i<mSectors.size(); ++i)
240  {
241  for(unsigned j=0; j<mSectors[i]->volumes().size(); ++j)
242  {
243  if (sectors()[i]->volumes()[j].isInside(eye))
244  return sectors()[i].get();
245  }
246  }
247  return externalSector();
248 }
249 //-----------------------------------------------------------------------------
Associates a Renderable object to an Effect and Transform.
Definition: Actor.hpp:130
Sector * computeStartingSector(const Camera *camera)
const T * at(int i) const
Definition: Collection.hpp:100
The SceneManagerPortals calss implements a portal-based hidden surface removal algorithm to efficentl...
const Vector3 & normalize(T_Scalar *len=NULL)
Definition: Vector3.hpp:227
LineWidth * gocLineWidth()
Definition: Shader.cpp:131
const T * get() const
Definition: Object.hpp:128
Color * gocColor()
Definition: Shader.cpp:103
void visitSector(Sector *prev, Sector *sector, const vec3 &eye, const Camera *camera)
Vector4< float > fvec4
A 4 components vector with float precision.
Definition: Vector4.hpp:279
A simple String formatting class.
Definition: Say.hpp:124
The Plane class defines a plane using a normal and an origin.
Definition: Plane.hpp:49
void computePortalNormals()
Compute the normal of the sectors.
void setPlane(unsigned i, const Plane &plane)
Definition: Frustum.hpp:57
A set of planes defining a frustum used for culling purposes (frustum culling).
Definition: Frustum.hpp:49
bool computeNormal()
Computes the normal of the portal polygon.
int size() const
Definition: Collection.hpp:82
std::vector< Plane > & planes()
Definition: Frustum.hpp:54
AABB computeBoundingBox()
Returns the bounding box of all the Actors in the sector.
If enabled, blend the incoming RGBA color values with the values in the color buffers, see also BlendFunc for more information.
static void error(const String &message)
Use this function to provide information about run-time errors: file not found, out of memory...
Definition: Log.cpp:165
void setVertexArray(ArrayAbstract *data)
Conventional vertex array.
Definition: Geometry.cpp:155
ActorCollection * actors()
The Actor object contained in a sector. An actor can be part of multiple sectors. ...
void resize(size_t dim)
Definition: Array.hpp:233
fvec3 cross(const fvec3 &v1, const fvec3 &v2)
Definition: Vector3.hpp:277
std::vector< fvec3 > & geometry()
The set of points defining the shape of the portal. The points must define a planar convex polygon an...
Sector * mTargetSector
size_t size() const
Returns the number of elements of an array.
Definition: Array.hpp:235
The Geometry class is a Renderable that implements a polygonal mesh made of polygons, lines and points.
Definition: Geometry.hpp:66
Visualization Library main namespace.
unsigned int mVisitTick
float dot(float a, float b)
Definition: glsl_math.hpp:1111
const Frustum & frustum() const
The view frustum of the camera used to perform frustum culling.
Definition: Camera.hpp:132
void set(float linewidth)
Definition: Shader.hpp:1097
void extractActors(ActorCollection &list)
Appends to the given list all the Actors contained in the scene regardless of their visibility...
The AABB class implements an axis-aligned bounding box using vl::real precision.
Definition: AABB.hpp:44
const mat4 & modelingMatrix() const
Returns the Camera&#39;s modelingMatrix() (inverse of the view matrix).
Definition: Camera.hpp:169
void push_back(T *data)
Definition: Collection.hpp:76
void renderPortal(Portal *portal)
const AABB & boundingBox() const
Returns the bounding box (not guaranteed to be up to date) that contains this Actor.
Definition: Actor.hpp:205
#define NULL
Definition: OpenGLDefs.hpp:81
void extractVisibleActors(ActorCollection &list, const Camera *camera)
Appends to the given list all the visible Actors using the portal culling algorithm.
Shader * shader(int lodi=0, int pass=0)
Utility function, same as &#39;lod(lodi)->at(pass);&#39;.
Definition: Effect.hpp:178
Defines the sequence of Shader objects used to render an Actor.
Definition: Effect.hpp:91
Defines an area containg a set if Actors that is connected to other Sector[s] through its Portal[s]...
Vector3< T_Scalar > getT() const
Definition: Matrix4.hpp:131
T_VectorType & at(size_t i)
Definition: Array.hpp:255
Defined as a simple subclass of Collection<Actor>, see Collection for more information.
Definition: Actor.hpp:479
fvec3 vec3
Defined as: &#39;typedef fvec3 vec3&#39;. See also VL_PIPELINE_PRECISION.
Definition: Vector3.hpp:269
void executeCallbacks(const Camera *cam, SceneManagerPortals *psm, Portal *p)
void computeBounds()
Computes the bounding box and bounding sphere of an Actor if boundsDirty().
Definition: Actor.cpp:95
void setValue(const fvec4 &color)
Definition: Shader.hpp:108
void initialize()
Calls computePortalNormals() and performs some error checking.
An array of vl::fvec3.
Definition: Array.hpp:414
Represents a virtual camera defining, among other things, the point of view from which scenes can be ...
Definition: Camera.hpp:50
Wraps the OpenGL function glDrawArrays().
Definition: DrawArrays.hpp:57
#define VL_CHECK(expr)
Definition: checks.hpp:73
void enable(EEnable capability)
Definition: Shader.hpp:2158
A planar convex polygon used to define the visibility from one Sector to another. ...
std::vector< ref< Portal > > & portals()
The portals within a sector that connect it to other sectors.
Collection< DrawCall > & drawCalls()
Returns the list of DrawCall objects bound to a Geometry.
Definition: Geometry.hpp:102