commit x64 compilation from lulu cause the other branch dont seems to compile properly at home
This commit is contained in:
341
include/engine/core/item.cpp
Normal file
341
include/engine/core/item.cpp
Normal file
@ -0,0 +1,341 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "core/item.h"
|
||||
#include "geometry/bounding_box.h"
|
||||
#include "log/log.h"
|
||||
|
||||
using namespace GS;
|
||||
using namespace GS::Core;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
Matrix4 Item::GetMatrixNoPivot()
|
||||
{
|
||||
Matrix4 p = GetPivot();
|
||||
SetPivot(Matrix4::IdentityMatrix());
|
||||
Matrix4 m = GetMatrix();
|
||||
SetPivot(p);
|
||||
return m;
|
||||
}
|
||||
void Item::ComputeLocalMatrix()
|
||||
{
|
||||
if (!item_flags.IsSet(ItemFlagLocalMatrixDirty))
|
||||
return;
|
||||
|
||||
if (!item_flags.IsSet(ItemFlagHasTarget) && item_flags.IsSet(ItemFlagRotationMatrixDirty))
|
||||
{
|
||||
rotation_matrix = Matrix3::FromEuler(rotation.x, rotation.y, rotation.z, rorder);
|
||||
item_flags.Remove(ItemFlagRotationMatrixDirty);
|
||||
}
|
||||
|
||||
local_matrix =
|
||||
(
|
||||
Matrix4::TranslationMatrix(position) *
|
||||
Matrix4::FromMatrix3(rotation_matrix) *
|
||||
Matrix4::ScaleMatrix(scale)
|
||||
)
|
||||
*
|
||||
pivot_matrix;
|
||||
|
||||
item_flags.Remove(ItemFlagLocalMatrixDirty);
|
||||
}
|
||||
void Item::ComputeMatrix()
|
||||
{
|
||||
bool update_local = item_flags.IsSet(ItemFlagLocalMatrixDirty),
|
||||
update_world = item_flags.IsSet(ItemFlagWorldMatrixDirty);
|
||||
|
||||
if (update_local)
|
||||
ComputeLocalMatrix();
|
||||
|
||||
if (!parent)
|
||||
{
|
||||
if (update_world)
|
||||
matrix = local_matrix;
|
||||
}
|
||||
else if (update_world)
|
||||
{
|
||||
matrix = parent->GetMatrix() * local_matrix;
|
||||
|
||||
if (item_flags.IsSet(ItemFlagInheritPositionOnly))
|
||||
{
|
||||
Matrix4 m(Matrix4::FromMatrix3(rotation_matrix));
|
||||
m.SetRow(3, matrix.GetRow(3));
|
||||
matrix = m;
|
||||
}
|
||||
}
|
||||
|
||||
/// Handle item target and scale.
|
||||
if (update_local || update_world)
|
||||
if (item_flags.IsSet(ItemFlagHasTarget))
|
||||
{
|
||||
matrix.Decompose(NULL, NULL, &rotation_matrix);
|
||||
Matrix3 tgtm = Matrix3::FromOrthonormalBasis(target - matrix.GetRow(3));
|
||||
matrix = matrix * Matrix4::FromMatrix3(rotation_matrix.Transposed() * tgtm);
|
||||
rotation_matrix = tgtm;
|
||||
}
|
||||
|
||||
item_flags.Remove(ItemFlagWorldMatrixDirty);
|
||||
}
|
||||
void Item::ComputeInverseMatrix()
|
||||
{
|
||||
if (item_flags.IsSet(ItemFlagInverseWorldMatrixDirty))
|
||||
{
|
||||
imatrix = GetMatrix().InversedFast();
|
||||
item_flags.Remove(ItemFlagInverseWorldMatrixDirty);
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void Item::MarkWorldTransformationDirty()
|
||||
{
|
||||
item_flags.Set(ItemFlagWorldMatrixDirty | ItemFlagInverseWorldMatrixDirty);
|
||||
ListForeachPtr(Item *, i, children)
|
||||
i->MarkWorldTransformationDirty();
|
||||
}
|
||||
void Item::MarkTransformationDirty(bool child_only)
|
||||
{
|
||||
if (!child_only)
|
||||
item_flags.Set(ItemFlagLocalMatrixDirty | ItemFlagWorldMatrixDirty | ItemFlagInverseWorldMatrixDirty);
|
||||
|
||||
ListForeachPtr(Item *, i, children)
|
||||
i->MarkWorldTransformationDirty();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void Item::SetPosition(const Vector4 &p)
|
||||
{
|
||||
position = p;
|
||||
MarkTransformationDirty();
|
||||
}
|
||||
const Vector4 &Item::GetPosition() const
|
||||
{ return position; }
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void Item::SetRotation(const Vector4 &r)
|
||||
{
|
||||
rotation = r;
|
||||
item_flags.Set(ItemFlagRotationMatrixDirty);
|
||||
MarkTransformationDirty();
|
||||
}
|
||||
void Item::SetRotation(const Quaternion &q)
|
||||
{
|
||||
rotation_matrix = q.AsMatrix3();
|
||||
item_flags.Remove(ItemFlagRotationMatrixDirty);
|
||||
rotation = rotation_matrix.AsEuler(GetRotationOrder());
|
||||
MarkTransformationDirty();
|
||||
}
|
||||
void Item::SetRotation(const Matrix3 &m)
|
||||
{
|
||||
rotation_matrix = m;
|
||||
item_flags.Remove(ItemFlagRotationMatrixDirty);
|
||||
rotation = rotation_matrix.AsEuler(GetRotationOrder());
|
||||
MarkTransformationDirty();
|
||||
}
|
||||
const Vector4 &Item::GetRotation() const
|
||||
{ return rotation; }
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void Item::SetScale(const Vector4 &s)
|
||||
{
|
||||
scale = s;
|
||||
MarkTransformationDirty();
|
||||
}
|
||||
const Vector4 &Item::GetScale() const
|
||||
{ return scale; }
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void Item::SetPivot(const Matrix4 &m)
|
||||
{
|
||||
pivot_matrix = m;
|
||||
MarkTransformationDirty();
|
||||
}
|
||||
const Matrix4 &Item::GetPivot() const
|
||||
{ return pivot_matrix; }
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
const Matrix4 &Item::GetPreviousMatrix() const
|
||||
{ return prv_matrix; }
|
||||
void Item::SetPreviousMatrix(const Matrix4 &mtx)
|
||||
{ prv_matrix = mtx; }
|
||||
const Matrix4 &Item::GetLocalMatrix()
|
||||
{
|
||||
ComputeMatrix();
|
||||
return local_matrix;
|
||||
}
|
||||
const Matrix4 &Item::GetMatrix()
|
||||
{
|
||||
ComputeMatrix();
|
||||
return matrix;
|
||||
}
|
||||
const Matrix4 &Item::GetInverseMatrix()
|
||||
{
|
||||
ComputeInverseMatrix();
|
||||
return imatrix;
|
||||
}
|
||||
const Matrix3 &Item::GetRotationMatrix()
|
||||
{
|
||||
ComputeMatrix();
|
||||
return rotation_matrix;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
void Item::OffsetWorldPosition(const Vector4 &offset)
|
||||
//-------------------------------------------------------------------
|
||||
{
|
||||
if (parent)
|
||||
position += (matrix.GetRow(3) + offset) * parent->imatrix - matrix.GetRow(3) * parent->imatrix;
|
||||
else position += offset;
|
||||
|
||||
MarkTransformationDirty();
|
||||
}
|
||||
|
||||
//------------------------------------------------
|
||||
bool Item::IsLinkedTo(Item *item)
|
||||
//------------------------------------------------
|
||||
{
|
||||
for (Item *c = this; c; )
|
||||
{
|
||||
if (c == item)
|
||||
return true;
|
||||
c = c->GetParent();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
void Item::ComputeLocalMinMax(MinMax &minmax) const
|
||||
//------------------------------------------------------------------
|
||||
{
|
||||
Vector4 w_position = matrix.GetRow(3);
|
||||
minmax.Set(w_position, w_position);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------------------
|
||||
void Item::SnapshotTransformation(const Matrix4 &m, bool local, bool only_matrix)
|
||||
//------------------------------------------------------------------------------------------------
|
||||
{
|
||||
local_matrix = (parent && !local) ? parent->GetInverseMatrix() * m : m;
|
||||
item_flags.Remove(ItemFlagLocalMatrixDirty);
|
||||
|
||||
if (!only_matrix)
|
||||
{
|
||||
// Remove pivot before extracting transformation components.
|
||||
(local_matrix * pivot_matrix.InversedFast()).Decompose(&position, &scale, &rotation_matrix);
|
||||
rotation = rotation_matrix.AsEuler(rorder);
|
||||
item_flags.Remove(ItemFlagRotationMatrixDirty);
|
||||
}
|
||||
|
||||
MarkWorldTransformationDirty();
|
||||
}
|
||||
|
||||
//--------------------------------------------
|
||||
void Item::SetParent(Item *p)
|
||||
//--------------------------------------------
|
||||
{
|
||||
if (p == this)
|
||||
__ERRRAW__(__LOG_E__ << "Cannot parent item to itself.\n")
|
||||
|
||||
// Already linked.
|
||||
if (p && p->children.Find(this)) // FIXME why not if (parent == i)???
|
||||
return;
|
||||
|
||||
// Catch and correct deadlock.
|
||||
for (Item *c = p; c; c = c->GetParent())
|
||||
if (c->GetParent() && (c->GetParent() == this))
|
||||
{
|
||||
c->SetParent(GetParent()); // Extract 'this' from the parent chain.
|
||||
__LOG_W__ << "Deadlock detected, link chain has been corrected.\n";
|
||||
break;
|
||||
}
|
||||
|
||||
// Remove from current parent children list.
|
||||
if (parent)
|
||||
parent->children.Remove(this);
|
||||
|
||||
// Set parent.
|
||||
parent = p;
|
||||
|
||||
// Insert as a new parent child.
|
||||
if (parent)
|
||||
parent->children.Add(this);
|
||||
|
||||
MarkTransformationDirty();
|
||||
}
|
||||
|
||||
//----------------------------------------------------
|
||||
void Item::SetTarget(const Vector4 *p)
|
||||
//----------------------------------------------------
|
||||
{
|
||||
if (p)
|
||||
{
|
||||
item_flags.Set(ItemFlagHasTarget);
|
||||
target = *p;
|
||||
}
|
||||
else
|
||||
item_flags.Remove(ItemFlagHasTarget);
|
||||
|
||||
MarkTransformationDirty();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------
|
||||
void Item::SetMatrix(const Matrix4 &m)
|
||||
//-----------------------------------------------------
|
||||
{
|
||||
SnapshotTransformation(m, false);
|
||||
|
||||
matrix = m;
|
||||
imatrix = m.InversedFast();
|
||||
item_flags.Remove(ItemFlagWorldMatrixDirty | ItemFlagInverseWorldMatrixDirty);
|
||||
|
||||
MarkTransformationDirty(true);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------
|
||||
void Item::SetRotationOrder(Math::rOrder order)
|
||||
//--------------------------------------------------------------
|
||||
{
|
||||
rorder = order;
|
||||
MarkTransformationDirty();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
Item::Item() : position(0, 0, 0), rotation(0, 0, 0), scale(1, 1, 1)
|
||||
{
|
||||
local_matrix = Matrix4::IdentityMatrix();
|
||||
prv_matrix = Matrix4::IdentityMatrix();
|
||||
matrix = Matrix4::IdentityMatrix();
|
||||
imatrix = Matrix4::IdentityMatrix();
|
||||
pivot_matrix = Matrix4::IdentityMatrix();
|
||||
|
||||
parent = NULL;
|
||||
|
||||
rorder = Math::rOrder_Default;
|
||||
|
||||
scale.Set(1,1,1,1);
|
||||
|
||||
mitem = NULL;
|
||||
target.Set(0, 0, 1);
|
||||
|
||||
opacity = 1;
|
||||
|
||||
MarkTransformationDirty();
|
||||
item_flags.Set(ItemFlagRotationMatrixDirty);
|
||||
}
|
||||
Item::~Item()
|
||||
{
|
||||
ListForeachPtr(Item *, child, children)
|
||||
child->SetParent(NULL);
|
||||
SetParent(NULL);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
Reference in New Issue
Block a user