commit x64 compilation from lulu cause the other branch dont seems to compile properly at home
This commit is contained in:
186
include/modules/tools/scene_merge_object_list.cpp
Normal file
186
include/modules/tools/scene_merge_object_list.cpp
Normal file
@ -0,0 +1,186 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "tools/scene_merge_object_list.h"
|
||||
#include "tools/geometry_merge.h"
|
||||
#include "scene3d/scene.h"
|
||||
#include "scene3d/mobject.h"
|
||||
#include "physic/physic_world.h"
|
||||
#include "core/graphic_resource_factory.h"
|
||||
|
||||
using namespace GS;
|
||||
using namespace GS::Core;
|
||||
using namespace GS::S3D;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
struct ItemTransform
|
||||
{
|
||||
sMItem i;
|
||||
Matrix4 m;
|
||||
|
||||
ItemTransform(MItem *_i, const Matrix4 &_m) : i(_i), m(_m) {}
|
||||
};
|
||||
struct GeometryTransform
|
||||
{
|
||||
sMItem i;
|
||||
Matrix4 m;
|
||||
sGeometry g;
|
||||
|
||||
GeometryTransform(MItem *_i, Geometry *_g, const Matrix4 &_m) : i(_i), m(_m), g(_g) {}
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
static void MergePhysicShape(MItem *to, MItem *from)
|
||||
{
|
||||
if (!from->physic_item)
|
||||
return;
|
||||
|
||||
ListForeachPtr(PhysicShape *, shape, from->physic_item_desc.shape_list)
|
||||
if (PhysicShape *new_shape = new PhysicShape)
|
||||
{
|
||||
new_shape->SetMatrix(from->GetBaseItem()->GetMatrix() * shape->GetMatrix());
|
||||
new_shape->mass = shape->mass;
|
||||
|
||||
switch (shape->GetType())
|
||||
{
|
||||
case PhysicShape::TypeNone:
|
||||
break;
|
||||
|
||||
case PhysicShape::TypeHeightmap:
|
||||
__LOG_W__ << "Merge heightmap physic shape STUB.\n";
|
||||
break;
|
||||
|
||||
case PhysicShape::TypeBox:
|
||||
case PhysicShape::TypeCapsule:
|
||||
case PhysicShape::TypeCylinder:
|
||||
case PhysicShape::TypeCone:
|
||||
case PhysicShape::TypeSphere:
|
||||
new_shape->Set(shape->GetType(), shape->dimensions);
|
||||
break;
|
||||
|
||||
case PhysicShape::TypeConvex:
|
||||
case PhysicShape::TypeMesh:
|
||||
new_shape->Set(shape->GetType(), shape->path);
|
||||
break;
|
||||
}
|
||||
|
||||
to->physic_item_desc.shape_list.Add(new_shape);
|
||||
}
|
||||
|
||||
to->physic_item_desc.physic_mode = from->physic_item_desc.physic_mode;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool SceneMergeObjectList::Merge(Scene *scene, const SharedList <MItem *> &item_list, Core::ResourceFactory &gf, sMItem &out_item, sGeometry &out_geo)
|
||||
{
|
||||
// Unlink all children, store matrix beforehand.
|
||||
AutoList <ItemTransform *> child_list;
|
||||
|
||||
ListForeachPtr(MItem *, item, item_list)
|
||||
ListForeachPtr(Item *, child, item->GetBaseItem()->GetChildren())
|
||||
{
|
||||
MItem *cchild = Scene::LocateManagedItem(child);
|
||||
|
||||
// Do not store item if it is going to be merged.
|
||||
if (!item_list.Find(cchild))
|
||||
child_list.Add(new ItemTransform(cchild, cchild->GetBaseItem()->GetMatrix()));
|
||||
}
|
||||
|
||||
Vector4 average_vec(0.0,0.0,0.0);
|
||||
int counter_average = 0;
|
||||
ListForeachPtr(MItem *, item, item_list)
|
||||
if (item->GetItemType() == Type_Object)
|
||||
{
|
||||
++counter_average;
|
||||
average_vec += item->GetBaseItem()->GetPosition();
|
||||
}
|
||||
|
||||
average_vec /= counter_average;
|
||||
|
||||
ListForeachPtr(MItem *, item, item_list)
|
||||
if (item->GetItemType() == Type_Object)
|
||||
item->GetBaseItem()->SetPosition(item->GetBaseItem()->GetPosition() - average_vec);
|
||||
|
||||
// Build merge list.
|
||||
AutoList <GeometryTransform *> geo_list;
|
||||
ListForeachPtr(MItem *, item, item_list)
|
||||
if (item->GetItemType() == Type_Object)
|
||||
geo_list.Add(new GeometryTransform(item, gf.LoadGeometry(((MObject *)item)->geometry), item->GetBaseItem()->GetMatrix()));
|
||||
|
||||
if (geo_list.GetCount() < 2)
|
||||
return true; // nothing to be done
|
||||
|
||||
// Count total steps.
|
||||
int total_step_count = 0;
|
||||
for (int count = item_list.GetCount(); count > 1; count /= 2)
|
||||
total_step_count += count;
|
||||
|
||||
// Merge list.
|
||||
AutoList <GeometryTransform *> tgt_list, *in_list = &geo_list, *out_list = &tgt_list;
|
||||
|
||||
int step_count = 0;
|
||||
for (bool running = true; (in_list->GetCount() > 1) && running; )
|
||||
{
|
||||
for (uint n = 0; (n < in_list->GetCount()) && running; n += 2)
|
||||
{
|
||||
if (n == (in_list->GetCount() - 1))
|
||||
{
|
||||
GeometryTransform *t = (*in_list)[n];
|
||||
out_list->Add(new GeometryTransform(t->i, t->g, t->m));
|
||||
continue; // nothing to merge
|
||||
}
|
||||
|
||||
// Merge geometries.
|
||||
GeometryTransform *left = (*in_list)[n], *right = (*in_list)[n + 1];
|
||||
sGeometry merged_geometry(MergeGeometry(left->g, right->g, &left->m, &right->m));
|
||||
if (merged_geometry.IsNull())
|
||||
continue;
|
||||
|
||||
// Merge physic shapes.
|
||||
MObject *merged_object = new MObject;
|
||||
scene->SetupItemComponents(merged_object);
|
||||
MergePhysicShape(merged_object, left->i);
|
||||
MergePhysicShape(merged_object, right->i);
|
||||
|
||||
out_list->Add(new GeometryTransform(merged_object, merged_geometry, Matrix4::IdentityMatrix()));
|
||||
|
||||
running = OnProgress(++step_count, total_step_count);
|
||||
}
|
||||
in_list->Clear();
|
||||
|
||||
AutoList <GeometryTransform *> *tmp_list = in_list; in_list = out_list; out_list = tmp_list;
|
||||
}
|
||||
if (in_list->GetCount() != 1)
|
||||
return false;
|
||||
|
||||
// Remove merged items from scene.
|
||||
ListForeachPtr(MItem *, item, item_list)
|
||||
if (item->GetItemType() == Type_Object)
|
||||
scene->RemoveItem(item);
|
||||
|
||||
// Store output...
|
||||
out_item = (*in_list)[0]->i;
|
||||
out_geo = (*in_list)[0]->g;
|
||||
|
||||
out_item->GetBaseItem()->SetPosition(average_vec);
|
||||
|
||||
out_item->name = "Merged Object";
|
||||
scene->AddItem(out_item, false);
|
||||
|
||||
// ...restore parenting.
|
||||
ListForeachPtr(ItemTransform *, t, child_list)
|
||||
{
|
||||
t->i->GetBaseItem()->SetParent(out_item->GetBaseItem());
|
||||
t->i->GetBaseItem()->SnapshotTransformation(t->m);
|
||||
}
|
||||
child_list.Clear();
|
||||
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
Reference in New Issue
Block a user