diff options
Diffstat (limited to 'source/gameengine/Ketsji/KX_SG_NodeRelationships.cpp')
-rw-r--r-- | source/gameengine/Ketsji/KX_SG_NodeRelationships.cpp | 309 |
1 files changed, 128 insertions, 181 deletions
diff --git a/source/gameengine/Ketsji/KX_SG_NodeRelationships.cpp b/source/gameengine/Ketsji/KX_SG_NodeRelationships.cpp index e80de76861e..160654c26f1 100644 --- a/source/gameengine/Ketsji/KX_SG_NodeRelationships.cpp +++ b/source/gameengine/Ketsji/KX_SG_NodeRelationships.cpp @@ -32,267 +32,214 @@ #include "KX_SG_NodeRelationships.h" -/** - * Implementation of classes defined in KX_SG_NodeRelationships.h - */ /** - * first of all KX_NormalParentRelation + * KX_NormalParentRelation - a regular parent/child relation, the child's coordinates are relative to the parent */ - KX_NormalParentRelation * -KX_NormalParentRelation:: -New( -) { +KX_NormalParentRelation* KX_NormalParentRelation::New() +{ return new KX_NormalParentRelation(); } - bool -KX_NormalParentRelation:: -UpdateChildCoordinates( - SG_Spatial * child, - const SG_Spatial * parent, - bool& parentUpdated -) { +bool KX_NormalParentRelation::UpdateChildCoordinates(SG_Spatial *child, const SG_Spatial *parent, bool &parentUpdated) +{ MT_assert(child != NULL); + /* If nothing changed in the parent or child, there is nothing to do here */ if (!parentUpdated && !child->IsModified()) return false; - parentUpdated = true; - - if (parent==NULL) { /* Simple case */ + /* The child has no parent, it is a root object. + * The world and local coordinates should be the same and applied directly. */ + if (parent==NULL) { child->SetWorldFromLocalTransform(); - child->ClearModified(); - return true; //false; } + /* The child has a parent. The child's coordinates are defined relative to the parent's. + * The parent's coordinates should be applied to the child's local ones to calculate the real world position. */ else { - // the childs world locations which we will update. - const MT_Vector3 & p_world_scale = parent->GetWorldScaling(); - const MT_Point3 & p_world_pos = parent->GetWorldPosition(); - const MT_Matrix3x3 & p_world_rotation = parent->GetWorldOrientation(); - - child->SetWorldScale(p_world_scale * child->GetLocalScale()); - child->SetWorldOrientation(p_world_rotation * child->GetLocalOrientation()); - child->SetWorldPosition(p_world_pos + p_world_scale * (p_world_rotation * child->GetLocalPosition())); - child->ClearModified(); - return true; + const MT_Vector3 & parent_world_scale = parent->GetWorldScaling(); + const MT_Point3 & parent_world_pos = parent->GetWorldPosition(); + const MT_Matrix3x3 & parent_world_ori = parent->GetWorldOrientation(); + const MT_Vector3 & child_local_scale = child->GetLocalScale(); + const MT_Point3 & child_local_pos = child->GetLocalPosition(); + const MT_Matrix3x3 & child_local_ori = child->GetLocalOrientation(); + + const MT_Vector3 & new_world_scale = parent_world_scale * child_local_scale; + const MT_Matrix3x3 & new_world_ori = parent_world_ori * child_local_ori; + const MT_Point3 & new_world_pos = parent_world_pos + (new_world_scale * (new_world_ori * child_local_pos)); + + child->SetWorldScale(new_world_scale); + child->SetWorldOrientation(new_world_ori); + child->SetWorldPosition(new_world_pos); } + + parentUpdated = true; //this variable is going to be used to update the children of this child + child->ClearModified(); + return true; } - SG_ParentRelation * -KX_NormalParentRelation:: -NewCopy( -) { +SG_ParentRelation* KX_NormalParentRelation::NewCopy() +{ return new KX_NormalParentRelation(); } -KX_NormalParentRelation:: -~KX_NormalParentRelation( -) { +KX_NormalParentRelation::~KX_NormalParentRelation() +{ //nothing to do } - -KX_NormalParentRelation:: -KX_NormalParentRelation( -) { +KX_NormalParentRelation::KX_NormalParentRelation() +{ // nothing to do } -/** - * Next KX_VertexParentRelation - */ - KX_VertexParentRelation * -KX_VertexParentRelation:: -New( -) { - return new KX_VertexParentRelation(); -} - -/** - * Method inherited from KX_ParentRelation + + +/** + * KX_VertexParentRelation - the child only inherits the position, not the orientation or scale */ - bool -KX_VertexParentRelation:: -UpdateChildCoordinates( - SG_Spatial * child, - const SG_Spatial * parent, - bool& parentUpdated -) { +KX_VertexParentRelation* KX_VertexParentRelation::New() +{ + return new KX_VertexParentRelation(); +} +bool KX_VertexParentRelation::UpdateChildCoordinates(SG_Spatial *child, const SG_Spatial *parent, bool &parentUpdated) +{ MT_assert(child != NULL); + /* If nothing changed in the parent or child, there is nothing to do here */ if (!parentUpdated && !child->IsModified()) return false; - child->SetWorldScale(child->GetLocalScale()); - - if (parent) - child->SetWorldPosition(child->GetLocalPosition()+parent->GetWorldPosition()); - else + /* The parent (if existing) is a vertex, so only position should be applied + * to the child's local coordinates to calculate the real world position. */ + + if (parent==NULL) child->SetWorldPosition(child->GetLocalPosition()); - + else + child->SetWorldPosition(child->GetLocalPosition()+parent->GetWorldPosition()); + + child->SetWorldScale(child->GetLocalScale()); child->SetWorldOrientation(child->GetLocalOrientation()); + + parentUpdated = true; //this variable is going to be used to update the children of this child child->ClearModified(); - return true; //parent != NULL; + return true; } -/** - * Method inherited from KX_ParentRelation - */ - - SG_ParentRelation * -KX_VertexParentRelation:: -NewCopy( -) { +SG_ParentRelation* KX_VertexParentRelation::NewCopy() +{ return new KX_VertexParentRelation(); -}; +} -KX_VertexParentRelation:: -~KX_VertexParentRelation( -) { +KX_VertexParentRelation::~KX_VertexParentRelation() +{ //nothing to do } - -KX_VertexParentRelation:: -KX_VertexParentRelation( -) { +KX_VertexParentRelation::KX_VertexParentRelation() +{ //nothing to do } + + + /** - * Slow parent relationship + * KX_SlowParentRelation - the child only inherits the position, not the orientation or scale */ - KX_SlowParentRelation * -KX_SlowParentRelation:: -New( - MT_Scalar relaxation -) { - return new KX_SlowParentRelation(relaxation); +KX_SlowParentRelation* KX_SlowParentRelation::New(MT_Scalar relaxation) +{ + return new KX_SlowParentRelation(relaxation); } -/** - * Method inherited from KX_ParentRelation - */ - - bool -KX_SlowParentRelation:: -UpdateChildCoordinates( - SG_Spatial * child, - const SG_Spatial * parent, - bool& parentUpdated -) { +bool KX_SlowParentRelation::UpdateChildCoordinates(SG_Spatial *child, const SG_Spatial *parent, bool &parentUpdated) +{ MT_assert(child != NULL); - // the child will move even if the parent is not - parentUpdated = true; - - const MT_Vector3 & child_scale = child->GetLocalScale(); - const MT_Point3 & child_pos = child->GetLocalPosition(); - const MT_Matrix3x3 & child_rotation = child->GetLocalOrientation(); - - // the childs world locations which we will update. - - MT_Vector3 child_w_scale; - MT_Point3 child_w_pos; - MT_Matrix3x3 child_w_rotation; - - if (parent) { - - // This is a slow parent relation - // first compute the normal child world coordinates. - - MT_Vector3 child_n_scale; - MT_Point3 child_n_pos; - MT_Matrix3x3 child_n_rotation; - - const MT_Vector3 & p_world_scale = parent->GetWorldScaling(); - const MT_Point3 & p_world_pos = parent->GetWorldPosition(); - const MT_Matrix3x3 & p_world_rotation = parent->GetWorldOrientation(); - - child_n_scale = p_world_scale * child_scale; - child_n_rotation = p_world_rotation * child_rotation; - - child_n_pos = p_world_pos + p_world_scale * - (p_world_rotation * child_pos); - + /* The child has no parent, it is a root object. + * The world and local coordinates should be the same and applied directly. */ + if (parent==NULL) { + child->SetWorldFromLocalTransform(); + } + /* The child's coordinates get linearly interpolated with the parent's */ + else { + const MT_Vector3 & parent_world_scale = parent->GetWorldScaling(); + const MT_Point3 & parent_world_pos = parent->GetWorldPosition(); + const MT_Matrix3x3 & parent_world_ori = parent->GetWorldOrientation(); + const MT_Vector3 & child_local_scale = child->GetLocalScale(); + const MT_Point3 & child_local_pos = child->GetLocalPosition(); + const MT_Matrix3x3 & child_local_ori = child->GetLocalOrientation(); + + /* Compute the normal world coordinates, where the child would be if it was a normal parent relation */ + const MT_Vector3 & normal_world_scale = parent_world_scale * child_local_scale; + const MT_Matrix3x3 & normal_world_ori = parent_world_ori * child_local_ori; + const MT_Point3 & normal_world_pos = parent_world_pos + (normal_world_scale * (normal_world_ori * child_local_pos)); + + MT_Vector3 new_world_scale; + MT_Point3 new_world_pos; + MT_Matrix3x3 new_world_ori; if (m_initialized) { - // get the current world positions + /* Get the current world positions */ + const MT_Vector3 & current_world_scale = child->GetWorldScaling(); + const MT_Matrix3x3 & current_world_ori = child->GetWorldOrientation(); + const MT_Point3 & current_world_pos = child->GetWorldPosition(); - child_w_scale = child->GetWorldScaling(); - child_w_pos = child->GetWorldPosition(); - child_w_rotation = child->GetWorldOrientation(); + /* Interpolate between the current world coordinates and the normal ones according to the weight. + * a bigger relax parameter, is a smaller weight, + * meaning that the child follows its normal position in smaller steps*/ + /* XXX - this design has problems as it does not consider elapsed time between last update */ + new_world_ori.setRotation(current_world_ori.getRotation().slerp(normal_world_ori.getRotation(), m_weight)); + new_world_pos = current_world_pos + ( (normal_world_pos - current_world_pos) * m_weight); + new_world_scale = current_world_scale + ( (normal_world_scale - current_world_scale) * m_weight); - // now 'interpolate' the normal coordinates with the last - // world coordinates to get the new world coordinates. - - MT_Scalar weight = MT_Scalar(1)/(m_relax + 1); - child_w_scale = (m_relax * child_w_scale + child_n_scale) * weight; - child_w_pos = (m_relax * child_w_pos + child_n_pos) * weight; - // for rotation we must go through quaternion - MT_Quaternion child_w_quat = child_w_rotation.getRotation().slerp(child_n_rotation.getRotation(), weight); - child_w_rotation.setRotation(child_w_quat); //FIXME: update physics controller. + } else { - child_w_scale = child_n_scale; - child_w_pos = child_n_pos; - child_w_rotation = child_n_rotation; + /** + * We need to compute valid world coordinates the first + * time we update spatial data of the child. This is done + * by just doing a normal parent relation the first time. + */ + new_world_scale = normal_world_scale; + new_world_ori = normal_world_ori; + new_world_pos = normal_world_pos; m_initialized = true; } - - } else { - child_w_scale = child_scale; - child_w_pos = child_pos; - child_w_rotation = child_rotation; + child->SetWorldScale(new_world_scale); + child->SetWorldOrientation(new_world_ori); + child->SetWorldPosition(new_world_pos); } - child->SetWorldScale(child_w_scale); - child->SetWorldPosition(child_w_pos); - child->SetWorldOrientation(child_w_rotation); + parentUpdated = true; //this variable is going to be used to update the children of this child child->ClearModified(); // this node must always be updated, so reschedule it for next time child->ActivateRecheduleUpdateCallback(); - - return true; //parent != NULL; + return true; } -/** - * Method inherited from KX_ParentRelation - */ - - SG_ParentRelation * -KX_SlowParentRelation:: -NewCopy( -) { +SG_ParentRelation* KX_SlowParentRelation::NewCopy() +{ return new KX_SlowParentRelation(m_relax); } -KX_SlowParentRelation:: -KX_SlowParentRelation( - MT_Scalar relaxation -): - m_relax(relaxation), - m_initialized(false) +KX_SlowParentRelation::KX_SlowParentRelation(MT_Scalar relaxation) + :m_initialized(false) { - //nothing to do + m_relax = fabs(relaxation); + m_weight = MT_Scalar(1)/(m_relax + 1); } -KX_SlowParentRelation:: -~KX_SlowParentRelation( -) { +KX_SlowParentRelation::~KX_SlowParentRelation() +{ //nothing to do } - - - - |