00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "xrb_engine2_object.hpp"
00012
00013 #include "xrb_engine2_compound.hpp"
00014 #include "xrb_engine2_entity.hpp"
00015 #include "xrb_engine2_objectlayer.hpp"
00016 #include "xrb_engine2_sprite.hpp"
00017 #include "xrb_rendercontext.hpp"
00018 #include "xrb_serializer.hpp"
00019
00020 namespace Xrb
00021 {
00022
00023
00024
00025
00026
00027
00028
00029 Float const Engine2::Object::DrawLoopFunctor::ms_radius_limit_upper = 1.0f;
00030 Float const Engine2::Object::DrawLoopFunctor::ms_radius_limit_lower = 0.5f;
00031 Float const Engine2::Object::DrawLoopFunctor::ms_distance_fade_slope =
00032 1.0f /
00033 (Engine2::Object::DrawLoopFunctor::ms_radius_limit_upper - Engine2::Object::DrawLoopFunctor::ms_radius_limit_lower);
00034 Float const Engine2::Object::DrawLoopFunctor::ms_distance_fade_intercept =
00035 Engine2::Object::DrawLoopFunctor::ms_radius_limit_lower /
00036 (Engine2::Object::DrawLoopFunctor::ms_radius_limit_lower - Engine2::Object::DrawLoopFunctor::ms_radius_limit_upper);
00037
00038 Engine2::Object::DrawLoopFunctor::DrawLoopFunctor (
00039 RenderContext const &render_context,
00040 FloatMatrix2 const &world_to_screen,
00041 Float const pixels_in_view_radius,
00042 FloatVector2 const &view_center,
00043 Float const view_radius,
00044 bool const is_collect_transparent_object_pass,
00045 TransparentObjectVector *const transparent_object_vector,
00046 QuadTreeType const quad_tree_type)
00047 :
00048 m_object_draw_data(render_context, world_to_screen),
00049 m_transparent_object_vector(transparent_object_vector)
00050 {
00051 m_pixels_in_view_radius = pixels_in_view_radius;
00052 m_view_center = view_center;
00053 m_view_radius = view_radius;
00054 m_is_collect_transparent_object_pass = is_collect_transparent_object_pass;
00055 m_quad_tree_type = quad_tree_type;
00056 m_drawn_opaque_object_count = 0;
00057 m_drawn_transparent_object_count = 0;
00058 }
00059
00060 void Engine2::Object::DrawLoopFunctor::operator () (Engine2::Object const *object)
00061 {
00062 ASSERT3(m_transparent_object_vector != NULL);
00063
00064
00065 Float object_radius = m_pixels_in_view_radius * object->Radius(m_quad_tree_type) / m_view_radius;
00066
00067
00068 if (object_radius >= ms_radius_limit_lower)
00069 {
00070 Float distance_fade;
00071 if (m_is_collect_transparent_object_pass)
00072 {
00073 ASSERT3(m_object_draw_data.GetRenderContext().ColorMask()[Dim::A] <= 1.0f);
00074 ASSERT3(object->ColorMask()[Dim::A] <= 1.0f);
00075
00076
00077 if (object->IsTransparent() ||
00078 object->ColorMask()[Dim::A] < 1.0f ||
00079 (distance_fade = CalculateDistanceFade(object_radius)) < 1.0f ||
00080 m_object_draw_data.GetRenderContext().ColorMask()[Dim::A] < 1.0f)
00081 {
00082 m_transparent_object_vector->push_back(object);
00083
00084 return;
00085 }
00086 }
00087 else
00088 distance_fade = CalculateDistanceFade(object_radius);
00089
00090
00091 object->Draw(m_object_draw_data, distance_fade);
00092
00093 if (m_is_collect_transparent_object_pass)
00094 ++m_drawn_opaque_object_count;
00095 else
00096 ++m_drawn_transparent_object_count;
00097 }
00098 }
00099
00100 Float Engine2::Object::DrawLoopFunctor::CalculateDistanceFade (Float const object_radius)
00101 {
00102
00103
00104
00105
00106
00107
00108 Float distance_fade =
00109 (object_radius > ms_radius_limit_upper) ?
00110 1.0f :
00111 (ms_distance_fade_slope * object_radius + ms_distance_fade_intercept);
00112 ASSERT1(distance_fade <= 1.0f);
00113 return distance_fade;
00114 }
00115
00116
00117
00118
00119
00120 Engine2::Object::~Object ()
00121 {
00122 if (m_entity != NULL)
00123 {
00124 ASSERT1(m_entity->m_owner_object == this);
00125 ASSERT1(!m_entity->IsInWorld());
00126 m_entity->m_owner_object = NULL;
00127 Delete(m_entity);
00128 }
00129 }
00130
00131 Engine2::Object *Engine2::Object::Create (
00132 Serializer &serializer,
00133 CreateEntityFunction CreateEntity)
00134 {
00135 ASSERT1(serializer.GetIODirection() == IOD_READ);
00136
00137 Object *retval = NULL;
00138 switch (ReadObjectType(serializer))
00139 {
00140 case OT_OBJECT:
00141 retval = new Object(OT_OBJECT);
00142 retval->Object::ReadClassSpecific(serializer);
00143 break;
00144
00145 case OT_SPRITE:
00146 retval = Sprite::Create(serializer);
00147 break;
00148
00149 case OT_COMPOUND:
00150 retval = Compound::Create(serializer);
00151 break;
00152
00153 default:
00154 ASSERT0(false && "Invalid object type");
00155 retval = NULL;
00156 break;
00157 }
00158
00159
00160 if (serializer.ReadBool())
00161 {
00162 ASSERT1(CreateEntity != NULL);
00163 retval->m_entity = CreateEntity(serializer);
00164 ASSERT1(retval->m_entity != NULL);
00165 }
00166
00167 return retval;
00168 }
00169
00170 void Engine2::Object::Write (Serializer &serializer) const
00171 {
00172 WriteObjectType(serializer);
00173
00174 Object::WriteClassSpecific(serializer);
00175
00176
00177 serializer.WriteBool(m_entity != NULL);
00178
00179 if (m_entity != NULL)
00180 m_entity->Write(serializer);
00181 }
00182
00183 Engine2::World *Engine2::Object::GetWorld () const
00184 {
00185 ASSERT1(m_object_layer != NULL);
00186 ASSERT1(m_object_layer->OwnerWorld() != NULL);
00187 return m_object_layer->OwnerWorld();
00188 }
00189
00190 void Engine2::Object::SetEntity (Entity *const entity)
00191 {
00192 if (m_entity != NULL)
00193 {
00194 ASSERT1(m_entity->m_owner_object == this);
00195 m_entity->m_owner_object = NULL;
00196 }
00197
00198 m_entity = entity;
00199
00200 if (m_entity != NULL)
00201 {
00202 m_entity->m_owner_object = this;
00203 m_entity->HandleNewOwnerObject();
00204 }
00205 }
00206
00207 Engine2::Object::Object (ObjectType object_type)
00208 :
00209 FloatTransform2(FloatTransform2::ms_identity, true),
00210 m_object_type(object_type),
00211 m_color_bias(Color::ms_identity_color_bias),
00212 m_color_mask(Color::ms_identity_color_mask)
00213 {
00214 ASSERT1(m_object_type < OT_COUNT);
00215 m_z_depth = 0.0f;
00216 m_object_layer = NULL;
00217 for (Uint32 i = 0; i < QTT_COUNT; ++i)
00218 {
00219 m_radius[i] = 0.0f;
00220 m_owner_quad_tree[i] = NULL;
00221 }
00222 m_entity = NULL;
00223 m_is_transparent = false;
00224 m_radii_need_to_be_recalculated = true;
00225 }
00226
00227 Engine2::ObjectType Engine2::Object::ReadObjectType (Serializer &serializer)
00228 {
00229 return static_cast<ObjectType>(serializer.ReadUint8());
00230 }
00231
00232 void Engine2::Object::WriteObjectType (Serializer &serializer) const
00233 {
00234 serializer.WriteUint8(static_cast<Uint8>(m_object_type));
00235 }
00236
00237 void Engine2::Object::ReadClassSpecific (Serializer &serializer)
00238 {
00239 serializer.ReadFloatTransform2(this);
00240 serializer.ReadColor(&m_color_bias);
00241 serializer.ReadColor(&m_color_mask);
00242 }
00243
00244 void Engine2::Object::WriteClassSpecific (Serializer &serializer) const
00245 {
00246 serializer.WriteFloatTransform2(*static_cast<FloatTransform2 const *>(this));
00247 serializer.WriteColor(m_color_bias);
00248 serializer.WriteColor(m_color_mask);
00249 }
00250
00251 void Engine2::Object::CloneProperties (Object const *const object)
00252 {
00253 ASSERT1(object != NULL);
00254
00255 SetTranslation(object->Translation());
00256 SetScaleFactors(object->ScaleFactors());
00257 SetAngle(object->Angle());
00258 m_color_bias = object->m_color_bias;
00259 m_color_mask = object->m_color_mask;
00260 }
00261
00262 void Engine2::Object::CalculateTransform () const
00263 {
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278 if (IsDirty())
00279 {
00280 if (ScalingAndRotationIsDirty())
00281 {
00282 RecalculateTransform();
00283
00284 for (Uint32 i = 0; i < QTT_COUNT; ++i)
00285 CalculateRadius(static_cast<QuadTreeType>(i));
00286 m_radii_need_to_be_recalculated = false;
00287 }
00288 else if (m_radii_need_to_be_recalculated)
00289 {
00290 RecalculateTransformWithoutScalingAndRotation();
00291
00292 for (Uint32 i = 0; i < QTT_COUNT; ++i)
00293 CalculateRadius(static_cast<QuadTreeType>(i));
00294 m_radii_need_to_be_recalculated = false;
00295 }
00296 else
00297 RecalculateTransformWithoutScalingAndRotation();
00298 }
00299 else if (m_radii_need_to_be_recalculated)
00300 {
00301
00302 for (Uint32 i = 0; i < QTT_COUNT; ++i)
00303 CalculateRadius(static_cast<QuadTreeType>(i));
00304 m_radii_need_to_be_recalculated = false;
00305 }
00306 }
00307
00308 }