00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "xrb_engine2_objectlayer.hpp"
00012
00013 #include "xrb_engine2_entity.hpp"
00014 #include "xrb_engine2_visibilityquadtree.hpp"
00015 #include "xrb_rendercontext.hpp"
00016 #include "xrb_serializer.hpp"
00017
00018 namespace Xrb
00019 {
00020
00021 Engine2::ObjectLayer::~ObjectLayer ()
00022 {
00023 Delete(m_quad_tree);
00024 }
00025
00026 Engine2::ObjectLayer *Engine2::ObjectLayer::Create (
00027 Engine2::World *const owner_world,
00028 bool const is_wrapped,
00029 Float const side_length,
00030 Uint32 const tree_depth,
00031 Float const z_depth)
00032 {
00033 ASSERT1(owner_world != NULL);
00034 ASSERT1(side_length > 0.0);
00035 ASSERT1(tree_depth > 0);
00036
00037 ObjectLayer *retval =
00038 new ObjectLayer(
00039 owner_world,
00040 is_wrapped,
00041 side_length,
00042 z_depth);
00043
00044 retval->m_quad_tree =
00045 new VisibilityQuadTree(
00046 FloatVector2::ms_zero,
00047 0.5f*side_length,
00048 tree_depth);
00049
00050 return retval;
00051 }
00052
00053 Engine2::ObjectLayer *Engine2::ObjectLayer::Create (
00054 Serializer &serializer,
00055 Engine2::World *const owner_world)
00056 {
00057 ASSERT1(owner_world != NULL);
00058
00059 Float side_length;
00060 Float z_depth;
00061 serializer.ReadFloat(&side_length);
00062 serializer.ReadFloat(&z_depth);
00063 bool is_wrapped = serializer.ReadBool();
00064 ObjectLayer *retval =
00065 new ObjectLayer(
00066 owner_world,
00067 is_wrapped,
00068 side_length,
00069 z_depth);
00070
00071
00072 retval->m_quad_tree = VisibilityQuadTree::Create(serializer);
00073
00074 retval->m_quad_tree->ReadObjects(serializer, retval);
00075
00076 return retval;
00077 }
00078
00079 Engine2::Object *Engine2::ObjectLayer::SmallestObjectTouchingPoint (
00080 FloatVector2 const &point) const
00081 {
00082 return m_quad_tree->SmallestObjectTouchingPoint(point);
00083 }
00084
00085 bool Engine2::ObjectLayer::DoesAreaOverlapAnyObject (
00086 FloatVector2 const &area_center,
00087 Float const area_radius) const
00088 {
00089 ASSERT1(m_quad_tree != NULL);
00090 if (IsWrapped())
00091 return m_quad_tree->DoesAreaOverlapAnyObjectWrapped(
00092 area_center,
00093 area_radius,
00094 SideLength(),
00095 0.5f * SideLength());
00096 else
00097 return m_quad_tree->DoesAreaOverlapAnyObject(area_center, area_radius);
00098 }
00099
00100 FloatVector2 Engine2::ObjectLayer::NormalizedCoordinates (
00101 FloatVector2 const &coordinates) const
00102 {
00103 FloatVector2 normalized_coordinates(coordinates);
00104
00105 Float const half_object_layer_side_length = 0.5f * SideLength();
00106 if (IsWrapped())
00107 {
00108 while (normalized_coordinates[Dim::X] < -half_object_layer_side_length)
00109 normalized_coordinates[Dim::X] += SideLength();
00110 while (normalized_coordinates[Dim::X] > half_object_layer_side_length)
00111 normalized_coordinates[Dim::X] -= SideLength();
00112
00113 while (normalized_coordinates[Dim::Y] < -half_object_layer_side_length)
00114 normalized_coordinates[Dim::Y] += SideLength();
00115 while (normalized_coordinates[Dim::Y] > half_object_layer_side_length)
00116 normalized_coordinates[Dim::Y] -= SideLength();
00117 }
00118 else
00119 {
00120 if (normalized_coordinates[Dim::X] < -half_object_layer_side_length)
00121 normalized_coordinates[Dim::X] = -half_object_layer_side_length;
00122 else if (normalized_coordinates[Dim::X] > half_object_layer_side_length)
00123 normalized_coordinates[Dim::X] = half_object_layer_side_length;
00124
00125 if (normalized_coordinates[Dim::Y] < -half_object_layer_side_length)
00126 normalized_coordinates[Dim::Y] = -half_object_layer_side_length;
00127 else if (normalized_coordinates[Dim::Y] > half_object_layer_side_length)
00128 normalized_coordinates[Dim::Y] = half_object_layer_side_length;
00129 }
00130
00131 return normalized_coordinates;
00132 }
00133
00134 FloatVector2 Engine2::ObjectLayer::AdjustedCoordinates (
00135 FloatVector2 const &coordinates,
00136 FloatVector2 const &reference_coordinates) const
00137 {
00138 ASSERT_NAN_SANITY_CHECK(Math::IsFinite(coordinates[Dim::X]));
00139 ASSERT_NAN_SANITY_CHECK(Math::IsFinite(coordinates[Dim::Y]));
00140 ASSERT_NAN_SANITY_CHECK(Math::IsFinite(reference_coordinates[Dim::X]));
00141 ASSERT_NAN_SANITY_CHECK(Math::IsFinite(reference_coordinates[Dim::Y]));
00142
00143 if (IsWrapped())
00144 {
00145 Float const half_object_layer_side_length = 0.5f * SideLength();
00146 FloatVector2 adjusted_coordinates(coordinates);
00147
00148 ASSERT1(reference_coordinates[Dim::X] >= -half_object_layer_side_length);
00149 ASSERT1(reference_coordinates[Dim::X] <= half_object_layer_side_length);
00150 ASSERT1(reference_coordinates[Dim::X] >= -half_object_layer_side_length);
00151 ASSERT1(reference_coordinates[Dim::Y] <= half_object_layer_side_length);
00152
00153 while (adjusted_coordinates[Dim::X] < reference_coordinates[Dim::X] - half_object_layer_side_length)
00154 adjusted_coordinates[Dim::X] += SideLength();
00155 ASSERT1(adjusted_coordinates[Dim::X] >= reference_coordinates[Dim::X] - half_object_layer_side_length);
00156
00157 while (adjusted_coordinates[Dim::X] > reference_coordinates[Dim::X] + half_object_layer_side_length)
00158 adjusted_coordinates[Dim::X] -= SideLength();
00159 ASSERT1(adjusted_coordinates[Dim::X] <= reference_coordinates[Dim::X] + half_object_layer_side_length);
00160
00161 while (adjusted_coordinates[Dim::Y] < reference_coordinates[Dim::Y] - half_object_layer_side_length)
00162 adjusted_coordinates[Dim::Y] += SideLength();
00163 ASSERT1(adjusted_coordinates[Dim::Y] >= reference_coordinates[Dim::Y] - half_object_layer_side_length);
00164
00165 while (adjusted_coordinates[Dim::Y] > reference_coordinates[Dim::Y] + half_object_layer_side_length)
00166 adjusted_coordinates[Dim::Y] -= SideLength();
00167 ASSERT1(adjusted_coordinates[Dim::Y] <= reference_coordinates[Dim::Y] + half_object_layer_side_length);
00168
00169 return adjusted_coordinates;
00170 }
00171 else
00172 return coordinates;
00173 }
00174
00175 void Engine2::ObjectLayer::Write (Serializer &serializer) const
00176 {
00177
00178 serializer.WriteFloat(m_side_length);
00179 serializer.WriteFloat(m_z_depth);
00180 serializer.WriteBool(m_is_wrapped);
00181
00182 ASSERT1(m_quad_tree != NULL);
00183
00184 m_quad_tree->WriteStructure(serializer);
00185
00186 DEBUG1_CODE(Uint32 written_static_object_count =)
00187 m_quad_tree->WriteObjects(serializer);
00188 ASSERT1(written_static_object_count == m_quad_tree->SubordinateStaticObjectCount());
00189 }
00190
00191 Uint32 Engine2::ObjectLayer::Draw (
00192 RenderContext const &render_context,
00193 FloatMatrix2 const &world_to_screen,
00194 Float const pixels_in_view_radius,
00195 FloatVector2 const &view_center,
00196 Float const &view_radius,
00197 TransparentObjectVector *const transparent_object_vector)
00198 {
00199 ASSERT2(view_radius > 0.0);
00200
00201 if (m_is_wrapped)
00202 return m_quad_tree->DrawWrapped(
00203 render_context,
00204 world_to_screen,
00205 pixels_in_view_radius,
00206 view_center,
00207 view_radius,
00208 transparent_object_vector);
00209 else
00210 return m_quad_tree->Draw(
00211 render_context,
00212 world_to_screen,
00213 pixels_in_view_radius,
00214 view_center,
00215 view_radius,
00216 transparent_object_vector);
00217 }
00218
00219 void Engine2::ObjectLayer::AddObject (Engine2::Object *const object)
00220 {
00221 ASSERT1(object != NULL);
00222 ASSERT1(m_quad_tree != NULL);
00223 ASSERT1(object->OwnerQuadTree(QTT_VISIBILITY) == NULL);
00224
00225
00226 object->SetObjectLayer(this);
00227
00228 HandleContainmentOrWrapping(object);
00229
00230 DEBUG1_CODE(bool add_success =)
00231 m_quad_tree->AddObject(object);
00232 ASSERT1(add_success);
00233
00234 ASSERT1(object->OwnerQuadTree(QTT_VISIBILITY) != NULL);
00235 }
00236
00237 void Engine2::ObjectLayer::RemoveObject (Engine2::Object *const object)
00238 {
00239 ASSERT1(object != NULL);
00240 ASSERT1(object->GetObjectLayer() == this);
00241 ASSERT1(object->OwnerQuadTree(QTT_VISIBILITY) != NULL);
00242 object->OwnerQuadTree(QTT_VISIBILITY)->RemoveObject(object);
00243 }
00244
00245 void Engine2::ObjectLayer::HandleContainmentOrWrapping (Object *object)
00246 {
00247 ASSERT1(object != NULL);
00248 ASSERT1(m_quad_tree != NULL);
00249
00250
00251 Entity *entity = object->GetEntity();
00252 if (m_is_wrapped)
00253 {
00254 if (entity != NULL)
00255 WrapEntity(entity);
00256 else
00257 WrapTransform2(object);
00258 }
00259 else
00260 {
00261 if (entity != NULL)
00262 ContainEntity(entity);
00263 else
00264 ContainTransform2(object);
00265 }
00266 }
00267
00268 void Engine2::ObjectLayer::ContainVector2 (FloatVector2 *const vector) const
00269 {
00270 ASSERT1(vector != NULL);
00271
00272 for (Uint32 i = 0; i <= 1; ++i)
00273 {
00274 if (vector->m[i] > m_half_side_length)
00275 vector->m[i] = m_half_side_length;
00276 else if (vector->m[i] < -m_half_side_length)
00277 vector->m[i] = -m_half_side_length;
00278 }
00279 }
00280
00281 void Engine2::ObjectLayer::ContainTransform2 (FloatTransform2 *const transform) const
00282 {
00283 ASSERT1(transform != NULL);
00284 ASSERT1(!IsWrapped());
00285
00286 FloatVector2 translation(transform->Translation());
00287 ContainVector2(&translation);
00288 transform->SetTranslation(translation);
00289 }
00290
00291 void Engine2::ObjectLayer::ContainEntity (Engine2::Entity *const entity) const
00292 {
00293 ASSERT1(entity != NULL);
00294 ASSERT1(!IsWrapped());
00295
00296 FloatVector2 translation(entity->Translation());
00297 bool component_x = false;
00298 bool component_y = false;
00299
00300 if (translation[Dim::X] > m_half_side_length)
00301 {
00302 translation[Dim::X] = m_half_side_length;
00303 component_x = true;
00304 }
00305 else if (translation[Dim::X] < -m_half_side_length)
00306 {
00307 translation[Dim::X] = -m_half_side_length;
00308 component_x = true;
00309 }
00310
00311 if (translation[Dim::Y] > m_half_side_length)
00312 {
00313 translation[Dim::Y] = m_half_side_length;
00314 component_y = true;
00315 }
00316 else if (translation[Dim::Y] < -m_half_side_length)
00317 {
00318 translation[Dim::Y] = -m_half_side_length;
00319 component_y = true;
00320 }
00321
00322 ASSERT1(entity->OwnerObject() != NULL);
00323 entity->OwnerObject()->SetTranslation(translation);
00324 entity->HandleObjectLayerContainment(component_x, component_y);
00325 }
00326
00327 void Engine2::ObjectLayer::WrapVector2 (FloatVector2 *const vector) const
00328 {
00329 ASSERT1(vector != NULL);
00330
00331 for (Uint32 i = 0; i <= 1; ++i)
00332 {
00333 if (vector->m[i] > m_half_side_length)
00334 vector->m[i] -= m_side_length *
00335 (int)((vector->m[i] + m_half_side_length) /
00336 m_side_length);
00337
00338 if (vector->m[i] < -m_half_side_length)
00339 vector->m[i] -= m_side_length *
00340 (int)((vector->m[i] - m_half_side_length) /
00341 m_side_length);
00342 }
00343 }
00344
00345 void Engine2::ObjectLayer::WrapTransform2 (FloatTransform2 *const transform) const
00346 {
00347 ASSERT1(transform != NULL);
00348 ASSERT1(IsWrapped());
00349
00350 FloatVector2 translation(transform->Translation());
00351 WrapVector2(&translation);
00352 transform->SetTranslation(translation);
00353 }
00354
00355 void Engine2::ObjectLayer::WrapEntity (Entity *const entity) const
00356 {
00357 ASSERT1(entity != NULL);
00358 ASSERT1(IsWrapped());
00359
00360 FloatVector2 previous_translation(entity->Translation());
00361 WrapTransform2(entity->OwnerObject());
00362 entity->AccumulateWrappedOffset(previous_translation - entity->Translation());
00363 }
00364
00365 Engine2::ObjectLayer::ObjectLayer (
00366 Engine2::World *const owner_world,
00367 bool const is_wrapped,
00368 Float const side_length,
00369 Float const z_depth)
00370 {
00371 ASSERT1(owner_world != NULL);
00372 ASSERT1(side_length > 0.0f);
00373 ASSERT1(z_depth >= 0.0f);
00374
00375 m_owner_world = owner_world;
00376 m_is_wrapped = is_wrapped;
00377 m_side_length = side_length;
00378 m_half_side_length = 0.5f * side_length;
00379 m_z_depth = z_depth;
00380 m_quad_tree = NULL;
00381 }
00382
00383 }