synched with trunk at revision 32129
[blender.git] / source / gameengine / Ketsji / KX_SG_NodeRelationships.cpp
index 437f696d872022b2d0b5dbc80d22d38c0c5d678b..ccdaac8edb75045e7bf7c84ec94e126f12a2404d 100644 (file)
@@ -1,14 +1,11 @@
 /**
  * $Id$
- * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ * ***** BEGIN GPL LICENSE BLOCK *****
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
  * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version. The Blender
- * Foundation also sells licenses for use in proprietary software under
- * the Blender License.  See http://www.blender.org/BL/ for information
- * about this.
+ * of the License, or (at your option) any later version.
  *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -17,7 +14,7 @@
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  *
  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
  * All rights reserved.
  *
  * Contributor(s): none yet.
  *
- * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * ***** END GPL LICENSE BLOCK *****
  */
 
 #include "KX_SG_NodeRelationships.h"
 
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
 /**
  * Implementation of classes defined in KX_SG_NodeRelationships.h
  */
@@ -50,48 +43,37 @@ New(
        return new KX_NormalParentRelation();
 }              
 
-       void
+       bool
 KX_NormalParentRelation::
 UpdateChildCoordinates(
        SG_Spatial * child,
-       const SG_Spatial * parent
+       const SG_Spatial * parent,
+       bool& parentUpdated     
 ){
-       assert(child != NULL);
+       MT_assert(child != NULL);
 
-       // This way of accessing child coordinates is a bit cumbersome
-       // be nice to have non constant reference access to these values.
+       if (!parentUpdated && !child->IsModified())
+               return false;
 
-       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) {
+       parentUpdated = true;
 
+       if (parent==NULL) { /* Simple case */
+               child->SetWorldFromLocalTransform();
+               child->ClearModified();
+               return true; //false;
+       }
+       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_w_scale = p_world_scale * child_scale;
-               child_w_rotation = p_world_rotation * child_rotation;
-
-               child_w_pos = p_world_pos + p_world_scale * 
-                       (p_world_rotation * child_pos);
-       } else {
-
-               child_w_scale = child_scale;
-               child_w_pos = child_pos;
-               child_w_rotation = child_rotation;
+               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;
        }
-
-       child->SetWorldScale(child_w_scale);
-       child->SetWorldPosition(child_w_pos);
-       child->SetWorldOrientation(child_w_rotation);
 }
 
        SG_ParentRelation *
@@ -130,48 +112,29 @@ New(
  * Method inherited from KX_ParentRelation
  */
 
-       void
+       bool
 KX_VertexParentRelation::
 UpdateChildCoordinates(
        SG_Spatial * child,
-       const SG_Spatial * parent
+       const SG_Spatial * parent,
+       bool& parentUpdated     
 ){
 
-       assert(child != NULL);
+       MT_assert(child != NULL);
 
-       const MT_Vector3 & child_scale = child->GetLocalScale();
-       const MT_Point3 & child_pos = child->GetLocalPosition();
-       const MT_Matrix3x3 & child_rotation = child->GetLocalOrientation();
+       if (!parentUpdated && !child->IsModified())
+               return false;
 
-       // the childs world locations which we will update.     
+       child->SetWorldScale(child->GetLocalScale());
        
-       MT_Vector3 child_w_scale;
-       MT_Point3 child_w_pos;
-       MT_Matrix3x3 child_w_rotation;
-               
-       if (parent) {
-
-               // This is a vertex parent so we do not inherit orientation 
-               // information.
-
-               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_w_scale = child_scale;
-               child_w_rotation = child_rotation;
-               child_w_pos = p_world_pos + child_pos;
-
-       } else {
-
-               child_w_scale = child_scale;
-               child_w_pos = child_pos;
-               child_w_rotation = child_rotation;
-       }
-
-       child->SetWorldScale(child_w_scale);
-       child->SetWorldPosition(child_w_pos);
-       child->SetWorldOrientation(child_w_rotation);
+       if (parent)
+               child->SetWorldPosition(child->GetLocalPosition()+parent->GetWorldPosition());
+       else
+               child->SetWorldPosition(child->GetLocalPosition());
+       
+       child->SetWorldOrientation(child->GetLocalOrientation());
+       child->ClearModified();
+       return true; //parent != NULL;
 }
 
 /** 
@@ -215,13 +178,17 @@ New(
  * Method inherited from KX_ParentRelation
  */
 
-       void
+       bool
 KX_SlowParentRelation::
 UpdateChildCoordinates(
        SG_Spatial * child,
-       const SG_Spatial * parent
+       const SG_Spatial * parent,
+       bool& parentUpdated     
 ){
-       assert(child != NULL);
+       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();
@@ -264,22 +231,13 @@ UpdateChildCoordinates(
                        // now 'interpolate' the normal coordinates with the last 
                        // world coordinates to get the new world coordinates.
 
-                       // problem 1:
-                       // The child world scale needs to be initialized in some way for this 
-                       // to make sense
-                       // problem 2:
-                       // This is way of doing interpolation is nonsense
-
-                       int i;
-
                        MT_Scalar weight = MT_Scalar(1)/(m_relax + 1);
-                       for (i=0;i <3 ;i++) {
-                               child_w_scale[i] = (m_relax * child_w_scale[i] + child_n_scale[i]) * weight;
-                               child_w_pos[i] = (m_relax * child_w_pos[i] + child_n_pos[i]) * weight;
-                               child_w_rotation[0][i] = (m_relax * child_w_rotation[0][i] + child_n_rotation[0][i]) * weight;
-                               child_w_rotation[1][i] = (m_relax * child_w_rotation[1][i] + child_n_rotation[1][i]) * weight;
-                               child_w_rotation[2][i] = (m_relax * child_w_rotation[2][i] + child_n_rotation[2][i]) * weight;
-                       }
+                       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;
@@ -297,6 +255,11 @@ UpdateChildCoordinates(
        child->SetWorldScale(child_w_scale);
        child->SetWorldPosition(child_w_pos);
        child->SetWorldOrientation(child_w_rotation);
+       child->ClearModified();
+       // this node must always be updated, so reschedule it for next time
+       child->ActivateRecheduleUpdateCallback();
+       
+       return true; //parent != NULL;
 }
 
 /**