commit x64 compilation from lulu cause the other branch dont seems to compile properly at home
This commit is contained in:
494
include/engine/scene3d/scene.cpp
Normal file
494
include/engine/scene3d/scene.cpp
Normal file
@ -0,0 +1,494 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "scene3d/scene.h"
|
||||
#include "scene3d/mlight.h"
|
||||
#include "scene3d/mobject.h"
|
||||
#include "scene3d/mcamera.h"
|
||||
#include "scene3d/mtrigger.h"
|
||||
#include "scene3d/memitter.h"
|
||||
#include "scene3d/mterrain.h"
|
||||
#include "scene3d/instance.h"
|
||||
#include "scene3d/mconstraint.h"
|
||||
#include "scene3d/mitem_scripted_object.h"
|
||||
#include "scene3d/scene_event_script_interface.h"
|
||||
#include "scene3d/scene_renderer_environment_interface.h"
|
||||
#include "scene3d/scene_physic_world_interface.h"
|
||||
#include "scene3d/scene_scripted_object.h"
|
||||
#include "scene3d/scene_script_unit.h"
|
||||
#include "scene3d/mitem_event_script_interface.h"
|
||||
#include "physic/physic_constraint.h"
|
||||
#include "physic/physic_world.h"
|
||||
#include "ui/ui.h"
|
||||
|
||||
using namespace GS;
|
||||
using namespace S3D;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void Scene::SetClock(Core::Clock *c, bool set_ui)
|
||||
{
|
||||
clock = c ? c : new Core::Clock;
|
||||
if (set_ui)
|
||||
ui->SetClock(c);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void Scene::GetMinMax(MinMax &minmax) const
|
||||
{
|
||||
bool initial = true;
|
||||
|
||||
ArrayListForeachPtr(MItem *, i, active_list)
|
||||
{
|
||||
if (i->GetItemType() != Type_Object)
|
||||
continue;
|
||||
|
||||
MObject *object = (MObject *)i;
|
||||
if (object->render_data.IsNull() || object->render_data->geometry.IsNull())
|
||||
continue;
|
||||
|
||||
MinMax local_minmax = object->render_data->geometry->minmax;
|
||||
|
||||
if (initial)
|
||||
minmax = local_minmax;
|
||||
else minmax.Grow(local_minmax);
|
||||
initial = false;
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
Group *Scene::AddGroup(Group *g)
|
||||
{
|
||||
group_list.Add(g);
|
||||
return g;
|
||||
}
|
||||
bool Scene::RemoveGroup(Group *g)
|
||||
{
|
||||
return group_list.Remove(g);
|
||||
}
|
||||
Group *Scene::FindGroup(const char *name) const
|
||||
{
|
||||
ListForeachPtr(Group *, g, group_list)
|
||||
if (g->name == name)
|
||||
return g;
|
||||
return NULL;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
uint Scene::GetItemGroupList(const MItem *item, SharedList <Group *> &list) const
|
||||
{
|
||||
uint count = 0;
|
||||
ListForeachPtr(Group *, g, group_list)
|
||||
if (g->IsMember(item))
|
||||
{
|
||||
count++;
|
||||
list.Add(g);
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
void Scene::UnregisterItemFromGroups(MItem *item) const
|
||||
{
|
||||
ListForeachPtr(Group *, g, group_list)
|
||||
g->Remove(item);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool Scene::ActivateItem(MItem *i, bool v)
|
||||
{
|
||||
if (v)
|
||||
{
|
||||
if (active_list.IndexOf(i) == -1)
|
||||
active_list.Add(i);
|
||||
}
|
||||
else
|
||||
active_list.Remove(i);
|
||||
|
||||
if (i->physic_item)
|
||||
i->physic_item->SetActive(v);
|
||||
|
||||
i->mitem_flags.Raise(MItem::Flag_IsActive, v);
|
||||
return true;
|
||||
}
|
||||
void Scene::ProcessItemActivationQueue()
|
||||
{
|
||||
ListForeachPtr(MItem *, i, activation_queue)
|
||||
ActivateItem(i, true);
|
||||
ListForeachPtr(MItem *, i, deactivation_queue)
|
||||
ActivateItem(i, false);
|
||||
|
||||
activation_queue.Clear();
|
||||
deactivation_queue.Clear();
|
||||
}
|
||||
void Scene::QueueItemActivation(MItem *item, bool activate, bool propagate)
|
||||
{
|
||||
if (item->mitem_flags.IsSet(MItem::Flag_IsActive) != activate)
|
||||
{
|
||||
// Queue item.
|
||||
if (activate)
|
||||
{
|
||||
if (!activation_queue.Find(item))
|
||||
activation_queue.Add(item);
|
||||
deactivation_queue.Remove(item);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!deactivation_queue.Find(item))
|
||||
deactivation_queue.Add(item);
|
||||
activation_queue.Remove(item);
|
||||
}
|
||||
|
||||
// Script callback.
|
||||
item->item_event->OnActivate(item, activate);
|
||||
item->mitem_flags.Raise(MItem::Flag_IsActive, activate);
|
||||
}
|
||||
|
||||
if (propagate)
|
||||
ListForeachPtr(Core::Item *, child, item->GetBaseItem()->GetChildren())
|
||||
QueueItemActivation(LocateManagedItem(child), activate, true);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool Scene::Create(PhysicWorld *w)
|
||||
{
|
||||
Clear();
|
||||
|
||||
if ((physic_world = w) != NULL)
|
||||
{
|
||||
if (!physic_world->Create())
|
||||
return false;
|
||||
|
||||
// bullet_world->CreateDebugger(GetEngine().GetRenderer());
|
||||
physic_world->SetWorldInterface(iphysic_world);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
MTrigger *Scene::RaytraceTriggerList(Vector4 &s, Vector4 &d, float l, Vector4 *i)
|
||||
{
|
||||
ListForeachPtr(MItem *, item, item_list)
|
||||
if (item->GetItemType() == Type_Trigger)
|
||||
{
|
||||
MTrigger *t = (MTrigger *)item;
|
||||
|
||||
// Move ray to trigger space.
|
||||
Vector4 local_s, local_d;
|
||||
t->GetInverseMatrix().Apply(&local_s, &s);
|
||||
t->GetInverseMatrix().ApplyRotation(&local_d, &d);
|
||||
|
||||
// Test ray against bbox normalized space.
|
||||
MinMax mm;
|
||||
mm.SetFromPositionSize(Vector4(0, 0, 0), Vector4(1, 1, 1));
|
||||
|
||||
// Raytrace against minmax.
|
||||
Vector4 local_i;
|
||||
if (l == -1 ? mm.ClassifyLine(local_s, local_d, local_i) : mm.ClassifySegment(local_s, local_s + local_d * l, local_i))
|
||||
{
|
||||
if (i)
|
||||
*i = local_i * t->GetMatrix();
|
||||
return t;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void Scene::RecordAllItemLocation()
|
||||
{
|
||||
ListForeachPtr(MItem *, i, item_list)
|
||||
i->SetInitialTransformation();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
MItem *Scene::ItemFromUid(uint uid) const
|
||||
{
|
||||
ListForeachPtr(MItem *, i, item_list)
|
||||
if (i->GetUid() == uid)
|
||||
return i;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
MItemType Scene::LocateItem(const Core::Item *item, MItem **entity) const
|
||||
{
|
||||
ListForeachPtr(MItem *, i, item_list)
|
||||
if (i->GetBaseItem() == item)
|
||||
{
|
||||
if (entity)
|
||||
*entity = i;
|
||||
return i->GetItemType();
|
||||
}
|
||||
|
||||
return Type_None;
|
||||
}
|
||||
MItem *Scene::LocateManagedItem(Core::Item *i)
|
||||
{
|
||||
return i ? (MItem *)i->mitem : NULL;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
static bool FindItemByName(const MItem *i, const char *name) { return i->name == name; }
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
MItem *Scene::Item(const char *item_name, MItem *parent) const
|
||||
{
|
||||
StringList node;
|
||||
String(item_name).Split("/", node);
|
||||
|
||||
MItem *item = NULL;
|
||||
|
||||
if (parent)
|
||||
ListForeachPtr(Core::Item *, child, parent->GetBaseItem()->GetChildren())
|
||||
{
|
||||
MItem *child_item = LocateManagedItem(child);
|
||||
if (child_item && (child_item->name == node[0]))
|
||||
{
|
||||
item = child_item;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
item = ListFindEx(item_list, FindItemByName, node[0]);
|
||||
|
||||
if (!item)
|
||||
__ERR__(__LOG_W__ << "No item named '" << item_name << "' in scene '" << name << "'.\n", NULL)
|
||||
|
||||
// Solve additional path.
|
||||
if (node.GetCount() > 1)
|
||||
for (uint n = 1; n < node.GetCount(); ++n)
|
||||
{
|
||||
if (item->GetItemType() != Type_Instance)
|
||||
__ERR__(__LOG_W__ << "Cannot solve sub-path '" << node[n] << "' on item '" << item->name << "'.\n", NULL)
|
||||
|
||||
Instance *instance = (Instance *)item;
|
||||
if (!instance->instance_group)
|
||||
return NULL;
|
||||
|
||||
item = instance->instance_group->Item(node[n]);
|
||||
}
|
||||
|
||||
return item;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void Scene::SetItemStatic(MItem *item, bool v)
|
||||
{
|
||||
item->mitem_flags.Raise(MItem::Flag_IsStatic, v);
|
||||
|
||||
if (Core::Renderable *r = item->GetRenderable())
|
||||
{
|
||||
RemoveRenderable(r);
|
||||
AddRenderable(r, v);
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void Scene::AddRenderable(Core::Renderable *r, bool is_static)
|
||||
{
|
||||
if (is_static)
|
||||
octree_culling_system.AddRenderable(r);
|
||||
else simple_culling_system.AddRenderable(r);
|
||||
}
|
||||
void Scene::RemoveRenderable(Core::Renderable *r)
|
||||
{
|
||||
simple_culling_system.DeleteRenderable(r);
|
||||
octree_culling_system.DeleteRenderable(r);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void Scene::SetupItemComponents(MItem *i)
|
||||
{
|
||||
// Create scripted object and event handler.
|
||||
i->scripted_object = new MItemScriptedObject(i, vm);
|
||||
if (vm)
|
||||
i->item_event = new MItemScriptEvent;
|
||||
|
||||
// Create physic item.
|
||||
if (physic_world && i->GetBaseItem())
|
||||
{
|
||||
i->physic_item = physic_world->NewItem();
|
||||
i->physic_item->SetUserPointer((void *)i);
|
||||
}
|
||||
}
|
||||
void Scene::AddItem(MItem *i, bool setup_components)
|
||||
{
|
||||
i->uid = current_item_uid++;
|
||||
|
||||
if (setup_components)
|
||||
SetupItemComponents(i);
|
||||
|
||||
g_scene_messenger.BroadcastMessage(SceneMsg_AddingItem, this, i);
|
||||
|
||||
// Add to all lists.
|
||||
item_list.Add(i);
|
||||
active_list.Add(i);
|
||||
|
||||
switch (i->GetItemType())
|
||||
{
|
||||
case Type_Light: light_list.Add((MLight *)i); break;
|
||||
case Type_Trigger: trigger_list.Add((MTrigger *)i); break;
|
||||
}
|
||||
|
||||
// Add to culling systems.
|
||||
if (Core::Renderable *r = i->GetRenderable())
|
||||
AddRenderable(r, i->mitem_flags.IsSet(MItem::Flag_IsStatic));
|
||||
|
||||
g_scene_messenger.BroadcastMessage(SceneMsg_ItemAdded, this, i);
|
||||
}
|
||||
bool Scene::RemoveItem(MItem *i)
|
||||
{
|
||||
g_scene_messenger.BroadcastMessage(SceneMsg_DeletingItem, this, (void *)i);
|
||||
|
||||
i->item_event->OnDelete(i);
|
||||
|
||||
if (vm.IsValid())
|
||||
vm->InvalidateNativeReference(i);
|
||||
|
||||
// Remove from groups.
|
||||
UnregisterItemFromGroups(i);
|
||||
|
||||
if (Core::Renderable *r = i->GetRenderable())
|
||||
{
|
||||
// Remove from culling systems.
|
||||
simple_culling_system.DeleteRenderable(r);
|
||||
octree_culling_system.DeleteRenderable(r);
|
||||
}
|
||||
|
||||
if (Core::Item *b = i->GetBaseItem())
|
||||
{
|
||||
// Unset if current camera.
|
||||
if (current_camera == b)
|
||||
current_camera = NULL;
|
||||
|
||||
// Remove from triggers & skins.
|
||||
ListForeachPtr(MItem *, item, item_list)
|
||||
switch (item->GetItemType())
|
||||
{
|
||||
case Type_Trigger:
|
||||
((MTrigger *)item)->DropItem(b);
|
||||
break;
|
||||
|
||||
case Type_Object:
|
||||
{
|
||||
MObject *o = (MObject *)item;
|
||||
for (uint n = 0; n < o->GetBoneCount(); ++n)
|
||||
if (o->GetBone(n) == b)
|
||||
o->BindBone(n, NULL);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Remove from physic world.
|
||||
i->physic_item = NULL;
|
||||
|
||||
switch (i->GetItemType())
|
||||
{
|
||||
case Type_Light: light_list.Remove((MLight *)i); break;
|
||||
case Type_Trigger: trigger_list.Remove((MTrigger *)i); break;
|
||||
}
|
||||
|
||||
active_list.Remove(i);
|
||||
removal_queue.Remove(i);
|
||||
activation_queue.Remove(i);
|
||||
deactivation_queue.Remove(i);
|
||||
|
||||
item_list.Remove(i); // keep last
|
||||
|
||||
g_scene_messenger.BroadcastMessage(SceneMsg_ItemDeleted, this, i);
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void Scene::QueueItemRemoval(MItem *i)
|
||||
{ removal_queue.Add(i); }
|
||||
void Scene::ProcessItemRemovalQueue()
|
||||
{
|
||||
while (List <MItem *> ::Item *r = removal_queue.GetRoot())
|
||||
RemoveItem(r->Object());
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void Scene::Clear(bool keep_script)
|
||||
{
|
||||
g_scene_messenger.BroadcastMessage(SceneMsg_Clearing, this, 0);
|
||||
|
||||
scene_event->OnDelete(this);
|
||||
|
||||
// Remove all items (immediate/non-queued).
|
||||
while (List <MItem *> ::Item *i = item_list.GetRoot())
|
||||
RemoveItem(i->Object());
|
||||
|
||||
// Drop UI.
|
||||
ui->Clear();
|
||||
|
||||
// Close scripts.
|
||||
if (!keep_script)
|
||||
scripted_object->RemoveAllUnit();
|
||||
|
||||
fog_color.Set();
|
||||
fog_near = 0;
|
||||
fog_far = 0;
|
||||
|
||||
current_item_uid = 0;
|
||||
|
||||
g_scene_messenger.BroadcastMessage(SceneMsg_Cleared, this, 0);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
Scene::Scene(Script::IVM *script_vm) : profiler(*this)
|
||||
{
|
||||
vm = script_vm;
|
||||
current_camera = NULL;
|
||||
|
||||
current_item_uid = 0;
|
||||
|
||||
ambient_intensity = 1;
|
||||
target_exposure = 0.25;
|
||||
|
||||
time_of_day = 0.5;
|
||||
|
||||
fog_near = 0;
|
||||
fog_far = 0;
|
||||
fog_color.Set(0, 0, 0);
|
||||
|
||||
background_color.Set(0, 0, 0);
|
||||
ambient_color.Set(0, 0, 0);
|
||||
|
||||
clock = new Core::Clock;
|
||||
|
||||
scene_event = vm ? new SceneScriptEvent : new ISceneEvent;
|
||||
scripted_object = new SceneScriptedObject(vm, this);
|
||||
|
||||
irenderer_environment = new IEnvironment(this);
|
||||
iphysic_world = new IScenePhysicWorld(this);
|
||||
|
||||
ui = new S2D::Scene(vm);
|
||||
}
|
||||
Scene::~Scene()
|
||||
{
|
||||
SetAsScriptGlobalScene();
|
||||
Clear();
|
||||
|
||||
if (vm)
|
||||
vm->InvalidateNativeReference((void *)this);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
Reference in New Issue
Block a user