00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "xrb_engine2_visibilityquadtree.hpp"
00012
00013 #include <algorithm>
00014
00015 #include "xrb_engine2_entity.hpp"
00016 #include "xrb_engine2_objectlayer.hpp"
00017 #include "xrb_gl.hpp"
00018 #include "xrb_render.hpp"
00019 #include "xrb_rendercontext.hpp"
00020 #include "xrb_serializer.hpp"
00021
00022 namespace Xrb
00023 {
00024
00025
00026
00027
00028
00029 Engine2::VisibilityQuadTree::VisibilityQuadTree (
00030 FloatVector2 const ¢er,
00031 Float const half_side_length,
00032 Uint8 const depth)
00033 :
00034 QuadTree(NULL)
00035 {
00036 Initialize<VisibilityQuadTree>(center, half_side_length, depth);
00037 SetQuadTreeType(QTT_VISIBILITY);
00038 }
00039
00040 Engine2::VisibilityQuadTree *Engine2::VisibilityQuadTree::Create (Serializer &serializer)
00041 {
00042 VisibilityQuadTree *retval = new VisibilityQuadTree(NULL);
00043
00044 retval->ReadStructure(serializer);
00045 retval->SetQuadTreeType(QTT_VISIBILITY);
00046
00047
00048
00049 return retval;
00050 }
00051
00052 void Engine2::VisibilityQuadTree::ReadStructure (Serializer &serializer)
00053 {
00054
00055 m_center = serializer.ReadFloatVector2();
00056 serializer.ReadFloat(&m_half_side_length);
00057 serializer.ReadFloat(&m_radius);
00058 bool has_children = serializer.ReadBool();
00059
00060 if (has_children)
00061 {
00062 for (Uint8 i = 0; i < 4; ++i)
00063 {
00064 ASSERT1(m_child[i] == NULL);
00065 m_child[i] = new VisibilityQuadTree(this);
00066 Child<VisibilityQuadTree>(i)->ReadStructure(serializer);
00067 }
00068 }
00069 }
00070
00071 void Engine2::VisibilityQuadTree::WriteStructure (Serializer &serializer) const
00072 {
00073
00074 serializer.WriteFloatVector2(m_center);
00075 serializer.WriteFloat(m_half_side_length);
00076 serializer.WriteFloat(m_radius);
00077 serializer.WriteBool(HasChildren());
00078
00079 if (HasChildren())
00080 for (Uint8 i = 0; i < 4; ++i)
00081 Child<VisibilityQuadTree>(i)->WriteStructure(serializer);
00082 }
00083
00084 void Engine2::VisibilityQuadTree::ReadObjects (
00085 Serializer &serializer,
00086 Engine2::ObjectLayer *const object_layer)
00087 {
00088 ASSERT1(object_layer != NULL);
00089
00090 fprintf(stderr, "Engine2::VisibilityQuadTree::ReadObjects();\n");
00091 Uint32 static_object_count = serializer.ReadUint32();
00092 while (static_object_count > 0)
00093 {
00094
00095
00096 Object *object = Object::Create(serializer, NULL);
00097 ASSERT1(!object->IsDynamic());
00098 object_layer->AddObject(object);
00099 --static_object_count;
00100 }
00101 }
00102
00103 Uint32 Engine2::VisibilityQuadTree::WriteObjects (Serializer &serializer) const
00104 {
00105
00106
00107 if (Parent() == NULL)
00108 serializer.WriteUint32(SubordinateStaticObjectCount());
00109
00110
00111 Uint32 retval = 0;
00112
00113
00114 for (ObjectSet::const_iterator it = m_object_set.begin(),
00115 it_end = m_object_set.end();
00116 it != it_end;
00117 ++it)
00118 {
00119 Object const *object = *it;
00120 ASSERT1(object != NULL);
00121 if (!object->IsDynamic())
00122 {
00123 object->Write(serializer);
00124 ++retval;
00125 }
00126 }
00127
00128
00129 if (HasChildren())
00130 {
00131 for (Uint8 i = 0; i < 4; ++i)
00132 {
00133 ASSERT1(m_child[i]->Parent() == this);
00134 retval += Child<VisibilityQuadTree>(i)->WriteObjects(serializer);
00135 }
00136 }
00137
00138 return retval;
00139 }
00140
00141 Uint32 Engine2::VisibilityQuadTree::Draw (
00142 RenderContext const &render_context,
00143 FloatMatrix2 const &world_to_screen,
00144 Float const pixels_in_view_radius,
00145 FloatVector2 const &view_center,
00146 Float const view_radius,
00147 TransparentObjectVector *const transparent_object_vector)
00148 {
00149 ASSERT1(transparent_object_vector != NULL);
00150 ASSERT1(m_parent == NULL);
00151
00152
00153 transparent_object_vector->clear();
00154 Object::DrawLoopFunctor
00155 draw_loop_functor(
00156 render_context,
00157 world_to_screen,
00158 pixels_in_view_radius,
00159 view_center,
00160 view_radius,
00161 true,
00162 transparent_object_vector,
00163 GetQuadTreeType());
00164
00165
00166 {
00167 glEnable(GL_DEPTH_TEST);
00168 glDepthMask(GL_TRUE);
00169 glClearDepth(1.0f);
00170 glClear(GL_DEPTH_BUFFER_BIT);
00171
00172
00173
00174
00175
00176
00177 Draw(draw_loop_functor);
00178 }
00179
00180
00181 {
00182 glDisable(GL_DEPTH_TEST);
00183 glDepthMask(GL_FALSE);
00184
00185
00186 if (!transparent_object_vector->empty())
00187 std::sort(
00188 &(*transparent_object_vector)[0],
00189 &(*transparent_object_vector)[0]+transparent_object_vector->size(),
00190 Object::TransparentObjectOrder());
00191
00192 draw_loop_functor.SetIsCollectTransparentObjectPass(false);
00193 std::for_each(
00194 draw_loop_functor.GetTransparentObjectVector()->begin(),
00195 draw_loop_functor.GetTransparentObjectVector()->end(),
00196 draw_loop_functor);
00197 }
00198
00199 return draw_loop_functor.DrawnOpaqueObjectCount();
00200 }
00201
00202 Uint32 Engine2::VisibilityQuadTree::DrawWrapped (
00203 RenderContext const &render_context,
00204 FloatMatrix2 const &world_to_screen,
00205 Float const pixels_in_view_radius,
00206 FloatVector2 const &view_center,
00207 Float const view_radius,
00208 TransparentObjectVector *const transparent_object_vector)
00209 {
00210 ASSERT1(transparent_object_vector != NULL);
00211 ASSERT1(m_parent == NULL);
00212
00213
00214 transparent_object_vector->clear();
00215 Object::DrawLoopFunctor
00216 draw_loop_functor(
00217 render_context,
00218 world_to_screen,
00219 pixels_in_view_radius,
00220 view_center,
00221 view_radius,
00222 true,
00223 transparent_object_vector,
00224 GetQuadTreeType());
00225
00226
00227 {
00228 glEnable(GL_DEPTH_TEST);
00229 glDepthMask(GL_TRUE);
00230 glClearDepth(1.0f);
00231 glClear(GL_DEPTH_BUFFER_BIT);
00232
00233
00234
00235
00236
00237
00238 DrawWrapped(draw_loop_functor);
00239 }
00240
00241
00242 {
00243 glDisable(GL_DEPTH_TEST);
00244 glDepthMask(GL_FALSE);
00245
00246
00247 if (!transparent_object_vector->empty())
00248 {
00249 std::sort(
00250 &(*transparent_object_vector)[0],
00251 &(*transparent_object_vector)[0]+transparent_object_vector->size(),
00252 Object::TransparentObjectOrder());
00253
00254
00255 Uint32 write = 0;
00256 Uint32 read = 0;
00257 Uint32 size = transparent_object_vector->size();
00258 while (read < size)
00259 {
00260 Object const *skip_object = (*transparent_object_vector)[read];
00261 (*transparent_object_vector)[write] = skip_object;
00262 ++write;
00263 ++read;
00264 while (read < size && (*transparent_object_vector)[read] == skip_object)
00265 ++read;
00266 }
00267 transparent_object_vector->resize(write);
00268 }
00269
00270 draw_loop_functor.SetIsCollectTransparentObjectPass(false);
00271 DrawWrapped(draw_loop_functor);
00272 }
00273
00274 return draw_loop_functor.DrawnOpaqueObjectCount();
00275 }
00276
00277 void Engine2::VisibilityQuadTree::DrawBounds (
00278 RenderContext const &render_context,
00279 Color const &color)
00280 {
00281 Float r_o2 = m_radius * 0.5f * Math::Sqrt(2.0f);
00282 FloatVector2 upper_right( r_o2, r_o2);
00283 FloatVector2 upper_left (-r_o2, r_o2);
00284 FloatVector2 lower_left (-r_o2, -r_o2);
00285 FloatVector2 lower_right( r_o2, -r_o2);
00286 upper_right += m_center;
00287 upper_left += m_center;
00288 lower_left += m_center;
00289 lower_right += m_center;
00290 Render::DrawLine(render_context, upper_right, upper_left, color);
00291 Render::DrawLine(render_context, upper_left, lower_left, color);
00292 Render::DrawLine(render_context, lower_left, lower_right, color);
00293 Render::DrawLine(render_context, lower_right, upper_right, color);
00294 }
00295
00296 void Engine2::VisibilityQuadTree::DrawTreeBounds (
00297 RenderContext const &render_context,
00298 Color const &color)
00299 {
00300 if (!m_parent)
00301 DrawBounds(render_context, color);
00302
00303 Float r_o2 = m_radius * 0.5f * Math::Sqrt(2.0f);
00304 FloatVector2 top ( 0.0, r_o2);
00305 FloatVector2 bottom( 0.0, -r_o2);
00306 FloatVector2 left (-r_o2, 0.0);
00307 FloatVector2 right ( r_o2, 0.0);
00308 top += m_center;
00309 bottom += m_center;
00310 left += m_center;
00311 right += m_center;
00312
00313 Render::DrawLine(render_context, top, bottom, color);
00314 Render::DrawLine(render_context, left, right, color);
00315
00316 if (HasChildren())
00317 for (Uint8 i = 0; i < 4; ++i)
00318 Child<VisibilityQuadTree>(i)->DrawTreeBounds(render_context, color);
00319 }
00320
00321 void Engine2::VisibilityQuadTree::Draw (
00322 Engine2::Object::DrawLoopFunctor const &draw_loop_functor)
00323 {
00324
00325 if (SubordinateObjectCount() == 0)
00326 return;
00327
00328 ASSERT2(draw_loop_functor.PixelsInViewRadius() > 0.0f);
00329 ASSERT2(draw_loop_functor.ViewRadius() > 0.0f);
00330
00331
00332
00333
00334
00335 if (draw_loop_functor.PixelsInViewRadius() * Radius()
00336 <
00337 draw_loop_functor.ViewRadius() * Object::DrawLoopFunctor::ms_radius_limit_lower)
00338 {
00339 return;
00340 }
00341
00342
00343 if (!DoesAreaOverlapQuadBounds(draw_loop_functor.ViewCenter(), draw_loop_functor.ViewRadius()))
00344 return;
00345
00346
00347
00348 std::for_each(m_object_set.begin(), m_object_set.end(), draw_loop_functor);
00349
00350
00351 if (HasChildren())
00352 for (Uint8 i = 0; i < 4; ++i)
00353 Child<VisibilityQuadTree>(i)->Draw(draw_loop_functor);
00354 }
00355
00356 void Engine2::VisibilityQuadTree::DrawWrapped (
00357 Engine2::Object::DrawLoopFunctor draw_loop_functor)
00358 {
00359
00360 if (SubordinateObjectCount() == 0)
00361 return;
00362
00363 ASSERT1(Parent() == NULL);
00364 ASSERT2(draw_loop_functor.PixelsInViewRadius() > 0.0f);
00365 ASSERT2(draw_loop_functor.ViewRadius() > 0.0f);
00366 ASSERT2(m_half_side_length > 0.0f);
00367
00368 Float side_length = SideLength();
00369 Float radius_sum = 2.0f*Radius() + draw_loop_functor.ViewRadius();
00370 Float top = floor((draw_loop_functor.ViewCenter().m[1]+radius_sum)/side_length);
00371 Float bottom = ceil((draw_loop_functor.ViewCenter().m[1]-radius_sum)/side_length);
00372 Float left = ceil((draw_loop_functor.ViewCenter().m[0]-radius_sum)/side_length);
00373 Float right = floor((draw_loop_functor.ViewCenter().m[0]+radius_sum)/side_length);
00374 FloatVector2 old_view_center(draw_loop_functor.ViewCenter());
00375 FloatVector2 view_offset;
00376
00377 glMatrixMode(GL_MODELVIEW);
00378
00379 for (Float x = left; x <= right; x += 1.0f)
00380 {
00381 for (Float y = bottom; y <= top; y += 1.0f)
00382 {
00383 view_offset.SetComponents(side_length*x, side_length*y);
00384
00385
00386 if ((old_view_center - view_offset).LengthSquared() < radius_sum*radius_sum)
00387 {
00388 draw_loop_functor.SetViewCenter(old_view_center - view_offset);
00389
00390 glLoadIdentity();
00391 glTranslatef(
00392 view_offset[Dim::X],
00393 view_offset[Dim::Y],
00394 0.0f);
00395
00396 if (draw_loop_functor.IsCollectTransparentObjectPass())
00397 Draw(draw_loop_functor);
00398 else
00399 std::for_each(
00400 draw_loop_functor.GetTransparentObjectVector()->begin(),
00401 draw_loop_functor.GetTransparentObjectVector()->end(),
00402 draw_loop_functor);
00403 }
00404 }
00405 }
00406 }
00407
00408 }