resolved conflict state with HEAD r14096
[blender.git] / source / gameengine / SceneGraph / SG_Spatial.cpp
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version. The Blender
10  * Foundation also sells licenses for use in proprietary software under
11  * the Blender License.  See http://www.blender.org/BL/ for information
12  * about this.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22  *
23  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
24  * All rights reserved.
25  *
26  * The Original Code is: all of this file.
27  *
28  * Contributor(s): none yet.
29  *
30  * ***** END GPL/BL DUAL LICENSE BLOCK *****
31  */
32
33 #include "SG_Node.h"
34 #include "SG_Spatial.h"
35 #include "SG_Controller.h"
36 #include "SG_ParentRelation.h"
37
38 #ifdef HAVE_CONFIG_H
39 #include <config.h>
40 #endif
41
42 SG_Spatial::
43 SG_Spatial(
44         void* clientobj,
45         void* clientinfo,
46         SG_Callbacks callbacks
47 ): 
48
49         SG_IObject(clientobj,clientinfo,callbacks),
50         m_localPosition(MT_Point3(0.0,0.0,0.0)),
51         m_localRotation(MT_Matrix3x3(1.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,1.0)),
52         m_localScaling(MT_Vector3(1.f,1.f,1.f)),
53         
54         m_worldPosition(MT_Point3(0.0,0.0,0.0)),
55         m_worldRotation(MT_Matrix3x3(1.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,1.0)),
56         m_worldScaling(MT_Vector3(1.f,1.f,1.f)),
57
58         m_parent_relation (NULL),
59         
60         m_bbox(MT_Point3(-1.0, -1.0, -1.0), MT_Point3(1.0, 1.0, 1.0)),
61         m_radius(1.0)
62 {
63 }
64
65 SG_Spatial::
66 SG_Spatial(
67         const SG_Spatial& other
68 ) : 
69         SG_IObject(other),
70         m_localPosition(other.m_localPosition),
71         m_localRotation(other.m_localRotation),
72         m_localScaling(other.m_localScaling),
73         
74         m_worldPosition(other.m_worldPosition),
75         m_worldRotation(other.m_worldRotation),
76         m_worldScaling(other.m_worldScaling),
77         
78         m_parent_relation(NULL),
79         
80         m_bbox(other.m_bbox),
81         m_radius(other.m_radius)
82 {
83         // duplicate the parent relation for this object
84         m_parent_relation = other.m_parent_relation->NewCopy();
85 }
86         
87 SG_Spatial::
88 ~SG_Spatial()
89 {
90         delete (m_parent_relation);
91 }
92
93         void
94 SG_Spatial::
95 SetParentRelation(
96         SG_ParentRelation *relation
97 ){
98         delete (m_parent_relation);
99         m_parent_relation = relation;
100 }
101
102
103 /**
104  * Update Spatial Data.
105  * Calculates WorldTransform., (either doing itsself or using the linked SGControllers)
106  */
107
108
109         bool 
110 SG_Spatial::
111 UpdateSpatialData(
112         const SG_Spatial *parent,
113         double time
114 ){
115
116     bool bComputesWorldTransform = false;
117
118         // update spatial controllers
119         
120         SGControllerList::iterator cit = GetSGControllerList().begin();
121         SGControllerList::const_iterator c_end = GetSGControllerList().end();
122
123         for (;cit!=c_end;++cit)
124         {
125                 if ((*cit)->Update(time))
126                         bComputesWorldTransform = true;
127         }
128
129         // If none of the objects updated our values then we ask the
130         // parent_relation object owned by this class to update 
131         // our world coordinates.
132
133         if (!bComputesWorldTransform)
134                 bComputesWorldTransform = ComputeWorldTransforms(parent);
135
136         return bComputesWorldTransform;
137 }
138
139 bool    SG_Spatial::ComputeWorldTransforms(const SG_Spatial *parent)
140 {
141         return m_parent_relation->UpdateChildCoordinates(this,parent);
142 }
143
144 /**
145  * Position and translation methods
146  */
147
148
149         void 
150 SG_Spatial::
151 RelativeTranslate(
152         const MT_Vector3& trans,
153         const SG_Spatial *parent,
154         bool local
155 ){
156         if (local) {
157                         m_localPosition += m_localRotation * trans;
158         } else {
159                 if (parent) {
160                         m_localPosition += trans * parent->GetWorldOrientation();
161                 } else {
162                         m_localPosition += trans;
163                 }
164         }
165 }       
166         
167         void 
168 SG_Spatial::
169 SetLocalPosition(
170         const MT_Point3& trans
171 ){
172         m_localPosition = trans;
173 }
174
175         void                            
176 SG_Spatial::
177 SetWorldPosition(
178         const MT_Point3& trans
179 ) {
180         m_worldPosition = trans;
181 }
182
183 /**
184  * Scaling methods.
185  */ 
186
187         void 
188 SG_Spatial::
189 RelativeScale(
190         const MT_Vector3& scale
191 ){
192         m_localScaling = m_localScaling * scale;
193 }
194
195         void 
196 SG_Spatial::
197 SetLocalScale(
198         const MT_Vector3& scale
199 ){
200         m_localScaling = scale;
201 }
202
203
204         void                            
205 SG_Spatial::
206 SetWorldScale(
207         const MT_Vector3& scale
208 ){ 
209         m_worldScaling = scale;
210 }
211
212 /**
213  * Orientation and rotation methods.
214  */
215
216
217         void 
218 SG_Spatial::
219 RelativeRotate(
220         const MT_Matrix3x3& rot,
221         bool local
222 ){
223         m_localRotation = m_localRotation * (
224         local ? 
225                 rot 
226         :
227         (GetWorldOrientation().inverse() * rot * GetWorldOrientation()));
228 }
229
230         void 
231 SG_Spatial::
232 SetLocalOrientation(const MT_Matrix3x3& rot)
233 {
234         m_localRotation = rot;
235 }
236
237
238
239         void                            
240 SG_Spatial::
241 SetWorldOrientation(
242         const MT_Matrix3x3& rot
243 ) {
244         m_worldRotation = rot;
245 }
246
247 const 
248         MT_Point3&
249 SG_Spatial::
250 GetLocalPosition(
251 ) const {
252          return m_localPosition;
253 }
254
255 const 
256         MT_Matrix3x3&
257 SG_Spatial::
258 GetLocalOrientation(
259 ) const {
260         return m_localRotation;
261 }
262
263 const 
264         MT_Vector3&     
265 SG_Spatial::
266 GetLocalScale(
267 ) const{
268         return m_localScaling;
269 }
270
271
272 const 
273         MT_Point3&
274 SG_Spatial::
275 GetWorldPosition(
276 ) const {
277         return m_worldPosition;
278 }
279
280 const 
281         MT_Matrix3x3&   
282 SG_Spatial::
283 GetWorldOrientation(
284 ) const {
285         return m_worldRotation;
286 }
287
288 const 
289         MT_Vector3&     
290 SG_Spatial::
291 GetWorldScaling(
292 ) const {
293         return m_worldScaling;
294 }
295
296 SG_BBox& SG_Spatial::BBox()
297 {
298         return m_bbox;
299 }
300
301 void SG_Spatial::SetBBox(SG_BBox& bbox)
302 {
303         m_bbox = bbox;
304 }
305
306 MT_Transform SG_Spatial::GetWorldTransform() const
307 {
308         return MT_Transform(m_worldPosition, 
309                 m_worldRotation.scaled(
310                 m_worldScaling[0], m_worldScaling[1], m_worldScaling[2]));
311 }
312
313 bool SG_Spatial::inside(const MT_Point3 &point) const
314 {
315         MT_Scalar radius = m_worldScaling[m_worldScaling.closestAxis()]*m_radius;
316         return (m_worldPosition.distance2(point) <= radius*radius) ?
317                 m_bbox.transform(GetWorldTransform()).inside(point) :
318                 false;
319 }
320
321 void SG_Spatial::getBBox(MT_Point3 *box) const
322 {
323         m_bbox.get(box, GetWorldTransform());
324 }
325
326 void SG_Spatial::getAABBox(MT_Point3 *box) const
327 {
328         m_bbox.getaa(box, GetWorldTransform());
329 }
330