remove $Id: tags after discussion on the mailign list: http://markmail.org/message...
[blender.git] / source / gameengine / SceneGraph / SG_Spatial.cpp
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): none yet.
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file gameengine/SceneGraph/SG_Spatial.cpp
29  *  \ingroup bgesg
30  */
31
32
33 #include "SG_Node.h"
34 #include "SG_Spatial.h"
35 #include "SG_Controller.h"
36 #include "SG_ParentRelation.h"
37
38 SG_Spatial::
39 SG_Spatial(
40         void* clientobj,
41         void* clientinfo,
42         SG_Callbacks& callbacks
43 ): 
44
45         SG_IObject(clientobj,clientinfo,callbacks),
46         m_localPosition(0.0,0.0,0.0),
47         m_localRotation(1.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,1.0),
48         m_localScaling(1.f,1.f,1.f),
49         
50         m_worldPosition(0.0,0.0,0.0),
51         m_worldRotation(1.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,1.0),
52         m_worldScaling(1.f,1.f,1.f),
53
54         m_parent_relation (NULL),
55         
56         m_bbox(MT_Point3(-1.0, -1.0, -1.0), MT_Point3(1.0, 1.0, 1.0)),
57         m_radius(1.0),
58         m_modified(false),
59         m_ogldirty(false)
60 {
61 }
62
63 SG_Spatial::
64 SG_Spatial(
65         const SG_Spatial& other
66 ) : 
67         SG_IObject(other),
68         m_localPosition(other.m_localPosition),
69         m_localRotation(other.m_localRotation),
70         m_localScaling(other.m_localScaling),
71         
72         m_worldPosition(other.m_worldPosition),
73         m_worldRotation(other.m_worldRotation),
74         m_worldScaling(other.m_worldScaling),
75         
76         m_parent_relation(NULL),
77         
78         m_bbox(other.m_bbox),
79         m_radius(other.m_radius),
80         m_modified(false),
81         m_ogldirty(false)
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         SetModified();
101 }
102
103
104 /**
105  * Update Spatial Data.
106  * Calculates WorldTransform., (either doing itsself or using the linked SGControllers)
107  */
108
109
110         bool
111 SG_Spatial::
112 UpdateSpatialData(
113                 const SG_Spatial *parent,
114                 double time,
115                 bool& parentUpdated
116                 ){
117         bool bComputesWorldTransform = false;
118
119         // update spatial controllers
120
121         SGControllerList::iterator cit = GetSGControllerList().begin();
122         SGControllerList::const_iterator c_end = GetSGControllerList().end();
123
124         for (;cit!=c_end;++cit)
125         {
126                 if ((*cit)->Update(time))
127                         bComputesWorldTransform = true;
128         }
129
130         // If none of the objects updated our values then we ask the
131         // parent_relation object owned by this class to update
132         // our world coordinates.
133
134         if (!bComputesWorldTransform)
135                 bComputesWorldTransform = ComputeWorldTransforms(parent, parentUpdated);
136
137         return bComputesWorldTransform;
138 }
139
140 /**
141  * Position and translation methods
142  */
143
144
145         void 
146 SG_Spatial::
147 RelativeTranslate(
148         const MT_Vector3& trans,
149         const SG_Spatial *parent,
150         bool local
151 ){
152         if (local) {
153                         m_localPosition += m_localRotation * trans;
154         } else {
155                 if (parent) {
156                         m_localPosition += trans * parent->GetWorldOrientation();
157                 } else {
158                         m_localPosition += trans;
159                 }
160         }
161         SetModified();
162 }       
163         
164
165 /**
166  * Scaling methods.
167  */ 
168
169
170 /**
171  * Orientation and rotation methods.
172  */
173
174
175         void 
176 SG_Spatial::
177 RelativeRotate(
178         const MT_Matrix3x3& rot,
179         bool local
180 ){
181         m_localRotation = m_localRotation * (
182         local ? 
183                 rot 
184         :
185         (GetWorldOrientation().inverse() * rot * GetWorldOrientation()));
186         SetModified();
187 }
188
189
190
191 MT_Transform SG_Spatial::GetWorldTransform() const
192 {
193         return MT_Transform(m_worldPosition, 
194                 m_worldRotation.scaled(
195                 m_worldScaling[0], m_worldScaling[1], m_worldScaling[2]));
196 }
197
198 bool SG_Spatial::inside(const MT_Point3 &point) const
199 {
200         MT_Scalar radius = m_worldScaling[m_worldScaling.closestAxis()]*m_radius;
201         return (m_worldPosition.distance2(point) <= radius*radius) ?
202                 m_bbox.transform(GetWorldTransform()).inside(point) :
203                 false;
204 }
205
206 void SG_Spatial::getBBox(MT_Point3 *box) const
207 {
208         m_bbox.get(box, GetWorldTransform());
209 }
210
211 void SG_Spatial::getAABBox(MT_Point3 *box) const
212 {
213         m_bbox.getaa(box, GetWorldTransform());
214 }
215