aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Physics')
-rw-r--r--OpenSim/Region/Physics/OdePlugin/ODECharacter.cs477
-rw-r--r--OpenSim/Region/Physics/OdePlugin/ODEPrim.cs686
-rw-r--r--OpenSim/Region/Physics/OdePlugin/OdePlugin.cs1142
3 files changed, 1166 insertions, 1139 deletions
diff --git a/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs b/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs
new file mode 100644
index 0000000..cda6af2
--- /dev/null
+++ b/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs
@@ -0,0 +1,477 @@
1using System;
2using System.Collections.Generic;
3using Axiom.Math;
4using Ode.NET;
5using OpenSim.Framework;
6using OpenSim.Region.Physics.Manager;
7
8namespace OpenSim.Region.Physics.OdePlugin
9{
10 public class OdeCharacter : PhysicsActor
11 {
12 private PhysicsVector _position;
13 private d.Vector3 _zeroPosition;
14 private bool _zeroFlag = false;
15 private bool m_lastUpdateSent = false;
16 private PhysicsVector _velocity;
17 private PhysicsVector _target_velocity;
18 private PhysicsVector _acceleration;
19 private PhysicsVector m_rotationalVelocity;
20 private static float PID_D = 3020.0f;
21 private static float PID_P = 7000.0f;
22 private static float POSTURE_SERVO = 10000.0f;
23 public static float CAPSULE_RADIUS = 0.5f;
24 public float CAPSULE_LENGTH = 0.79f;
25 private bool flying = false;
26 private bool m_iscolliding = false;
27 private bool m_iscollidingGround = false;
28 private bool m_wascolliding = false;
29 private bool m_wascollidingGround = false;
30 private bool m_alwaysRun = false;
31 private bool m_hackSentFall = false;
32 private bool m_hackSentFly = false;
33 private string m_name = "";
34
35 private bool[] m_colliderarr = new bool[11];
36 private bool[] m_colliderGroundarr = new bool[11];
37
38
39 private bool jumping = false;
40 //private float gravityAccel;
41 public IntPtr Body;
42 private OdeScene _parent_scene;
43 public IntPtr Shell;
44 public d.Mass ShellMass;
45 public bool collidelock = false;
46
47 public OdeCharacter(String avName, OdeScene parent_scene, PhysicsVector pos)
48 {
49 _velocity = new PhysicsVector();
50 _target_velocity = new PhysicsVector();
51 _position = pos;
52 _acceleration = new PhysicsVector();
53 _parent_scene = parent_scene;
54
55 for (int i = 0; i < 11; i++)
56 {
57 m_colliderarr[i] = false;
58 }
59
60 lock (OdeScene.OdeLock)
61 {
62
63 Shell = d.CreateCapsule(parent_scene.space, CAPSULE_RADIUS, CAPSULE_LENGTH);
64 d.MassSetCapsule(out ShellMass, 50.0f, 3, 0.4f, 1.0f);
65 Body = d.BodyCreate(parent_scene.world);
66 d.BodySetMass(Body, ref ShellMass);
67 d.BodySetPosition(Body, pos.X, pos.Y, pos.Z);
68 d.GeomSetBody(Shell, Body);
69 }
70 m_name = avName;
71 parent_scene.geom_name_map[Shell] = avName;
72 parent_scene.actor_name_map[Shell] = (PhysicsActor)this;
73 }
74 public override int PhysicsActorType
75 {
76 get { return (int)ActorTypes.Agent; }
77 set { return; }
78 }
79 public override bool SetAlwaysRun
80 {
81 get { return m_alwaysRun; }
82 set { m_alwaysRun = value; }
83 }
84 public override bool IsPhysical
85 {
86 get { return false; }
87 set { return; }
88 }
89 public override bool ThrottleUpdates
90 {
91 get { return false; }
92 set { return; }
93 }
94 public override bool Flying
95 {
96 get { return flying; }
97 set { flying = value; }
98 }
99 public override bool IsColliding
100 {
101
102 get { return m_iscolliding; }
103 set
104 {
105 int i;
106 int truecount = 0;
107 int falsecount = 0;
108
109 if (m_colliderarr.Length >= 10)
110 {
111 for (i = 0; i < 10; i++)
112 {
113 m_colliderarr[i] = m_colliderarr[i + 1];
114 }
115 }
116 m_colliderarr[10] = value;
117
118 for (i = 0; i < 11; i++)
119 {
120 if (m_colliderarr[i])
121 {
122 truecount++;
123 }
124 else
125 {
126 falsecount++;
127 }
128 }
129
130 // Equal truecounts and false counts means we're colliding with something.
131
132 if (falsecount > 1.2 * truecount)
133 {
134 m_iscolliding = false;
135 }
136 else
137 {
138 m_iscolliding = true;
139 }
140 if (m_wascolliding != m_iscolliding)
141 {
142 base.SendCollisionUpdate(new CollisionEventUpdate());
143 }
144 m_wascolliding = m_iscolliding;
145 }
146 }
147 public override bool CollidingGround
148 {
149 get { return m_iscollidingGround; }
150 set
151 {
152 int i;
153 int truecount = 0;
154 int falsecount = 0;
155
156 if (m_colliderGroundarr.Length >= 10)
157 {
158 for (i = 0; i < 10; i++)
159 {
160 m_colliderGroundarr[i] = m_colliderGroundarr[i + 1];
161 }
162 }
163 m_colliderGroundarr[10] = value;
164
165 for (i = 0; i < 11; i++)
166 {
167 if (m_colliderGroundarr[i])
168 {
169 truecount++;
170 }
171 else
172 {
173 falsecount++;
174 }
175 }
176
177 // Equal truecounts and false counts means we're colliding with something.
178
179 if (falsecount > 1.2 * truecount)
180 {
181 m_iscollidingGround = false;
182 }
183 else
184 {
185 m_iscollidingGround = true;
186 }
187 if (m_wascollidingGround != m_iscollidingGround)
188 {
189 //base.SendCollisionUpdate(new CollisionEventUpdate());
190 }
191 m_wascollidingGround = m_iscollidingGround;
192 }
193 }
194 public override bool CollidingObj
195 {
196 get { return false; }
197 set { return; }
198 }
199
200 public override PhysicsVector Position
201 {
202 get { return _position; }
203 set
204 {
205 lock (OdeScene.OdeLock)
206 {
207 d.BodySetPosition(Body, value.X, value.Y, value.Z);
208 _position = value;
209 }
210 }
211 }
212 public override PhysicsVector RotationalVelocity
213 {
214 get { return m_rotationalVelocity; }
215 set { m_rotationalVelocity = value; }
216 }
217 public override PhysicsVector Size
218 {
219 get { return new PhysicsVector(CAPSULE_RADIUS * 2, CAPSULE_RADIUS * 2, CAPSULE_LENGTH); }
220 set
221 {
222 lock (OdeScene.OdeLock)
223 {
224 PhysicsVector SetSize = value;
225 float prevCapsule = CAPSULE_LENGTH;
226 float capsuleradius = CAPSULE_RADIUS;
227 capsuleradius = 0.2f;
228
229 CAPSULE_LENGTH = (SetSize.Z - ((SetSize.Z * 0.43f))); // subtract 43% of the size
230 d.BodyDestroy(Body);
231 d.GeomDestroy(Shell);
232 //OpenSim.Framework.Console.MainLog.Instance.Verbose("PHYSICS", "Set Avatar Height To: " + (CAPSULE_RADIUS + CAPSULE_LENGTH));
233 Shell = d.CreateCapsule(_parent_scene.space, capsuleradius, CAPSULE_LENGTH);
234 d.MassSetCapsule(out ShellMass, 50.0f, 3, CAPSULE_RADIUS, CAPSULE_LENGTH);
235 Body = d.BodyCreate(_parent_scene.world);
236 d.BodySetMass(Body, ref ShellMass);
237 d.BodySetPosition(Body, _position.X, _position.Y, _position.Z + Math.Abs(CAPSULE_LENGTH - prevCapsule));
238 d.GeomSetBody(Shell, Body);
239 }
240 _parent_scene.geom_name_map[Shell] = m_name;
241 _parent_scene.actor_name_map[Shell] = (PhysicsActor)this;
242 }
243 }
244
245 public override PrimitiveBaseShape Shape
246 {
247 set
248 {
249 return;
250 }
251 }
252
253 public override PhysicsVector Velocity
254 {
255 get { return _velocity; }
256 set { _target_velocity = value; }
257 }
258
259 public override bool Kinematic
260 {
261 get { return false; }
262 set { }
263 }
264
265 public override Quaternion Orientation
266 {
267 get { return Quaternion.Identity; }
268 set { }
269 }
270
271 public override PhysicsVector Acceleration
272 {
273 get { return _acceleration; }
274 }
275
276 public void SetAcceleration(PhysicsVector accel)
277 {
278 _acceleration = accel;
279 }
280
281 public override void AddForce(PhysicsVector force)
282 {
283
284 _target_velocity.X += force.X;
285 _target_velocity.Y += force.Y;
286 _target_velocity.Z += force.Z;
287
288 //m_lastUpdateSent = false;
289 }
290 public void doForce(PhysicsVector force)
291 {
292 if (!collidelock)
293 {
294 d.BodyAddForce(Body, force.X, force.Y, force.Z);
295
296 // ok -- let's stand up straight!
297 d.Vector3 feet;
298 d.Vector3 head;
299 d.BodyGetRelPointPos(Body, 0.0f, 0.0f, -1.0f, out feet);
300 d.BodyGetRelPointPos(Body, 0.0f, 0.0f, 1.0f, out head);
301 float posture = head.Z - feet.Z;
302
303 // restoring force proportional to lack of posture:
304 float servo = (2.5f - posture) * POSTURE_SERVO;
305 d.BodyAddForceAtRelPos(Body, 0.0f, 0.0f, servo, 0.0f, 0.0f, 1.0f);
306 d.BodyAddForceAtRelPos(Body, 0.0f, 0.0f, -servo, 0.0f, 0.0f, -1.0f);
307 //m_lastUpdateSent = false;
308
309 }
310
311 }
312 public override void SetMomentum(PhysicsVector momentum)
313 {
314
315 }
316
317 public void Move(float timeStep)
318 {
319 // no lock; for now it's only called from within Simulate()
320 PhysicsVector vec = new PhysicsVector();
321 d.Vector3 vel = d.BodyGetLinearVel(Body);
322 float movementdivisor = 1f;
323
324 if (!m_alwaysRun)
325 {
326 movementdivisor = 1.3f;
327 }
328 else
329 {
330 movementdivisor = 0.8f;
331
332 }
333
334 // if velocity is zero, use position control; otherwise, velocity control
335 if (_target_velocity.X == 0.0f && _target_velocity.Y == 0.0f && _target_velocity.Z == 0.0f && m_iscolliding)
336 {
337 // keep track of where we stopped. No more slippin' & slidin'
338 if (!_zeroFlag)
339 {
340 _zeroFlag = true;
341 _zeroPosition = d.BodyGetPosition(Body);
342 }
343 d.Vector3 pos = d.BodyGetPosition(Body);
344 vec.X = (_target_velocity.X - vel.X) * PID_D + (_zeroPosition.X - pos.X) * PID_P;
345 vec.Y = (_target_velocity.Y - vel.Y) * PID_D + (_zeroPosition.Y - pos.Y) * PID_P;
346 if (flying)
347 {
348 vec.Z = (_target_velocity.Z - vel.Z) * PID_D + (_zeroPosition.Z - pos.Z) * PID_P;
349 }
350 }
351 else
352 {
353
354 _zeroFlag = false;
355 if (m_iscolliding || flying)
356 {
357
358 vec.X = ((_target_velocity.X / movementdivisor) - vel.X) * PID_D;
359 vec.Y = ((_target_velocity.Y / movementdivisor) - vel.Y) * PID_D;
360 }
361 if (m_iscolliding && !flying && _target_velocity.Z > 0.0f)
362 {
363 d.Vector3 pos = d.BodyGetPosition(Body);
364 vec.Z = (_target_velocity.Z - vel.Z) * PID_D + (_zeroPosition.Z - pos.Z) * PID_P;
365 if (_target_velocity.X > 0)
366 {
367 vec.X = ((_target_velocity.X - vel.X) / 1.2f) * PID_D;
368 }
369 if (_target_velocity.Y > 0)
370 {
371 vec.Y = ((_target_velocity.Y - vel.Y) / 1.2f) * PID_D;
372 }
373 }
374 else if (!m_iscolliding && !flying)
375 {
376 d.Vector3 pos = d.BodyGetPosition(Body);
377 if (_target_velocity.X > 0)
378 {
379 vec.X = ((_target_velocity.X - vel.X) / 1.2f) * PID_D;
380 }
381 if (_target_velocity.Y > 0)
382 {
383 vec.Y = ((_target_velocity.Y - vel.Y) / 1.2f) * PID_D;
384 }
385
386 }
387
388
389 if (flying)
390 {
391 vec.Z = (_target_velocity.Z - vel.Z) * PID_D;
392 }
393 }
394 if (flying)
395 {
396 vec.Z += 10.0f;
397 }
398
399
400 doForce(vec);
401 }
402
403 public void UpdatePositionAndVelocity()
404 {
405 // no lock; called from Simulate() -- if you call this from elsewhere, gotta lock or do Monitor.Enter/Exit!
406 d.Vector3 vec = d.BodyGetPosition(Body);
407
408 // kluge to keep things in bounds. ODE lets dead avatars drift away (they should be removed!)
409 if (vec.X < 0.0f) vec.X = 0.0f;
410 if (vec.Y < 0.0f) vec.Y = 0.0f;
411 if (vec.X > 255.95f) vec.X = 255.95f;
412 if (vec.Y > 255.95f) vec.Y = 255.95f;
413
414 _position.X = vec.X;
415 _position.Y = vec.Y;
416 _position.Z = vec.Z;
417
418 if (_zeroFlag)
419 {
420 _velocity.X = 0.0f;
421 _velocity.Y = 0.0f;
422 _velocity.Z = 0.0f;
423 if (!m_lastUpdateSent)
424 {
425 m_lastUpdateSent = true;
426 base.RequestPhysicsterseUpdate();
427 string primScenAvatarIn = _parent_scene.whichspaceamIin(_position);
428 int[] arrayitem = _parent_scene.calculateSpaceArrayItemFromPos(_position);
429 if (primScenAvatarIn == "0")
430 {
431 OpenSim.Framework.Console.MainLog.Instance.Verbose("Physics", "Avatar " + m_name + " in space with no prim. Arr:':" + arrayitem[0].ToString() + "," + arrayitem[1].ToString());
432 }
433 else
434 {
435 OpenSim.Framework.Console.MainLog.Instance.Verbose("Physics", "Avatar " + m_name + " in Prim space':" + primScenAvatarIn + ". Arr:" + arrayitem[0].ToString() + "," + arrayitem[1].ToString());
436 }
437
438 }
439 }
440 else
441 {
442 m_lastUpdateSent = false;
443 vec = d.BodyGetLinearVel(Body);
444 _velocity.X = (vec.X);
445 _velocity.Y = (vec.Y);
446
447 _velocity.Z = (vec.Z);
448 if (_velocity.Z < -6 && !m_hackSentFall)
449 {
450 m_hackSentFall = true;
451 base.SendCollisionUpdate(new CollisionEventUpdate());
452 }
453 else if (flying && !m_hackSentFly)
454 {
455 //m_hackSentFly = true;
456 //base.SendCollisionUpdate(new CollisionEventUpdate());
457 }
458 else
459 {
460 m_hackSentFly = false;
461 m_hackSentFall = false;
462 }
463 }
464 }
465
466 public void Destroy()
467 {
468 lock (OdeScene.OdeLock)
469 {
470 d.GeomDestroy(Shell);
471 _parent_scene.geom_name_map.Remove(Shell);
472 d.BodyDestroy(Body);
473 }
474 }
475 }
476
477}
diff --git a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs
new file mode 100644
index 0000000..f423e82
--- /dev/null
+++ b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs
@@ -0,0 +1,686 @@
1using System;
2using System.Collections.Generic;
3using Axiom.Math;
4using Ode.NET;
5using OpenSim.Framework;
6using OpenSim.Region.Physics.Manager;
7
8namespace OpenSim.Region.Physics.OdePlugin
9{
10
11 public class OdePrim : PhysicsActor
12 {
13 public PhysicsVector _position;
14 private PhysicsVector _velocity;
15 private PhysicsVector m_lastVelocity = new PhysicsVector(0.0f, 0.0f, 0.0f);
16 private PhysicsVector m_lastposition = new PhysicsVector(0.0f, 0.0f, 0.0f);
17 private PhysicsVector m_rotationalVelocity;
18 private PhysicsVector _size;
19 private PhysicsVector _acceleration;
20 private Quaternion _orientation;
21 private PhysicsVector m_taintposition;
22 private PhysicsVector m_taintsize;
23 private Quaternion m_taintrot;
24 private bool m_taintshape = false;
25 private bool m_taintPhysics = false;
26 public bool m_taintremove = false;
27
28 private IMesh _mesh;
29 private PrimitiveBaseShape _pbs;
30 private OdeScene _parent_scene;
31 public IntPtr m_targetSpace = (IntPtr)0;
32 public IntPtr prim_geom;
33 public IntPtr _triMeshData;
34 private bool iscolliding = false;
35 private bool m_isphysical = false;
36 private bool m_throttleUpdates = false;
37 private int throttleCounter = 0;
38 public bool outofBounds = false;
39
40 public bool _zeroFlag = false;
41 private bool m_lastUpdateSent = false;
42
43 public IntPtr Body = (IntPtr)0;
44 private String m_primName;
45 private PhysicsVector _target_velocity;
46 public d.Mass pMass;
47 private const float MassMultiplier = 150f; // Ref: Water: 1000kg.. this iset to 500
48 private int debugcounter = 0;
49
50
51 public OdePrim(String primName, OdeScene parent_scene, IntPtr targetSpace, PhysicsVector pos, PhysicsVector size,
52 Quaternion rotation, IMesh mesh, PrimitiveBaseShape pbs, bool pisPhysical)
53 {
54
55
56 _velocity = new PhysicsVector();
57 _position = pos;
58 m_taintposition = pos;
59 if (_position.X > 257)
60 {
61 _position.X = 257;
62 }
63 if (_position.X < 0)
64 {
65 _position.X = 0;
66 }
67 if (_position.Y > 257)
68 {
69 _position.Y = 257;
70 }
71 if (_position.Y < 0)
72 {
73 _position.Y = 0;
74 }
75
76 _size = size;
77 m_taintsize = _size;
78 _acceleration = new PhysicsVector();
79 m_rotationalVelocity = PhysicsVector.Zero;
80 _orientation = rotation;
81 m_taintrot = _orientation;
82 _mesh = mesh;
83 _pbs = pbs;
84
85 _parent_scene = parent_scene;
86 m_targetSpace = targetSpace;
87
88 if (pos.Z < 0)
89 m_isphysical = false;
90 else
91 {
92 m_isphysical = pisPhysical;
93 // If we're physical, we need to be in the master space for now.
94 // linksets *should* be in a space together.. but are not currently
95 if (m_isphysical)
96 m_targetSpace = _parent_scene.space;
97
98 }
99 m_primName = primName;
100
101
102
103 lock (OdeScene.OdeLock)
104 {
105 if (mesh != null)
106 {
107 setMesh(parent_scene, mesh);
108 }
109 else
110 {
111 prim_geom = d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z);
112 }
113
114 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
115 d.Quaternion myrot = new d.Quaternion();
116 myrot.W = rotation.w;
117 myrot.X = rotation.x;
118 myrot.Y = rotation.y;
119 myrot.Z = rotation.z;
120 d.GeomSetQuaternion(prim_geom, ref myrot);
121
122
123 if (m_isphysical && Body == (IntPtr)0)
124 {
125 enableBody();
126 }
127 parent_scene.geom_name_map[prim_geom] = primName;
128 parent_scene.actor_name_map[prim_geom] = (PhysicsActor)this;
129 // don't do .add() here; old geoms get recycled with the same hash
130 }
131 }
132 public override int PhysicsActorType
133 {
134 get { return (int)ActorTypes.Prim; }
135 set { return; }
136 }
137 public override bool SetAlwaysRun
138 {
139 get { return false; }
140 set { return; }
141 }
142 public void enableBody()
143 {
144 // Sets the geom to a body
145 Body = d.BodyCreate(_parent_scene.world);
146
147 setMass();
148 d.BodySetPosition(Body, _position.X, _position.Y, _position.Z);
149 d.Quaternion myrot = new d.Quaternion();
150 myrot.W = _orientation.w;
151 myrot.X = _orientation.x;
152 myrot.Y = _orientation.y;
153 myrot.Z = _orientation.z;
154 d.BodySetQuaternion(Body, ref myrot);
155 d.GeomSetBody(prim_geom, Body);
156 d.BodySetAutoDisableFlag(Body, true);
157 d.BodySetAutoDisableSteps(Body, 20);
158
159 _parent_scene.addActivePrim(this);
160 }
161 public void setMass()
162 {
163 //Sets Mass based on member MassMultiplier.
164 if (Body != (IntPtr)0)
165 {
166 d.MassSetBox(out pMass, (_size.X * _size.Y * _size.Z * MassMultiplier), _size.X, _size.Y, _size.Z);
167 d.BodySetMass(Body, ref pMass);
168 }
169 }
170 public void disableBody()
171 {
172 //this kills the body so things like 'mesh' can re-create it.
173 if (Body != (IntPtr)0)
174 {
175 _parent_scene.remActivePrim(this);
176 d.BodyDestroy(Body);
177 Body = (IntPtr)0;
178 }
179 }
180 public void setMesh(OdeScene parent_scene, IMesh mesh)
181 {
182 //Kill Body so that mesh can re-make the geom
183 if (IsPhysical && Body != (IntPtr)0)
184 {
185 disableBody();
186 }
187 float[] vertexList = mesh.getVertexListAsFloatLocked(); // Note, that vertextList is pinned in memory
188 int[] indexList = mesh.getIndexListAsIntLocked(); // Also pinned, needs release after usage
189 int VertexCount = vertexList.GetLength(0) / 3;
190 int IndexCount = indexList.GetLength(0);
191
192 _triMeshData = d.GeomTriMeshDataCreate();
193
194 d.GeomTriMeshDataBuildSimple(_triMeshData, vertexList, 3 * sizeof(float), VertexCount, indexList, IndexCount,
195 3 * sizeof(int));
196 d.GeomTriMeshDataPreprocess(_triMeshData);
197
198 prim_geom = d.CreateTriMesh(m_targetSpace, _triMeshData, parent_scene.triCallback, null, null);
199
200 if (IsPhysical && Body == (IntPtr)0)
201 {
202 // Recreate the body
203 enableBody();
204 }
205 }
206 public void ProcessTaints(float timestep)
207 {
208 if (m_taintposition != _position)
209 Move(timestep);
210
211 if (m_taintrot != _orientation)
212 rotate(timestep);
213 //
214
215 if (m_taintPhysics != m_isphysical)
216 changePhysicsStatus(timestep);
217 //
218
219 if (m_taintsize != _size)
220 changesize(timestep);
221 //
222
223 if (m_taintshape)
224 changeshape(timestep);
225 //
226
227 }
228 public void Move(float timestep)
229 {
230 if (m_isphysical)
231 {
232 // This is a fallback.. May no longer be necessary.
233 if (Body == (IntPtr)0)
234 enableBody();
235 //Prim auto disable after 20 frames,
236 ///if you move it, re-enable the prim manually.
237 d.BodyEnable(Body);
238 d.BodySetPosition(Body, _position.X, _position.Y, _position.Z);
239 }
240 else
241 {
242 string primScenAvatarIn = _parent_scene.whichspaceamIin(_position);
243 int[] arrayitem = _parent_scene.calculateSpaceArrayItemFromPos(_position);
244 if (primScenAvatarIn == "0")
245 {
246 OpenSim.Framework.Console.MainLog.Instance.Verbose("Physics", "Prim " + m_primName + " in space with no prim: " + primScenAvatarIn + ". Expected to be at: " + m_targetSpace.ToString() + " . Arr:': " + arrayitem[0].ToString() + "," + arrayitem[1].ToString());
247 }
248 else
249 {
250 OpenSim.Framework.Console.MainLog.Instance.Verbose("Physics", "Prim " + m_primName + " in Prim space with prim: " + primScenAvatarIn + ". Expected to be at: " + m_targetSpace.ToString() + ". Arr:" + arrayitem[0].ToString() + "," + arrayitem[1].ToString());
251 }
252 m_targetSpace = _parent_scene.recalculateSpaceForGeom(prim_geom, _position, m_targetSpace);
253 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
254 d.SpaceAdd(m_targetSpace, prim_geom);
255 }
256
257 m_taintposition = _position;
258 }
259 public void rotate(float timestep)
260 {
261
262 d.Quaternion myrot = new d.Quaternion();
263 myrot.W = _orientation.w;
264 myrot.X = _orientation.x;
265 myrot.Y = _orientation.y;
266 myrot.Z = _orientation.z;
267 d.GeomSetQuaternion(prim_geom, ref myrot);
268 if (m_isphysical && Body != (IntPtr)0)
269 {
270 d.BodySetQuaternion(Body, ref myrot);
271 }
272
273 m_taintrot = _orientation;
274 }
275 public void changePhysicsStatus(float timestap)
276 {
277 if (m_isphysical == true)
278 {
279 if (Body == (IntPtr)0)
280 {
281 enableBody();
282 }
283
284 }
285 else
286 {
287 if (Body != (IntPtr)0)
288 {
289 disableBody();
290 }
291 }
292
293
294 m_taintPhysics = m_isphysical;
295 }
296 public void changesize(float timestamp)
297 {
298 string oldname = _parent_scene.geom_name_map[prim_geom];
299
300 // Cleanup of old prim geometry
301 if (_mesh != null)
302 {
303 // Cleanup meshing here
304 }
305 //kill body to rebuild
306 if (IsPhysical && Body != (IntPtr)0)
307 {
308 disableBody();
309 }
310 if (d.SpaceQuery(m_targetSpace, prim_geom))
311 {
312 d.SpaceRemove(m_targetSpace, prim_geom);
313 }
314 d.GeomDestroy(prim_geom);
315
316 // we don't need to do space calculation because the client sends a position update also.
317
318 // Construction of new prim
319 if (this._parent_scene.needsMeshing(_pbs))
320 {
321
322
323 // Don't need to re-enable body.. it's done in SetMesh
324 IMesh mesh = _parent_scene.mesher.CreateMesh(oldname, _pbs, _size);
325 // createmesh returns null when it's a shape that isn't a cube.
326 if (mesh != null)
327 {
328 setMesh(_parent_scene, mesh);
329 }
330 else
331 {
332 prim_geom = d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z);
333 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
334 d.Quaternion myrot = new d.Quaternion();
335 myrot.W = _orientation.w;
336 myrot.X = _orientation.x;
337 myrot.Y = _orientation.y;
338 myrot.Z = _orientation.z;
339 d.GeomSetQuaternion(prim_geom, ref myrot);
340
341
342 }
343 }
344 else
345 {
346 prim_geom = d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z);
347 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
348 d.Quaternion myrot = new d.Quaternion();
349 myrot.W = _orientation.w;
350 myrot.X = _orientation.x;
351 myrot.Y = _orientation.y;
352 myrot.Z = _orientation.z;
353 d.GeomSetQuaternion(prim_geom, ref myrot);
354
355
356 //d.GeomBoxSetLengths(prim_geom, _size.X, _size.Y, _size.Z);
357 if (IsPhysical && Body == (IntPtr)0)
358 {
359 // Re creates body on size.
360 // EnableBody also does setMass()
361 enableBody();
362 d.BodyEnable(Body);
363 }
364
365 }
366
367
368 _parent_scene.geom_name_map[prim_geom] = oldname;
369
370
371 m_taintsize = _size;
372 }
373 public void changeshape(float timestamp)
374 {
375 string oldname = _parent_scene.geom_name_map[prim_geom];
376
377 // Cleanup of old prim geometry and Bodies
378 if (IsPhysical && Body != (IntPtr)0)
379 {
380 disableBody();
381 }
382 d.GeomDestroy(prim_geom);
383 if (_mesh != null)
384 {
385
386 d.GeomBoxSetLengths(prim_geom, _size.X, _size.Y, _size.Z);
387
388 }
389
390 // Construction of new prim
391 if (this._parent_scene.needsMeshing(_pbs))
392 {
393 IMesh mesh = _parent_scene.mesher.CreateMesh(oldname, _pbs, _size);
394 if (mesh != null)
395 {
396 setMesh(_parent_scene, mesh);
397 }
398 else
399 {
400 prim_geom = d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z);
401 }
402 }
403 else
404 {
405 prim_geom = d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z);
406 }
407 if (IsPhysical && Body == (IntPtr)0)
408 {
409 //re-create new body
410 enableBody();
411 }
412 else
413 {
414 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
415 d.Quaternion myrot = new d.Quaternion();
416 myrot.W = _orientation.w;
417 myrot.X = _orientation.x;
418 myrot.Y = _orientation.y;
419 myrot.Z = _orientation.z;
420 d.GeomSetQuaternion(prim_geom, ref myrot);
421 }
422 _parent_scene.geom_name_map[prim_geom] = oldname;
423
424
425
426
427 m_taintshape = false;
428 }
429 public override bool IsPhysical
430 {
431 get { return m_isphysical; }
432 set { m_isphysical = value; }
433 }
434 public void setPrimForRemoval()
435 {
436 m_taintremove = true;
437 }
438
439 public override bool Flying
440 {
441 get
442 {
443 return false; //no flying prims for you
444 }
445 set { }
446 }
447
448 public override bool IsColliding
449 {
450 get { return iscolliding; }
451 set { iscolliding = value; }
452 }
453 public override bool CollidingGround
454 {
455 get { return false; }
456 set { return; }
457 }
458 public override bool CollidingObj
459 {
460 get { return false; }
461 set { return; }
462 }
463 public override bool ThrottleUpdates
464 {
465 get { return m_throttleUpdates; }
466 set { m_throttleUpdates = value; }
467 }
468
469 public override PhysicsVector Position
470 {
471 get { return _position; }
472
473
474 set
475 {
476 _position = value;
477
478 }
479 }
480
481 public override PhysicsVector Size
482 {
483 get { return _size; }
484 set
485 {
486 _size = value;
487
488 }
489 }
490
491 public override PrimitiveBaseShape Shape
492 {
493 set
494 {
495 _pbs = value;
496
497 }
498 }
499
500 public override PhysicsVector Velocity
501 {
502 get
503 {
504 // Averate previous velocity with the new one so
505 // client object interpolation works a 'little' better
506 PhysicsVector returnVelocity = new PhysicsVector();
507 returnVelocity.X = (m_lastVelocity.X + _velocity.X) / 2;
508 returnVelocity.Y = (m_lastVelocity.Y + _velocity.Y) / 2;
509 returnVelocity.Z = (m_lastVelocity.Z + _velocity.Z) / 2;
510 return returnVelocity;
511 }
512 set { _velocity = value; }
513 }
514
515 public override bool Kinematic
516 {
517 get { return false; }
518 set { }
519 }
520
521 public override Quaternion Orientation
522 {
523 get { return _orientation; }
524 set
525 {
526 _orientation = value;
527
528 }
529 }
530
531 public override PhysicsVector Acceleration
532 {
533 get { return _acceleration; }
534 }
535
536
537 public void SetAcceleration(PhysicsVector accel)
538 {
539 _acceleration = accel;
540 }
541
542 public override void AddForce(PhysicsVector force)
543 {
544 }
545
546 public override PhysicsVector RotationalVelocity
547 {
548 get { return m_rotationalVelocity; }
549 set { m_rotationalVelocity = value; }
550 }
551
552 public void UpdatePositionAndVelocity()
553 {
554 // no lock; called from Simulate() -- if you call this from elsewhere, gotta lock or do Monitor.Enter/Exit!
555
556 if (Body != (IntPtr)0)
557 {
558 d.Vector3 vec = d.BodyGetPosition(Body);
559 d.Quaternion ori = d.BodyGetQuaternion(Body);
560 d.Vector3 vel = d.BodyGetLinearVel(Body);
561 d.Vector3 rotvel = d.BodyGetAngularVel(Body);
562
563 PhysicsVector l_position = new PhysicsVector();
564 // kluge to keep things in bounds. ODE lets dead avatars drift away (they should be removed!)
565 if (vec.X < 0.0f) vec.X = 0.0f;
566 if (vec.Y < 0.0f) vec.Y = 0.0f;
567 if (vec.X > 255.95f) vec.X = 255.95f;
568 if (vec.Y > 255.95f) vec.Y = 255.95f;
569 m_lastposition = _position;
570
571 l_position.X = vec.X;
572 l_position.Y = vec.Y;
573 l_position.Z = vec.Z;
574 if (l_position.Z < 0)
575 {
576 // This is so prim that get lost underground don't fall forever and suck up
577 //
578 // Sim resources and memory.
579 // Disables the prim's movement physics....
580 // It's a hack and will generate a console message if it fails.
581
582
583
584
585 //IsPhysical = false;
586 base.RaiseOutOfBounds(_position);
587 _velocity.X = 0;
588 _velocity.Y = 0;
589 _velocity.Z = 0;
590 m_rotationalVelocity.X = 0;
591 m_rotationalVelocity.Y = 0;
592 m_rotationalVelocity.Z = 0;
593 base.RequestPhysicsterseUpdate();
594 m_throttleUpdates = false;
595 throttleCounter = 0;
596 _zeroFlag = true;
597 //outofBounds = true;
598 }
599
600 if ((Math.Abs(m_lastposition.X - l_position.X) < 0.02)
601 && (Math.Abs(m_lastposition.Y - l_position.Y) < 0.02)
602 && (Math.Abs(m_lastposition.Z - l_position.Z) < 0.02))
603 {
604
605 _zeroFlag = true;
606 }
607 else
608 {
609 //System.Console.WriteLine(Math.Abs(m_lastposition.X - l_position.X).ToString());
610 _zeroFlag = false;
611 }
612
613
614
615 if (_zeroFlag)
616 {
617 // Supposedly this is supposed to tell SceneObjectGroup that
618 // no more updates need to be sent..
619 // but it seems broken.
620 _velocity.X = 0.0f;
621 _velocity.Y = 0.0f;
622 _velocity.Z = 0.0f;
623 //_orientation.w = 0f;
624 //_orientation.x = 0f;
625 //_orientation.y = 0f;
626 //_orientation.z = 0f;
627 m_rotationalVelocity.X = 0;
628 m_rotationalVelocity.Y = 0;
629 m_rotationalVelocity.Z = 0;
630 if (!m_lastUpdateSent)
631 {
632 m_throttleUpdates = false;
633 throttleCounter = 0;
634 base.RequestPhysicsterseUpdate();
635 m_lastUpdateSent = true;
636 }
637
638 }
639 else
640 {
641 m_lastVelocity = _velocity;
642
643 _position = l_position;
644
645 _velocity.X = vel.X;
646 _velocity.Y = vel.Y;
647 _velocity.Z = vel.Z;
648
649 m_rotationalVelocity.X = rotvel.X;
650 m_rotationalVelocity.Y = rotvel.Y;
651 m_rotationalVelocity.Z = rotvel.Z;
652 //System.Console.WriteLine("ODE: " + m_rotationalVelocity.ToString());
653 _orientation.w = ori.W;
654 _orientation.x = ori.X;
655 _orientation.y = ori.Y;
656 _orientation.z = ori.Z;
657 m_lastUpdateSent = false;
658 if (!m_throttleUpdates || throttleCounter > 15)
659 {
660 base.RequestPhysicsterseUpdate();
661 }
662 else
663 {
664 throttleCounter++;
665 }
666 }
667 m_lastposition = l_position;
668 }
669 else
670 {
671 // Not a body.. so Make sure the client isn't interpolating
672 _velocity.X = 0;
673 _velocity.Y = 0;
674 _velocity.Z = 0;
675 m_rotationalVelocity.X = 0;
676 m_rotationalVelocity.Y = 0;
677 m_rotationalVelocity.Z = 0;
678 _zeroFlag = true;
679 }
680
681 }
682 public override void SetMomentum(PhysicsVector momentum)
683 {
684 }
685 }
686}
diff --git a/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs b/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs
index e8ee33c..1e05274 100644
--- a/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs
+++ b/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs
@@ -1087,1143 +1087,7 @@ namespace OpenSim.Region.Physics.OdePlugin
1087 { 1087 {
1088 } 1088 }
1089 } 1089 }
1090 # region ODE Actors 1090
1091 1091
1092 public class OdeCharacter : PhysicsActor 1092
1093 { 1093} \ No newline at end of file
1094 private PhysicsVector _position;
1095 private d.Vector3 _zeroPosition;
1096 private bool _zeroFlag = false;
1097 private bool m_lastUpdateSent = false;
1098 private PhysicsVector _velocity;
1099 private PhysicsVector _target_velocity;
1100 private PhysicsVector _acceleration;
1101 private PhysicsVector m_rotationalVelocity;
1102 private static float PID_D = 3020.0f;
1103 private static float PID_P = 7000.0f;
1104 private static float POSTURE_SERVO = 10000.0f;
1105 public static float CAPSULE_RADIUS = 0.5f;
1106 public float CAPSULE_LENGTH = 0.79f;
1107 private bool flying = false;
1108 private bool m_iscolliding = false;
1109 private bool m_iscollidingGround = false;
1110 private bool m_wascolliding = false;
1111 private bool m_wascollidingGround = false;
1112 private bool m_alwaysRun = false;
1113 private bool m_hackSentFall = false;
1114 private bool m_hackSentFly = false;
1115 private string m_name = "";
1116
1117 private bool[] m_colliderarr = new bool[11];
1118 private bool[] m_colliderGroundarr = new bool[11];
1119
1120
1121 private bool jumping = false;
1122 //private float gravityAccel;
1123 public IntPtr Body;
1124 private OdeScene _parent_scene;
1125 public IntPtr Shell;
1126 public d.Mass ShellMass;
1127 public bool collidelock = false;
1128
1129 public OdeCharacter(String avName, OdeScene parent_scene, PhysicsVector pos)
1130 {
1131 _velocity = new PhysicsVector();
1132 _target_velocity = new PhysicsVector();
1133 _position = pos;
1134 _acceleration = new PhysicsVector();
1135 _parent_scene = parent_scene;
1136
1137 for (int i = 0; i < 11; i++)
1138 {
1139 m_colliderarr[i] = false;
1140 }
1141
1142 lock (OdeScene.OdeLock)
1143 {
1144
1145 Shell = d.CreateCapsule(parent_scene.space, CAPSULE_RADIUS, CAPSULE_LENGTH);
1146 d.MassSetCapsule(out ShellMass, 50.0f, 3, 0.4f, 1.0f);
1147 Body = d.BodyCreate(parent_scene.world);
1148 d.BodySetMass(Body, ref ShellMass);
1149 d.BodySetPosition(Body, pos.X, pos.Y, pos.Z);
1150 d.GeomSetBody(Shell, Body);
1151 }
1152 m_name = avName;
1153 parent_scene.geom_name_map[Shell] = avName;
1154 parent_scene.actor_name_map[Shell] = (PhysicsActor)this;
1155 }
1156 public override int PhysicsActorType
1157 {
1158 get { return (int)ActorTypes.Agent; }
1159 set { return; }
1160 }
1161 public override bool SetAlwaysRun
1162 {
1163 get { return m_alwaysRun; }
1164 set { m_alwaysRun = value;}
1165 }
1166 public override bool IsPhysical
1167 {
1168 get { return false; }
1169 set { return; }
1170 }
1171 public override bool ThrottleUpdates
1172 {
1173 get { return false; }
1174 set { return; }
1175 }
1176 public override bool Flying
1177 {
1178 get { return flying; }
1179 set { flying = value; }
1180 }
1181 public override bool IsColliding
1182 {
1183
1184 get { return m_iscolliding; }
1185 set
1186 {
1187 int i;
1188 int truecount=0;
1189 int falsecount=0;
1190
1191 if (m_colliderarr.Length >= 10)
1192 {
1193 for (i = 0; i < 10; i++)
1194 {
1195 m_colliderarr[i] = m_colliderarr[i + 1];
1196 }
1197 }
1198 m_colliderarr[10] = value;
1199
1200 for (i = 0; i < 11; i++)
1201 {
1202 if (m_colliderarr[i])
1203 {
1204 truecount++;
1205 }
1206 else
1207 {
1208 falsecount++;
1209 }
1210 }
1211
1212 // Equal truecounts and false counts means we're colliding with something.
1213
1214 if (falsecount > 1.2 * truecount)
1215 {
1216 m_iscolliding = false;
1217 }
1218 else
1219 {
1220 m_iscolliding = true;
1221 }
1222 if (m_wascolliding != m_iscolliding)
1223 {
1224 base.SendCollisionUpdate(new CollisionEventUpdate());
1225 }
1226 m_wascolliding = m_iscolliding;
1227 }
1228 }
1229 public override bool CollidingGround
1230 {
1231 get { return m_iscollidingGround; }
1232 set
1233 {
1234 int i;
1235 int truecount = 0;
1236 int falsecount = 0;
1237
1238 if (m_colliderGroundarr.Length >= 10)
1239 {
1240 for (i = 0; i < 10; i++)
1241 {
1242 m_colliderGroundarr[i] = m_colliderGroundarr[i + 1];
1243 }
1244 }
1245 m_colliderGroundarr[10] = value;
1246
1247 for (i = 0; i < 11; i++)
1248 {
1249 if (m_colliderGroundarr[i])
1250 {
1251 truecount++;
1252 }
1253 else
1254 {
1255 falsecount++;
1256 }
1257 }
1258
1259 // Equal truecounts and false counts means we're colliding with something.
1260
1261 if (falsecount > 1.2 * truecount)
1262 {
1263 m_iscollidingGround = false;
1264 }
1265 else
1266 {
1267 m_iscollidingGround = true;
1268 }
1269 if (m_wascollidingGround != m_iscollidingGround)
1270 {
1271 //base.SendCollisionUpdate(new CollisionEventUpdate());
1272 }
1273 m_wascollidingGround = m_iscollidingGround;
1274 }
1275 }
1276 public override bool CollidingObj
1277 {
1278 get { return false; }
1279 set { return; }
1280 }
1281
1282 public override PhysicsVector Position
1283 {
1284 get { return _position; }
1285 set
1286 {
1287 lock (OdeScene.OdeLock)
1288 {
1289 d.BodySetPosition(Body, value.X, value.Y, value.Z);
1290 _position = value;
1291 }
1292 }
1293 }
1294 public override PhysicsVector RotationalVelocity
1295 {
1296 get { return m_rotationalVelocity; }
1297 set { m_rotationalVelocity = value; }
1298 }
1299 public override PhysicsVector Size
1300 {
1301 get { return new PhysicsVector(CAPSULE_RADIUS*2, CAPSULE_RADIUS*2, CAPSULE_LENGTH); }
1302 set {
1303 lock (OdeScene.OdeLock)
1304 {
1305 PhysicsVector SetSize = value;
1306 float prevCapsule = CAPSULE_LENGTH;
1307 float capsuleradius = CAPSULE_RADIUS;
1308 capsuleradius = 0.2f;
1309
1310 CAPSULE_LENGTH = (SetSize.Z - ((SetSize.Z * 0.43f))); // subtract 43% of the size
1311 d.BodyDestroy(Body);
1312 d.GeomDestroy(Shell);
1313 //OpenSim.Framework.Console.MainLog.Instance.Verbose("PHYSICS", "Set Avatar Height To: " + (CAPSULE_RADIUS + CAPSULE_LENGTH));
1314 Shell = d.CreateCapsule(_parent_scene.space, capsuleradius, CAPSULE_LENGTH);
1315 d.MassSetCapsule(out ShellMass, 50.0f, 3, CAPSULE_RADIUS, CAPSULE_LENGTH);
1316 Body = d.BodyCreate(_parent_scene.world);
1317 d.BodySetMass(Body, ref ShellMass);
1318 d.BodySetPosition(Body, _position.X, _position.Y, _position.Z + Math.Abs(CAPSULE_LENGTH-prevCapsule));
1319 d.GeomSetBody(Shell, Body);
1320 }
1321 _parent_scene.geom_name_map[Shell] = m_name;
1322 _parent_scene.actor_name_map[Shell] = (PhysicsActor)this;
1323 }
1324 }
1325
1326 public override PrimitiveBaseShape Shape
1327 {
1328 set
1329 {
1330 return;
1331 }
1332 }
1333
1334 public override PhysicsVector Velocity
1335 {
1336 get { return _velocity; }
1337 set { _target_velocity = value; }
1338 }
1339
1340 public override bool Kinematic
1341 {
1342 get { return false; }
1343 set { }
1344 }
1345
1346 public override Quaternion Orientation
1347 {
1348 get { return Quaternion.Identity; }
1349 set { }
1350 }
1351
1352 public override PhysicsVector Acceleration
1353 {
1354 get { return _acceleration; }
1355 }
1356
1357 public void SetAcceleration(PhysicsVector accel)
1358 {
1359 _acceleration = accel;
1360 }
1361
1362 public override void AddForce(PhysicsVector force)
1363 {
1364
1365 _target_velocity.X += force.X;
1366 _target_velocity.Y += force.Y;
1367 _target_velocity.Z += force.Z;
1368
1369 //m_lastUpdateSent = false;
1370 }
1371 public void doForce(PhysicsVector force)
1372 {
1373 if (!collidelock)
1374 {
1375 d.BodyAddForce(Body, force.X, force.Y, force.Z);
1376
1377 // ok -- let's stand up straight!
1378 d.Vector3 feet;
1379 d.Vector3 head;
1380 d.BodyGetRelPointPos(Body, 0.0f, 0.0f, -1.0f, out feet);
1381 d.BodyGetRelPointPos(Body, 0.0f, 0.0f, 1.0f, out head);
1382 float posture = head.Z - feet.Z;
1383
1384 // restoring force proportional to lack of posture:
1385 float servo = (2.5f - posture) * POSTURE_SERVO;
1386 d.BodyAddForceAtRelPos(Body, 0.0f, 0.0f, servo, 0.0f, 0.0f, 1.0f);
1387 d.BodyAddForceAtRelPos(Body, 0.0f, 0.0f, -servo, 0.0f, 0.0f, -1.0f);
1388 //m_lastUpdateSent = false;
1389
1390 }
1391
1392 }
1393 public override void SetMomentum(PhysicsVector momentum)
1394 {
1395
1396 }
1397
1398 public void Move(float timeStep)
1399 {
1400 // no lock; for now it's only called from within Simulate()
1401 PhysicsVector vec = new PhysicsVector();
1402 d.Vector3 vel = d.BodyGetLinearVel(Body);
1403 float movementdivisor = 1f;
1404
1405 if (!m_alwaysRun)
1406 {
1407 movementdivisor = 1.3f;
1408 }
1409 else
1410 {
1411 movementdivisor = 0.8f;
1412
1413 }
1414
1415 // if velocity is zero, use position control; otherwise, velocity control
1416 if (_target_velocity.X == 0.0f && _target_velocity.Y == 0.0f && _target_velocity.Z == 0.0f && m_iscolliding)
1417 {
1418 // keep track of where we stopped. No more slippin' & slidin'
1419 if (!_zeroFlag)
1420 {
1421 _zeroFlag = true;
1422 _zeroPosition = d.BodyGetPosition(Body);
1423 }
1424 d.Vector3 pos = d.BodyGetPosition(Body);
1425 vec.X = (_target_velocity.X - vel.X)*PID_D + (_zeroPosition.X - pos.X)*PID_P;
1426 vec.Y = (_target_velocity.Y - vel.Y)*PID_D + (_zeroPosition.Y - pos.Y)*PID_P;
1427 if (flying)
1428 {
1429 vec.Z = (_target_velocity.Z - vel.Z)*PID_D + (_zeroPosition.Z - pos.Z)*PID_P;
1430 }
1431 }
1432 else
1433 {
1434
1435 _zeroFlag = false;
1436 if (m_iscolliding || flying)
1437 {
1438
1439 vec.X = ((_target_velocity.X/movementdivisor) - vel.X) * PID_D;
1440 vec.Y = ((_target_velocity.Y/movementdivisor) - vel.Y) * PID_D;
1441 }
1442 if (m_iscolliding && !flying && _target_velocity.Z > 0.0f)
1443 {
1444 d.Vector3 pos = d.BodyGetPosition(Body);
1445 vec.Z = (_target_velocity.Z - vel.Z) * PID_D + (_zeroPosition.Z - pos.Z) * PID_P;
1446 if (_target_velocity.X > 0)
1447 {
1448 vec.X = ((_target_velocity.X - vel.X) / 1.2f) * PID_D;
1449 }
1450 if (_target_velocity.Y > 0)
1451 {
1452 vec.Y = ((_target_velocity.Y - vel.Y) / 1.2f) * PID_D;
1453 }
1454 }
1455 else if (!m_iscolliding && !flying)
1456 {
1457 d.Vector3 pos = d.BodyGetPosition(Body);
1458 if (_target_velocity.X > 0)
1459 {
1460 vec.X = ((_target_velocity.X - vel.X)/1.2f) * PID_D;
1461 }
1462 if (_target_velocity.Y > 0)
1463 {
1464 vec.Y = ((_target_velocity.Y - vel.Y)/1.2f) * PID_D;
1465 }
1466
1467 }
1468
1469
1470 if (flying)
1471 {
1472 vec.Z = (_target_velocity.Z - vel.Z)*PID_D;
1473 }
1474 }
1475 if (flying)
1476 {
1477 vec.Z += 10.0f;
1478 }
1479
1480
1481 doForce(vec);
1482 }
1483
1484 public void UpdatePositionAndVelocity()
1485 {
1486 // no lock; called from Simulate() -- if you call this from elsewhere, gotta lock or do Monitor.Enter/Exit!
1487 d.Vector3 vec = d.BodyGetPosition(Body);
1488
1489 // kluge to keep things in bounds. ODE lets dead avatars drift away (they should be removed!)
1490 if (vec.X < 0.0f) vec.X = 0.0f;
1491 if (vec.Y < 0.0f) vec.Y = 0.0f;
1492 if (vec.X > 255.95f) vec.X = 255.95f;
1493 if (vec.Y > 255.95f) vec.Y = 255.95f;
1494
1495 _position.X = vec.X;
1496 _position.Y = vec.Y;
1497 _position.Z = vec.Z;
1498
1499 if (_zeroFlag)
1500 {
1501 _velocity.X = 0.0f;
1502 _velocity.Y = 0.0f;
1503 _velocity.Z = 0.0f;
1504 if (!m_lastUpdateSent)
1505 {
1506 m_lastUpdateSent = true;
1507 base.RequestPhysicsterseUpdate();
1508 string primScenAvatarIn = _parent_scene.whichspaceamIin(_position);
1509 int[] arrayitem = _parent_scene.calculateSpaceArrayItemFromPos(_position);
1510 if (primScenAvatarIn == "0")
1511 {
1512 OpenSim.Framework.Console.MainLog.Instance.Verbose("Physics", "Avatar " + m_name + " in space with no prim. Arr:':" + arrayitem[0].ToString() + "," + arrayitem[1].ToString());
1513 }
1514 else
1515 {
1516 OpenSim.Framework.Console.MainLog.Instance.Verbose("Physics", "Avatar " + m_name + " in Prim space':" + primScenAvatarIn + ". Arr:" + arrayitem[0].ToString() + "," + arrayitem[1].ToString());
1517 }
1518
1519 }
1520 }
1521 else
1522 {
1523 m_lastUpdateSent = false;
1524 vec = d.BodyGetLinearVel(Body);
1525 _velocity.X = (vec.X);
1526 _velocity.Y = (vec.Y);
1527
1528 _velocity.Z = (vec.Z);
1529 if (_velocity.Z < -6 && !m_hackSentFall)
1530 {
1531 m_hackSentFall = true;
1532 base.SendCollisionUpdate(new CollisionEventUpdate());
1533 }
1534 else if (flying && !m_hackSentFly)
1535 {
1536 //m_hackSentFly = true;
1537 //base.SendCollisionUpdate(new CollisionEventUpdate());
1538 }
1539 else
1540 {
1541 m_hackSentFly = false;
1542 m_hackSentFall = false;
1543 }
1544 }
1545 }
1546
1547 public void Destroy()
1548 {
1549 lock (OdeScene.OdeLock)
1550 {
1551 d.GeomDestroy(Shell);
1552 _parent_scene.geom_name_map.Remove(Shell);
1553 d.BodyDestroy(Body);
1554 }
1555 }
1556 }
1557
1558 public class OdePrim : PhysicsActor
1559 {
1560 public PhysicsVector _position;
1561 private PhysicsVector _velocity;
1562 private PhysicsVector m_lastVelocity = new PhysicsVector(0.0f,0.0f,0.0f);
1563 private PhysicsVector m_lastposition = new PhysicsVector(0.0f, 0.0f, 0.0f);
1564 private PhysicsVector m_rotationalVelocity;
1565 private PhysicsVector _size;
1566 private PhysicsVector _acceleration;
1567 private Quaternion _orientation;
1568 private PhysicsVector m_taintposition;
1569 private PhysicsVector m_taintsize;
1570 private Quaternion m_taintrot;
1571 private bool m_taintshape = false;
1572 private bool m_taintPhysics = false;
1573 public bool m_taintremove = false;
1574
1575 private IMesh _mesh;
1576 private PrimitiveBaseShape _pbs;
1577 private OdeScene _parent_scene;
1578 public IntPtr m_targetSpace = (IntPtr)0;
1579 public IntPtr prim_geom;
1580 public IntPtr _triMeshData;
1581 private bool iscolliding = false;
1582 private bool m_isphysical = false;
1583 private bool m_throttleUpdates = false;
1584 private int throttleCounter = 0;
1585 public bool outofBounds = false;
1586
1587 public bool _zeroFlag = false;
1588 private bool m_lastUpdateSent = false;
1589
1590 public IntPtr Body = (IntPtr) 0;
1591 private String m_primName;
1592 private PhysicsVector _target_velocity;
1593 public d.Mass pMass;
1594 private const float MassMultiplier = 150f; // Ref: Water: 1000kg.. this iset to 500
1595 private int debugcounter = 0;
1596
1597
1598 public OdePrim(String primName, OdeScene parent_scene, IntPtr targetSpace, PhysicsVector pos, PhysicsVector size,
1599 Quaternion rotation, IMesh mesh, PrimitiveBaseShape pbs, bool pisPhysical)
1600 {
1601
1602
1603 _velocity = new PhysicsVector();
1604 _position = pos;
1605 m_taintposition = pos;
1606 if (_position.X > 257)
1607 {
1608 _position.X = 257;
1609 }
1610 if (_position.X < 0)
1611 {
1612 _position.X = 0;
1613 }
1614 if (_position.Y > 257)
1615 {
1616 _position.Y = 257;
1617 }
1618 if (_position.Y < 0)
1619 {
1620 _position.Y = 0;
1621 }
1622
1623 _size = size;
1624 m_taintsize = _size;
1625 _acceleration = new PhysicsVector();
1626 m_rotationalVelocity = PhysicsVector.Zero;
1627 _orientation = rotation;
1628 m_taintrot = _orientation;
1629 _mesh = mesh;
1630 _pbs = pbs;
1631
1632 _parent_scene = parent_scene;
1633 m_targetSpace = targetSpace;
1634
1635 if (pos.Z < 0)
1636 m_isphysical = false;
1637 else
1638 {
1639 m_isphysical = pisPhysical;
1640 // If we're physical, we need to be in the master space for now.
1641 // linksets *should* be in a space together.. but are not currently
1642 if (m_isphysical)
1643 m_targetSpace = _parent_scene.space;
1644
1645 }
1646 m_primName = primName;
1647
1648
1649
1650 lock (OdeScene.OdeLock)
1651 {
1652 if (mesh != null)
1653 {
1654 setMesh(parent_scene, mesh);
1655 }
1656 else
1657 {
1658 prim_geom = d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z);
1659 }
1660
1661 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
1662 d.Quaternion myrot = new d.Quaternion();
1663 myrot.W = rotation.w;
1664 myrot.X = rotation.x;
1665 myrot.Y = rotation.y;
1666 myrot.Z = rotation.z;
1667 d.GeomSetQuaternion(prim_geom, ref myrot);
1668
1669
1670 if (m_isphysical && Body == (IntPtr)0) {
1671 enableBody();
1672 }
1673 parent_scene.geom_name_map[prim_geom] = primName;
1674 parent_scene.actor_name_map[prim_geom] = (PhysicsActor)this;
1675 // don't do .add() here; old geoms get recycled with the same hash
1676 }
1677 }
1678 public override int PhysicsActorType
1679 {
1680 get { return (int)ActorTypes.Prim; }
1681 set { return; }
1682 }
1683 public override bool SetAlwaysRun
1684 {
1685 get { return false; }
1686 set { return; }
1687 }
1688 public void enableBody()
1689 {
1690 // Sets the geom to a body
1691 Body = d.BodyCreate(_parent_scene.world);
1692
1693 setMass();
1694 d.BodySetPosition(Body, _position.X, _position.Y, _position.Z);
1695 d.Quaternion myrot = new d.Quaternion();
1696 myrot.W = _orientation.w;
1697 myrot.X = _orientation.x;
1698 myrot.Y = _orientation.y;
1699 myrot.Z = _orientation.z;
1700 d.BodySetQuaternion(Body, ref myrot);
1701 d.GeomSetBody(prim_geom, Body);
1702 d.BodySetAutoDisableFlag(Body, true);
1703 d.BodySetAutoDisableSteps(Body,20);
1704
1705 _parent_scene.addActivePrim(this);
1706 }
1707 public void setMass()
1708 {
1709 //Sets Mass based on member MassMultiplier.
1710 if (Body != (IntPtr)0)
1711 {
1712 d.MassSetBox(out pMass, (_size.X * _size.Y * _size.Z * MassMultiplier), _size.X, _size.Y, _size.Z);
1713 d.BodySetMass(Body, ref pMass);
1714 }
1715 }
1716 public void disableBody()
1717 {
1718 //this kills the body so things like 'mesh' can re-create it.
1719 if (Body != (IntPtr)0)
1720 {
1721 _parent_scene.remActivePrim(this);
1722 d.BodyDestroy(Body);
1723 Body = (IntPtr)0;
1724 }
1725 }
1726 public void setMesh(OdeScene parent_scene, IMesh mesh)
1727 {
1728 //Kill Body so that mesh can re-make the geom
1729 if (IsPhysical && Body != (IntPtr)0)
1730 {
1731 disableBody();
1732 }
1733 float[] vertexList = mesh.getVertexListAsFloatLocked(); // Note, that vertextList is pinned in memory
1734 int[] indexList = mesh.getIndexListAsIntLocked(); // Also pinned, needs release after usage
1735 int VertexCount = vertexList.GetLength(0)/3;
1736 int IndexCount = indexList.GetLength(0);
1737
1738 _triMeshData = d.GeomTriMeshDataCreate();
1739
1740 d.GeomTriMeshDataBuildSimple(_triMeshData, vertexList, 3*sizeof (float), VertexCount, indexList, IndexCount,
1741 3*sizeof (int));
1742 d.GeomTriMeshDataPreprocess(_triMeshData);
1743
1744 prim_geom = d.CreateTriMesh(m_targetSpace, _triMeshData, parent_scene.triCallback, null, null);
1745
1746 if (IsPhysical && Body == (IntPtr)0)
1747 {
1748 // Recreate the body
1749 enableBody();
1750 }
1751 }
1752 public void ProcessTaints(float timestep)
1753 {
1754 if (m_taintposition != _position)
1755 Move(timestep);
1756
1757 if (m_taintrot != _orientation)
1758 rotate(timestep);
1759 //
1760
1761 if (m_taintPhysics != m_isphysical)
1762 changePhysicsStatus(timestep);
1763 //
1764
1765 if (m_taintsize != _size)
1766 changesize(timestep);
1767 //
1768
1769 if (m_taintshape)
1770 changeshape(timestep);
1771 //
1772
1773 }
1774 public void Move(float timestep)
1775 {
1776 if (m_isphysical)
1777 {
1778 // This is a fallback.. May no longer be necessary.
1779 if (Body == (IntPtr)0)
1780 enableBody();
1781 //Prim auto disable after 20 frames,
1782 ///if you move it, re-enable the prim manually.
1783 d.BodyEnable(Body);
1784 d.BodySetPosition(Body, _position.X, _position.Y, _position.Z);
1785 }
1786 else
1787 {
1788 string primScenAvatarIn = _parent_scene.whichspaceamIin(_position);
1789 int[] arrayitem = _parent_scene.calculateSpaceArrayItemFromPos(_position);
1790 if (primScenAvatarIn == "0")
1791 {
1792 OpenSim.Framework.Console.MainLog.Instance.Verbose("Physics", "Prim " + m_primName + " in space with no prim: " + primScenAvatarIn + ". Expected to be at: " + m_targetSpace.ToString() + " . Arr:': " + arrayitem[0].ToString() + "," + arrayitem[1].ToString());
1793 }
1794 else
1795 {
1796 OpenSim.Framework.Console.MainLog.Instance.Verbose("Physics", "Prim " + m_primName + " in Prim space with prim: " + primScenAvatarIn + ". Expected to be at: " + m_targetSpace.ToString() + ". Arr:" + arrayitem[0].ToString() + "," + arrayitem[1].ToString());
1797 }
1798 m_targetSpace = _parent_scene.recalculateSpaceForGeom(prim_geom, _position, m_targetSpace);
1799 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
1800 d.SpaceAdd(m_targetSpace, prim_geom);
1801 }
1802
1803 m_taintposition = _position;
1804 }
1805 public void rotate(float timestep)
1806 {
1807
1808 d.Quaternion myrot = new d.Quaternion();
1809 myrot.W = _orientation.w;
1810 myrot.X = _orientation.x;
1811 myrot.Y = _orientation.y;
1812 myrot.Z = _orientation.z;
1813 d.GeomSetQuaternion(prim_geom, ref myrot);
1814 if (m_isphysical && Body != (IntPtr)0)
1815 {
1816 d.BodySetQuaternion(Body, ref myrot);
1817 }
1818
1819 m_taintrot = _orientation;
1820 }
1821 public void changePhysicsStatus(float timestap)
1822 {
1823 if (m_isphysical == true)
1824 {
1825 if (Body == (IntPtr)0)
1826 {
1827 enableBody();
1828 }
1829
1830 }
1831 else
1832 {
1833 if (Body != (IntPtr)0)
1834 {
1835 disableBody();
1836 }
1837 }
1838
1839
1840 m_taintPhysics = m_isphysical;
1841 }
1842 public void changesize(float timestamp)
1843 {
1844 string oldname = _parent_scene.geom_name_map[prim_geom];
1845
1846 // Cleanup of old prim geometry
1847 if (_mesh != null)
1848 {
1849 // Cleanup meshing here
1850 }
1851 //kill body to rebuild
1852 if (IsPhysical && Body != (IntPtr)0)
1853 {
1854 disableBody();
1855 }
1856 if (d.SpaceQuery(m_targetSpace, prim_geom))
1857 {
1858 d.SpaceRemove(m_targetSpace, prim_geom);
1859 }
1860 d.GeomDestroy(prim_geom);
1861
1862 // we don't need to do space calculation because the client sends a position update also.
1863
1864 // Construction of new prim
1865 if (this._parent_scene.needsMeshing(_pbs))
1866 {
1867
1868
1869 // Don't need to re-enable body.. it's done in SetMesh
1870 IMesh mesh = _parent_scene.mesher.CreateMesh(oldname, _pbs, _size);
1871 // createmesh returns null when it's a shape that isn't a cube.
1872 if (mesh != null)
1873 {
1874 setMesh(_parent_scene, mesh);
1875 }
1876 else
1877 {
1878 prim_geom = d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z);
1879 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
1880 d.Quaternion myrot = new d.Quaternion();
1881 myrot.W = _orientation.w;
1882 myrot.X = _orientation.x;
1883 myrot.Y = _orientation.y;
1884 myrot.Z = _orientation.z;
1885 d.GeomSetQuaternion(prim_geom, ref myrot);
1886
1887
1888 }
1889 }
1890 else
1891 {
1892 prim_geom = d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z);
1893 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
1894 d.Quaternion myrot = new d.Quaternion();
1895 myrot.W = _orientation.w;
1896 myrot.X = _orientation.x;
1897 myrot.Y = _orientation.y;
1898 myrot.Z = _orientation.z;
1899 d.GeomSetQuaternion(prim_geom, ref myrot);
1900
1901
1902 //d.GeomBoxSetLengths(prim_geom, _size.X, _size.Y, _size.Z);
1903 if (IsPhysical && Body == (IntPtr)0)
1904 {
1905 // Re creates body on size.
1906 // EnableBody also does setMass()
1907 enableBody();
1908 d.BodyEnable(Body);
1909 }
1910
1911 }
1912
1913
1914 _parent_scene.geom_name_map[prim_geom] = oldname;
1915
1916
1917 m_taintsize = _size;
1918 }
1919 public void changeshape(float timestamp)
1920 {
1921 string oldname = _parent_scene.geom_name_map[prim_geom];
1922
1923 // Cleanup of old prim geometry and Bodies
1924 if (IsPhysical && Body != (IntPtr)0)
1925 {
1926 disableBody();
1927 }
1928 d.GeomDestroy(prim_geom);
1929 if (_mesh != null)
1930 {
1931
1932 d.GeomBoxSetLengths(prim_geom, _size.X, _size.Y, _size.Z);
1933
1934 }
1935
1936 // Construction of new prim
1937 if (this._parent_scene.needsMeshing(_pbs))
1938 {
1939 IMesh mesh = _parent_scene.mesher.CreateMesh(oldname, _pbs, _size);
1940 if (mesh != null)
1941 {
1942 setMesh(_parent_scene, mesh);
1943 }
1944 else
1945 {
1946 prim_geom = d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z);
1947 }
1948 }
1949 else
1950 {
1951 prim_geom = d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z);
1952 }
1953 if (IsPhysical && Body == (IntPtr)0)
1954 {
1955 //re-create new body
1956 enableBody();
1957 }
1958 else
1959 {
1960 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
1961 d.Quaternion myrot = new d.Quaternion();
1962 myrot.W = _orientation.w;
1963 myrot.X = _orientation.x;
1964 myrot.Y = _orientation.y;
1965 myrot.Z = _orientation.z;
1966 d.GeomSetQuaternion(prim_geom, ref myrot);
1967 }
1968 _parent_scene.geom_name_map[prim_geom] = oldname;
1969
1970
1971
1972
1973 m_taintshape = false;
1974 }
1975 public override bool IsPhysical
1976 {
1977 get { return m_isphysical; }
1978 set{ m_isphysical = value;}
1979 }
1980 public void setPrimForRemoval()
1981 {
1982 m_taintremove = true;
1983 }
1984
1985 public override bool Flying
1986 {
1987 get { return false; //no flying prims for you
1988 }
1989 set { }
1990 }
1991
1992 public override bool IsColliding
1993 {
1994 get { return iscolliding; }
1995 set { iscolliding = value; }
1996 }
1997 public override bool CollidingGround
1998 {
1999 get { return false; }
2000 set { return; }
2001 }
2002 public override bool CollidingObj
2003 {
2004 get { return false; }
2005 set { return; }
2006 }
2007 public override bool ThrottleUpdates
2008 {
2009 get { return m_throttleUpdates; }
2010 set { m_throttleUpdates=value; }
2011 }
2012
2013 public override PhysicsVector Position
2014 {
2015 get {return _position; }
2016
2017
2018 set
2019 {
2020 _position = value;
2021
2022 }
2023 }
2024
2025 public override PhysicsVector Size
2026 {
2027 get { return _size; }
2028 set
2029 {
2030 _size = value;
2031
2032 }
2033 }
2034
2035 public override PrimitiveBaseShape Shape
2036 {
2037 set
2038 {
2039 _pbs = value;
2040
2041 }
2042 }
2043
2044 public override PhysicsVector Velocity
2045 {
2046 get {
2047 // Averate previous velocity with the new one so
2048 // client object interpolation works a 'little' better
2049 PhysicsVector returnVelocity = new PhysicsVector();
2050 returnVelocity.X = (m_lastVelocity.X + _velocity.X) / 2;
2051 returnVelocity.Y = (m_lastVelocity.Y + _velocity.Y) / 2;
2052 returnVelocity.Z = (m_lastVelocity.Z + _velocity.Z) / 2;
2053 return returnVelocity;
2054 }
2055 set { _velocity = value; }
2056 }
2057
2058 public override bool Kinematic
2059 {
2060 get { return false; }
2061 set { }
2062 }
2063
2064 public override Quaternion Orientation
2065 {
2066 get { return _orientation; }
2067 set
2068 {
2069 _orientation = value;
2070
2071 }
2072 }
2073
2074 public override PhysicsVector Acceleration
2075 {
2076 get { return _acceleration; }
2077 }
2078
2079
2080 public void SetAcceleration(PhysicsVector accel)
2081 {
2082 _acceleration = accel;
2083 }
2084
2085 public override void AddForce(PhysicsVector force)
2086 {
2087 }
2088
2089 public override PhysicsVector RotationalVelocity
2090 {
2091 get{ return m_rotationalVelocity;}
2092 set { m_rotationalVelocity = value; }
2093 }
2094
2095 public void UpdatePositionAndVelocity() {
2096 // no lock; called from Simulate() -- if you call this from elsewhere, gotta lock or do Monitor.Enter/Exit!
2097
2098 if (Body != (IntPtr)0)
2099 {
2100 d.Vector3 vec = d.BodyGetPosition(Body);
2101 d.Quaternion ori = d.BodyGetQuaternion(Body);
2102 d.Vector3 vel = d.BodyGetLinearVel(Body);
2103 d.Vector3 rotvel = d.BodyGetAngularVel(Body);
2104
2105 PhysicsVector l_position = new PhysicsVector();
2106 // kluge to keep things in bounds. ODE lets dead avatars drift away (they should be removed!)
2107 if (vec.X < 0.0f) vec.X = 0.0f;
2108 if (vec.Y < 0.0f) vec.Y = 0.0f;
2109 if (vec.X > 255.95f) vec.X = 255.95f;
2110 if (vec.Y > 255.95f) vec.Y = 255.95f;
2111 m_lastposition = _position;
2112
2113 l_position.X = vec.X;
2114 l_position.Y = vec.Y;
2115 l_position.Z = vec.Z;
2116 if (l_position.Z < 0)
2117 {
2118 // This is so prim that get lost underground don't fall forever and suck up
2119 //
2120 // Sim resources and memory.
2121 // Disables the prim's movement physics....
2122 // It's a hack and will generate a console message if it fails.
2123
2124
2125
2126
2127 //IsPhysical = false;
2128 base.RaiseOutOfBounds(_position);
2129 _velocity.X = 0;
2130 _velocity.Y = 0;
2131 _velocity.Z = 0;
2132 m_rotationalVelocity.X = 0;
2133 m_rotationalVelocity.Y = 0;
2134 m_rotationalVelocity.Z = 0;
2135 base.RequestPhysicsterseUpdate();
2136 m_throttleUpdates = false;
2137 throttleCounter = 0;
2138 _zeroFlag = true;
2139 //outofBounds = true;
2140 }
2141
2142 if ((Math.Abs(m_lastposition.X - l_position.X) < 0.02)
2143 && (Math.Abs(m_lastposition.Y - l_position.Y) < 0.02)
2144 && (Math.Abs(m_lastposition.Z - l_position.Z) < 0.02 ))
2145 {
2146
2147 _zeroFlag = true;
2148 }
2149 else
2150 {
2151 //System.Console.WriteLine(Math.Abs(m_lastposition.X - l_position.X).ToString());
2152 _zeroFlag = false;
2153 }
2154
2155
2156
2157 if (_zeroFlag)
2158 {
2159 // Supposedly this is supposed to tell SceneObjectGroup that
2160 // no more updates need to be sent..
2161 // but it seems broken.
2162 _velocity.X = 0.0f;
2163 _velocity.Y = 0.0f;
2164 _velocity.Z = 0.0f;
2165 //_orientation.w = 0f;
2166 //_orientation.x = 0f;
2167 //_orientation.y = 0f;
2168 //_orientation.z = 0f;
2169 m_rotationalVelocity.X = 0;
2170 m_rotationalVelocity.Y = 0;
2171 m_rotationalVelocity.Z = 0;
2172 if (!m_lastUpdateSent)
2173 {
2174 m_throttleUpdates = false;
2175 throttleCounter = 0;
2176 base.RequestPhysicsterseUpdate();
2177 m_lastUpdateSent = true;
2178 }
2179
2180 }
2181 else
2182 {
2183 m_lastVelocity = _velocity;
2184
2185 _position = l_position;
2186
2187 _velocity.X = vel.X;
2188 _velocity.Y = vel.Y;
2189 _velocity.Z = vel.Z;
2190
2191 m_rotationalVelocity.X = rotvel.X;
2192 m_rotationalVelocity.Y = rotvel.Y;
2193 m_rotationalVelocity.Z = rotvel.Z;
2194 //System.Console.WriteLine("ODE: " + m_rotationalVelocity.ToString());
2195 _orientation.w = ori.W;
2196 _orientation.x = ori.X;
2197 _orientation.y = ori.Y;
2198 _orientation.z = ori.Z;
2199 m_lastUpdateSent = false;
2200 if (!m_throttleUpdates || throttleCounter > 15)
2201 {
2202 base.RequestPhysicsterseUpdate();
2203 }
2204 else
2205 {
2206 throttleCounter++;
2207 }
2208 }
2209 m_lastposition = l_position;
2210 }
2211 else
2212 {
2213 // Not a body.. so Make sure the client isn't interpolating
2214 _velocity.X = 0;
2215 _velocity.Y = 0;
2216 _velocity.Z = 0;
2217 m_rotationalVelocity.X = 0;
2218 m_rotationalVelocity.Y = 0;
2219 m_rotationalVelocity.Z = 0;
2220 _zeroFlag = true;
2221 }
2222
2223 }
2224 public override void SetMomentum(PhysicsVector momentum)
2225 {
2226 }
2227 }
2228}
2229 #endregion \ No newline at end of file