Minor speedups for the BGE
[blender.git] / source / gameengine / Ketsji / KX_SG_NodeRelationships.cpp
1 /**
2  * $Id$
3  * ***** BEGIN GPL LICENSE BLOCK *****
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software Foundation,
17  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18  *
19  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
20  * All rights reserved.
21  *
22  * The Original Code is: all of this file.
23  *
24  * Contributor(s): none yet.
25  *
26  * ***** END GPL LICENSE BLOCK *****
27  */
28
29 #include "KX_SG_NodeRelationships.h"
30
31 #ifdef HAVE_CONFIG_H
32 #include <config.h>
33 #endif
34
35 /**
36  * Implementation of classes defined in KX_SG_NodeRelationships.h
37  */
38
39 /** 
40  * first of all KX_NormalParentRelation
41  */
42
43         KX_NormalParentRelation *
44 KX_NormalParentRelation::
45 New(
46 ) {
47         return new KX_NormalParentRelation();
48 }               
49
50         bool
51 KX_NormalParentRelation::
52 UpdateChildCoordinates(
53         SG_Spatial * child,
54         const SG_Spatial * parent
55 ){
56         MT_assert(child != NULL);
57
58         if (parent==NULL) { /* Simple case */
59                 child->SetWorldFromLocalTransform();
60                 return false;
61         }
62         else {
63                 // the childs world locations which we will update.     
64                 const MT_Vector3 & p_world_scale = parent->GetWorldScaling();
65                 const MT_Point3 & p_world_pos = parent->GetWorldPosition();
66                 const MT_Matrix3x3 & p_world_rotation = parent->GetWorldOrientation();
67
68                 child->SetWorldScale(p_world_scale * child->GetLocalScale());
69                 child->SetWorldOrientation(p_world_rotation * child->GetLocalOrientation());
70                 child->SetWorldPosition(p_world_pos + p_world_scale * (p_world_rotation * child->GetLocalPosition()));
71                 return true;
72         }
73 }
74
75         SG_ParentRelation *
76 KX_NormalParentRelation::
77 NewCopy(
78 ){
79         return new KX_NormalParentRelation();
80 }
81
82 KX_NormalParentRelation::
83 ~KX_NormalParentRelation(
84 ){
85         //nothing to do
86 }
87
88
89 KX_NormalParentRelation::
90 KX_NormalParentRelation(
91 ){
92         // nothing to do
93 }
94
95 /** 
96  * Next KX_VertexParentRelation
97  */
98
99
100         KX_VertexParentRelation *
101 KX_VertexParentRelation::
102 New(
103 ){
104         return new KX_VertexParentRelation();
105 }
106                 
107 /** 
108  * Method inherited from KX_ParentRelation
109  */
110
111         bool
112 KX_VertexParentRelation::
113 UpdateChildCoordinates(
114         SG_Spatial * child,
115         const SG_Spatial * parent
116 ){
117
118         MT_assert(child != NULL);
119         child->SetWorldScale(child->GetLocalScale());
120         
121         if (parent)
122                 child->SetWorldPosition(child->GetLocalPosition()+parent->GetWorldPosition());
123         else
124                 child->SetWorldPosition(child->GetLocalPosition());
125         
126         child->SetWorldOrientation(child->GetLocalOrientation());
127         return parent != NULL;
128 }
129
130 /** 
131  * Method inherited from KX_ParentRelation
132  */
133
134         SG_ParentRelation *
135 KX_VertexParentRelation::
136 NewCopy(
137 ){
138         return new KX_VertexParentRelation();
139 };
140
141 KX_VertexParentRelation::
142 ~KX_VertexParentRelation(
143 ){
144         //nothing to do
145 }
146
147
148 KX_VertexParentRelation::
149 KX_VertexParentRelation(
150 ){
151         //nothing to do
152 }
153
154
155 /**
156  * Slow parent relationship
157  */
158
159         KX_SlowParentRelation *
160 KX_SlowParentRelation::
161 New(
162         MT_Scalar relaxation
163 ){
164         return new      KX_SlowParentRelation(relaxation);
165 }       
166
167 /** 
168  * Method inherited from KX_ParentRelation
169  */
170
171         bool
172 KX_SlowParentRelation::
173 UpdateChildCoordinates(
174         SG_Spatial * child,
175         const SG_Spatial * parent
176 ){
177         MT_assert(child != NULL);
178
179         const MT_Vector3 & child_scale = child->GetLocalScale();
180         const MT_Point3 & child_pos = child->GetLocalPosition();
181         const MT_Matrix3x3 & child_rotation = child->GetLocalOrientation();
182
183         // the childs world locations which we will update.     
184         
185         MT_Vector3 child_w_scale;
186         MT_Point3 child_w_pos;
187         MT_Matrix3x3 child_w_rotation;
188                 
189         if (parent) {
190
191                 // This is a slow parent relation
192                 // first compute the normal child world coordinates.
193
194                 MT_Vector3 child_n_scale;
195                 MT_Point3 child_n_pos;
196                 MT_Matrix3x3 child_n_rotation;
197
198                 const MT_Vector3 & p_world_scale = parent->GetWorldScaling();
199                 const MT_Point3 & p_world_pos = parent->GetWorldPosition();
200                 const MT_Matrix3x3 & p_world_rotation = parent->GetWorldOrientation();
201
202                 child_n_scale = p_world_scale * child_scale;
203                 child_n_rotation = p_world_rotation * child_rotation;
204
205                 child_n_pos = p_world_pos + p_world_scale * 
206                         (p_world_rotation * child_pos);
207
208
209                 if (m_initialized) {
210
211                         // get the current world positions
212
213                         child_w_scale = child->GetWorldScaling();
214                         child_w_pos = child->GetWorldPosition();
215                         child_w_rotation = child->GetWorldOrientation();        
216
217                         // now 'interpolate' the normal coordinates with the last 
218                         // world coordinates to get the new world coordinates.
219
220                         // problem 1:
221                         // The child world scale needs to be initialized in some way for this 
222                         // to make sense
223                         // problem 2:
224                         // This is way of doing interpolation is nonsense
225
226                         int i;
227
228                         MT_Scalar weight = MT_Scalar(1)/(m_relax + 1);
229                         for (i=0;i <3 ;i++) {
230                                 child_w_scale[i] = (m_relax * child_w_scale[i] + child_n_scale[i]) * weight;
231                                 child_w_pos[i] = (m_relax * child_w_pos[i] + child_n_pos[i]) * weight;
232                                 child_w_rotation[0][i] = (m_relax * child_w_rotation[0][i] + child_n_rotation[0][i]) * weight;
233                                 child_w_rotation[1][i] = (m_relax * child_w_rotation[1][i] + child_n_rotation[1][i]) * weight;
234                                 child_w_rotation[2][i] = (m_relax * child_w_rotation[2][i] + child_n_rotation[2][i]) * weight;
235                         }
236                         
237                         //FIXME: update physics controller.
238                 } else {
239                         child_w_scale = child_n_scale;
240                         child_w_pos = child_n_pos;
241                         child_w_rotation = child_n_rotation;
242                         m_initialized = true;
243                 }
244                         
245         } else {
246
247                 child_w_scale = child_scale;
248                 child_w_pos = child_pos;
249                 child_w_rotation = child_rotation;
250         }
251
252         child->SetWorldScale(child_w_scale);
253         child->SetWorldPosition(child_w_pos);
254         child->SetWorldOrientation(child_w_rotation);
255         
256         return parent != NULL;
257 }
258
259 /** 
260  * Method inherited from KX_ParentRelation
261  */
262
263         SG_ParentRelation *
264 KX_SlowParentRelation::
265 NewCopy(
266 ){
267         return new      KX_SlowParentRelation(m_relax);
268 }
269
270 KX_SlowParentRelation::
271 KX_SlowParentRelation(
272         MT_Scalar relaxation
273 ):
274         m_relax(relaxation),
275         m_initialized(false)
276 {
277         //nothing to do
278 }
279
280 KX_SlowParentRelation::
281 ~KX_SlowParentRelation(
282 ){
283         //nothing to do
284 }
285
286
287
288