1 /***************************************************************************
2 movingobject.cpp - Moving object class
3 -------------------
4 begin : Wed Dec 4 2002
5 copyright : (C) 2002 by CJP
6 email : cornware-cjp@users.sourceforge.net
7 ***************************************************************************/
8
9 /***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 ***************************************************************************/
17 #include <cstdio>
18
19 #include "movingobject.h"
20 #include "movobjinput.h"
21 #include "physics.h"
22
CMovingObject(CDataManager * manager)23 CMovingObject::CMovingObject(CDataManager *manager) : CDataObject(manager, CDataObject::eMovingObject)
24 {
25 //default mass:
26 m_InvMass = 1.0;
27
28 m_InputData = new CMovObjInput;
29
30 m_LastNetworkUpdateTime = -1000.0; //first update will always come through this
31
32 m_Ground.nor = CVector(0,0,0);
33 }
34
~CMovingObject()35 CMovingObject::~CMovingObject()
36 {
37 unload();
38 delete m_InputData; //I guess this will happen for all CMovingObject-derived classes
39 }
40
load(const CString & filename,const CParamList & list)41 bool CMovingObject::load(const CString &filename, const CParamList &list)
42 {
43 CDataObject::load(filename, list);
44
45 m_MovObjID = list.getValue("ID", "0").toInt();
46 m_InputData->m_MovObjID = m_MovObjID;
47
48 return true;
49 }
50
unload()51 void CMovingObject::unload()
52 {
53 //for(unsigned int i=0; i < m_Bodies.size(); i++)
54 // m_Bodies[i].destroyODE();
55 m_Bodies.clear();
56
57 m_Sounds.clear();
58 m_Textures.clear();
59
60 CDataObject::unload();
61 }
62
addForce(CVector F)63 void CMovingObject::addForce(CVector F)
64 {
65 m_Ftot += F;
66 }
67
addTorque(CVector M)68 void CMovingObject::addTorque(CVector M)
69 {
70 m_Mtot += M;
71 }
72
addForceAt(CVector F,CVector pos)73 void CMovingObject::addForceAt(CVector F, CVector pos)
74 {
75 m_Ftot += F;
76 m_Mtot += F.crossProduct(pos);
77
78 /*
79 CVector Madd = F.crossProduct(pos);
80 printf(" F = %s\n", CString(F).c_str());
81 printf(" p = %s\n", CString(pos).c_str());
82 printf(" M = %s\n", CString(Madd).c_str());
83 */
84 }
85
update(CPhysics * simulator,float dt)86 void CMovingObject::update(CPhysics *simulator, float dt)
87 {
88 //Integration step of the simulation:
89
90 //printf("Ftot = (%s) kN\n", CString(m_Ftot/1000.0).c_str());
91
92 //linear things:
93 CVector accel = m_Ftot * m_InvMass;
94
95 m_Position += (m_Velocity + 0.5*dt*accel)*dt;
96 m_Velocity += dt*accel;
97
98 //angular things:
99
100 //inverse inertia tensor, corrected for body orientation
101 CMatrix invInertia = m_OrientationMatrix.transpose() * m_InvInertia * m_OrientationMatrix;
102
103 CVector angaccel = invInertia * m_Mtot;
104
105 CMatrix dM;
106 dM.setRotation((m_AngularVelocity + 0.5*dt*angaccel)*dt);
107 m_OrientationMatrix *= dM;
108 m_AngularVelocity += dt*angaccel;
109
110
111 //Place the bodies:
112 placeBodies();
113
114 //Reset the forces:
115 m_Ftot = CVector (0,0,0);
116 m_Mtot = CVector (0,0,0);
117 }
118
determineGroundPlane(CPhysics * simulator)119 void CMovingObject::determineGroundPlane(CPhysics *simulator)
120 {
121 //TODO: some good default for non-car moving objects
122 }
123
correctCollisions()124 void CMovingObject::correctCollisions()
125 {
126 for(unsigned int c=0; c < m_SimCollisions.size(); c++)
127 {
128 CCollisionData col = m_SimCollisions[c];
129
130 //printf("depth = %.3f\n", col.depth);
131 CVector dr = col.nor * col.depth;
132
133 //correct the position
134 m_Position += dr;
135
136 //set the collision velocity to zero
137 m_Velocity -= col.vmean;
138 float radcomp = m_Velocity.dotProduct(col.nor);
139 if(radcomp < 0.0)
140 m_Velocity -= radcomp * col.nor;
141 m_Velocity += col.vmean;
142 }
143 }
144
getData(CBinBuffer & b) const145 CBinBuffer &CMovingObject::getData(CBinBuffer &b) const
146 {
147 b += (Uint8)m_MovObjID;
148
149 b.addFloat32(m_LastUpdateTime, 0.005); //more accurate than 1/100 sec
150
151 CVector
152 p = m_Position,
153 o = m_OrientationMatrix.getRotation(),
154 v = m_Velocity,
155 w = m_AngularVelocity;
156
157 b.addVector32(p, 0.001);
158 b.addVector16(o, 0.0002);
159 b.addVector16(v, 0.01);
160 b.addVector16(w, 0.001);
161
162 return b;
163 }
164
setData(const CBinBuffer & b,unsigned int & pos)165 bool CMovingObject::setData(const CBinBuffer &b, unsigned int &pos)
166 {
167 Uint8 ID = b.getUint8(pos);
168 if(ID != m_MovObjID) return false; //wrong delivery, in some way
169
170 float time = b.getFloat32(pos, 0.005);
171 //printf("Received package: sendTime = %.2f\n", time);
172 if(time < m_LastNetworkUpdateTime)
173 {
174 printf("Old package: time %.2f < %.2f\n", time, m_LastNetworkUpdateTime);
175 return false; //it was an old package
176 }
177 if(time > theWorld->m_LastTime + 3.0)
178 {
179 printf("Too late package: time %.2f > %.2f + 3.0\n", time, theWorld->m_LastTime);
180 return false; //probably a package from a previous game session
181 }
182
183 m_LastNetworkUpdateTime = time;
184 m_LastUpdateTime = theWorld->m_LastTime;
185
186 //TODO: correct game time for average lag time
187
188 CVector
189 p = b.getVector32(pos, 0.001),
190 o = b.getVector16(pos, 0.0002),
191 v = b.getVector16(pos, 0.01),
192 w = b.getVector16(pos, 0.001);
193
194 /*
195 A little hack:
196 We do not REALLY set the position to the position in the message.
197 Instead, we mix it with the current position.
198 This damps out "synchronisation errors"
199 */
200
201 //no damping at low speeds
202 float dampFactor = v.abs2() / (10.0 + v.abs2());
203
204 //lower damping at higher differences in speed (e.g. collisions)
205 float vdif2 = (v - m_Velocity).abs2();
206 dampFactor *= 10.0 / (10.0 + vdif2);
207
208 if(dampFactor > 0.95) dampFactor = 0.95; //not too much damping
209 if(!(dampFactor >= 0.0 && dampFactor <= 1.0)) dampFactor = 0.0; //you never know
210 //printf("dampFactor = %s\n", CString(dampFactor).c_str());
211
212 //some damping to correct for "synchronisation noise"
213 //We only do damping in the direction of v
214 CVector vdir = v.normal();
215 CVector p_vdir = p.component(vdir);
216 CVector p_ortho = p - p_vdir;
217 m_Position = p_ortho + (1.0 - dampFactor) * p_vdir + dampFactor * m_Position.component(vdir);
218
219 m_OrientationMatrix.setRotation(o);
220 m_Velocity = v;
221 m_AngularVelocity = w;
222
223 return true;
224 }
225