Initial revision
[blender.git] / source / gameengine / Physics / Sumo / Fuzzics / src / SM_Scene.cpp
1 /**
2  * $Id$
3  * Copyright (C) 2001 NaN Technologies B.V.
4  * The physics scene.
5  */
6
7 #ifdef WIN32
8 #pragma warning(disable : 4786)  // shut off 255 char limit debug template warning
9 #endif
10
11 #include "SM_Scene.h"
12 #include "SM_Object.h"
13 #include "SM_FhObject.h"
14
15 #include <algorithm>
16
17 void SM_Scene::add(SM_Object& object) {
18         object.calcXform();
19         m_objectList.push_back(&object);
20         DT_AddObject(m_scene, object.getObjectHandle());
21         if (object.isDynamic()) {
22                 DT_SetObjectResponse(m_respTable, object.getObjectHandle(),
23                                                          SM_Object::boing, DT_SIMPLE_RESPONSE, this);
24         }
25
26         if (object.getDynamicParent()) {
27                 DT_SetPairResponse(m_respTable, object.getObjectHandle(),
28                                                    object.getDynamicParent()->getObjectHandle(),
29                                                    0, DT_NO_RESPONSE, 0);
30         }
31         SM_FhObject *fh_object = object.getFhObject();
32
33         if (fh_object) {
34                 DT_AddObject(m_scene, fh_object->getObjectHandle());
35                 DT_SetObjectResponse(m_respTable, fh_object->getObjectHandle(),
36                                                          SM_FhObject::ray_hit, DT_SIMPLE_RESPONSE, this);
37         }
38 }       
39
40 void SM_Scene::remove(SM_Object& object) {      
41         T_ObjectList::iterator i =
42                 std::find(m_objectList.begin(), m_objectList.end(), &object);
43         if (!(i == m_objectList.end()))
44         {
45                 std::swap(*i, m_objectList.back());
46                 m_objectList.pop_back();
47                 DT_RemoveObject(m_scene, object.getObjectHandle());
48                 if (object.isDynamic()) {
49                         DT_ClearObjectResponse(m_respTable, object.getObjectHandle());
50                 }
51                 
52                 if (object.getDynamicParent()) {
53                         DT_ClearPairResponse(m_respTable, object.getObjectHandle(),
54                                                                  object.getDynamicParent()->getObjectHandle());
55                 }
56
57                 SM_FhObject *fh_object = object.getFhObject();
58                 
59                 if (fh_object) {
60                         DT_RemoveObject(m_scene, fh_object->getObjectHandle());
61                         DT_ClearObjectResponse(m_respTable,
62                                                                    fh_object->getObjectHandle());
63                 }
64         } 
65         else {
66                 // tried to remove an object that is not in the scene
67                 //assert(false);
68         }
69 }       
70
71 void SM_Scene::proceed(MT_Scalar timeStep, MT_Scalar subSampling) {
72         // Don't waste time...but it's OK to spill a little.
73         if (timeStep < 0.001)
74                 return;
75
76         // Divide the timeStep into a number of subsamples of size roughly 
77         // equal to subSampling (might be a little smaller).
78         int num_samples = (int)ceil(timeStep / subSampling);
79
80
81         MT_Scalar subStep = timeStep / num_samples;
82         T_ObjectList::iterator i;
83
84         // Apply a forcefield (such as gravity)
85         for (i = m_objectList.begin(); i != m_objectList.end(); ++i) {
86                 (*i)->applyForceField(m_forceField);
87         }
88         
89         // Do the integration steps per object.
90         int step;
91         for (step = 0; step != num_samples; ++step) {
92
93                 for (i = m_objectList.begin(); i != m_objectList.end(); ++i) {
94                         (*i)->integrateForces(subStep);
95                 }
96
97                 // And second we update the object positions by performing
98                 // an integration step for each object
99                 for (i = m_objectList.begin(); i != m_objectList.end(); ++i) {
100                         (*i)->integrateMomentum(subStep);
101                 }
102 #if 0
103                 // I changed the order of the next 2 statements.
104                 // Originally objects were first integrated with a call
105                 // to proceed(). However if external objects were 
106                 // directly manipulating the velocities etc of physics 
107                 // objects then the physics environment would not be able 
108                 // to react before object positions were updated. --- Laurence.
109
110                 // So now first we let the physics scene respond to 
111                 // new forces, velocities set externally. 
112 #endif
113                 // The collsion and friction impulses are computed here. 
114                 DT_Test(m_scene, m_respTable);
115
116         }
117
118
119         // clear the user set velocities.
120 #if 0
121         clearObjectCombinedVelocities();
122 #endif
123         // Finish this timestep by saving al state information for the next
124         // timestep and clearing the accumulated forces. 
125
126         for (i = m_objectList.begin(); i != m_objectList.end(); ++i) {
127                 (*i)->proceedKinematic(timeStep);
128                 (*i)->saveReactionForce(timeStep);
129                 (*i)->clearForce();
130         }
131         
132         // For each pair of object that collided, call the corresponding callback.
133         // Additional collisions of a pair within the same time step are ignored.
134
135         if (m_secondaryRespTable) {
136                 T_PairList::iterator p;
137                 for (p = m_pairList.begin(); p != m_pairList.end(); ++p) {
138                         DT_CallResponse(m_secondaryRespTable, 
139                                                         (*p).first->getObjectHandle(), 
140                                                         (*p).second->getObjectHandle(), 
141                                                         0);
142                 }
143         }
144         
145         clearPairs();
146 }
147
148 SM_Object *SM_Scene::rayTest(void *ignore_client, 
149                                                          const MT_Point3& from, const MT_Point3& to, 
150                                                          MT_Point3& result, MT_Vector3& normal) const {
151         MT_Point3 local; 
152  
153         SM_Object *hit_object = (SM_Object *) 
154                 DT_RayTest(m_scene, ignore_client, from.getValue(), to.getValue(),
155                                    local.getValue(), normal.getValue());
156
157         if (hit_object) {
158                 result = hit_object->getWorldCoord(local);
159         }
160
161         return hit_object;
162 }
163
164 void SM_Scene::clearObjectCombinedVelocities() {
165
166         T_ObjectList::iterator i;
167
168         for (i = m_objectList.begin(); i != m_objectList.end(); ++i) {
169
170                 (*i)->clearCombinedVelocities();
171
172         }
173
174 }       
175
176
177
178
179