aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics
diff options
context:
space:
mode:
authoropensim2009-09-30 18:51:02 +0200
committeropensim2009-09-30 18:51:02 +0200
commit827b0fb1993c6f9b1289931a1ac38ff2b810952c (patch)
tree3c5e7b7fe5b21fdf159d64f1264a9d41ceac7b69 /OpenSim/Region/Physics
parentFinish the (untested) authentication connector (diff)
downloadopensim-SC_OLD-827b0fb1993c6f9b1289931a1ac38ff2b810952c.zip
opensim-SC_OLD-827b0fb1993c6f9b1289931a1ac38ff2b810952c.tar.gz
opensim-SC_OLD-827b0fb1993c6f9b1289931a1ac38ff2b810952c.tar.bz2
opensim-SC_OLD-827b0fb1993c6f9b1289931a1ac38ff2b810952c.tar.xz
Commit initial version of KittoFlora's vehicle changes
Diffstat (limited to 'OpenSim/Region/Physics')
-rw-r--r--OpenSim/Region/Physics/OdePlugin/ODEDynamics.c_comments (renamed from OpenSim/Region/Physics/OdePlugin/ODEVehicleSettings.cs)558
-rw-r--r--OpenSim/Region/Physics/OdePlugin/ODEDynamics.cs658
-rw-r--r--OpenSim/Region/Physics/OdePlugin/ODEPrim.cs594
-rw-r--r--OpenSim/Region/Physics/OdePlugin/OdePlugin.cs54
4 files changed, 1300 insertions, 564 deletions
diff --git a/OpenSim/Region/Physics/OdePlugin/ODEVehicleSettings.cs b/OpenSim/Region/Physics/OdePlugin/ODEDynamics.c_comments
index a547c3e..1060aa6 100644
--- a/OpenSim/Region/Physics/OdePlugin/ODEVehicleSettings.cs
+++ b/OpenSim/Region/Physics/OdePlugin/ODEDynamics.c_comments
@@ -1,4 +1,16 @@
1/* 1/*
2 * Revised August 26 2009 by Kitto Flora. ODEDynamics.cs replaces
3 * ODEVehicleSettings.cs. It and ODEPrim.cs are re-organised:
4 * ODEPrim.cs contains methods dealing with Prim editing, Prim
5 * characteristics and Kinetic motion.
6 * ODEDynamics.cs contains methods dealing with Prim Physical motion
7 * (dynamics) and the associated settings. Old Linear and angular
8 * motors for dynamic motion have been replace with MoveLinear()
9 * and MoveAngular(); 'Physical' is used only to switch ODE dynamic
10 * simualtion on/off; VEHICAL_TYPE_NONE/VEHICAL_TYPE_<other> is to
11 * switch between 'VEHICLE' parameter use and general dynamics
12 * settings use.
13 *
2 * Copyright (c) Contributors, http://opensimulator.org/ 14 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders. 15 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 * 16 *
@@ -37,10 +49,10 @@ using OpenSim.Region.Physics.Manager;
37 49
38namespace OpenSim.Region.Physics.OdePlugin 50namespace OpenSim.Region.Physics.OdePlugin
39{ 51{
40 public class ODEVehicleSettings 52 public class ODEDynamics
41 { 53 {
42 public Vehicle Type 54 public Vehicle Type
43 { 55 {
44 get { return m_type; } 56 get { return m_type; }
45 } 57 }
46 58
@@ -49,49 +61,71 @@ namespace OpenSim.Region.Physics.OdePlugin
49 get { return m_body; } 61 get { return m_body; }
50 } 62 }
51 63
52 private int frcount = 0; 64 private int frcount = 0; // Used to limit dynamics debug output to
53 // private float frmod = 3.0f; 65 // every 100th frame
54 66
55 private Vehicle m_type = Vehicle.TYPE_NONE;
56 // private OdeScene m_parentScene = null; 67 // private OdeScene m_parentScene = null;
57 private IntPtr m_body = IntPtr.Zero; 68 private IntPtr m_body = IntPtr.Zero;
58 private IntPtr m_jointGroup = IntPtr.Zero; 69 private IntPtr m_jointGroup = IntPtr.Zero;
59 private IntPtr m_aMotor = IntPtr.Zero; 70 private IntPtr m_aMotor = IntPtr.Zero;
60 private IntPtr m_lMotor1 = IntPtr.Zero; 71
61 // private IntPtr m_lMotor2 = IntPtr.Zero;
62 // private IntPtr m_lMotor3 = IntPtr.Zero;
63 72
64 // Vehicle properties 73 // Vehicle properties
65 // private Quaternion m_referenceFrame = Quaternion.Identity; 74 private Vehicle m_type = Vehicle.TYPE_NONE; // If a 'VEHICLE', and what kind
66 private Vector3 m_angularFrictionTimescale = Vector3.Zero; 75 // private Quaternion m_referenceFrame = Quaternion.Identity; // Axis modifier
67 private Vector3 m_angularMotorDirection = Vector3.Zero; 76 private VehicleFlag m_flags = (VehicleFlag) 0; // Boolean settings:
68 private Vector3 m_angularMotorDirectionLASTSET = Vector3.Zero; 77 // HOVER_TERRAIN_ONLY
78 // HOVER_GLOBAL_HEIGHT
79 // NO_DEFLECTION_UP
80 // HOVER_WATER_ONLY
81 // HOVER_UP_ONLY
82 // LIMIT_MOTOR_UP
83 // LIMIT_ROLL_ONLY
84
85 // Linear properties
86 private Vector3 m_linearMotorDirection = Vector3.Zero; // velocity requested by LSL, decayed by time
87 private Vector3 m_linearMotorDirectionLASTSET = Vector3.Zero; // velocity requested by LSL
88 private Vector3 m_dir = Vector3.Zero; // velocity applied to body
69 private Vector3 m_linearFrictionTimescale = Vector3.Zero; 89 private Vector3 m_linearFrictionTimescale = Vector3.Zero;
70 private Vector3 m_linearMotorDirection = Vector3.Zero; 90 private float m_linearMotorDecayTimescale = 0;
71 private Vector3 m_linearMotorDirectionLASTSET = Vector3.Zero; 91 private float m_linearMotorTimescale = 0;
92 private Vector3 m_lastLinearVelocityVector = Vector3.Zero;
93 // private bool m_LinearMotorSetLastFrame = false;
72 // private Vector3 m_linearMotorOffset = Vector3.Zero; 94 // private Vector3 m_linearMotorOffset = Vector3.Zero;
73 // private float m_angularDeflectionEfficiency = 0; 95
74 // private float m_angularDeflectionTimescale = 0; 96 //Angular properties
97 private Vector3 m_angularMotorDirection = Vector3.Zero;
98 private Vector3 m_angularMotorDirectionLASTSET = Vector3.Zero;
99 private Vector3 m_angularFrictionTimescale = Vector3.Zero;
75 private float m_angularMotorDecayTimescale = 0; 100 private float m_angularMotorDecayTimescale = 0;
76 private float m_angularMotorTimescale = 0; 101 private float m_angularMotorTimescale = 0;
102 private Vector3 m_lastAngularVelocityVector = Vector3.Zero;
103
104 //Deflection properties
105 // private float m_angularDeflectionEfficiency = 0;
106 // private float m_angularDeflectionTimescale = 0;
107 // private float m_linearDeflectionEfficiency = 0;
108 // private float m_linearDeflectionTimescale = 0;
109
110 //Banking properties
77 // private float m_bankingEfficiency = 0; 111 // private float m_bankingEfficiency = 0;
78 // private float m_bankingMix = 0; 112 // private float m_bankingMix = 0;
79 // private float m_bankingTimescale = 0; 113 // private float m_bankingTimescale = 0;
80 // private float m_buoyancy = 0; 114
81 // private float m_hoverHeight = 0; 115 //Hover and Buoyancy properties
82 // private float m_hoverEfficiency = 0; 116 private float m_VhoverHeight = 0f;
83 // private float m_hoverTimescale = 0; 117 private float m_VhoverEfficiency = 0f;
84 // private float m_linearDeflectionEfficiency = 0; 118 private float m_VhoverTimescale = 0f;
85 // private float m_linearDeflectionTimescale = 0; 119 private float m_VhoverTargetHeight = -1.0f; // if <0 then no hover, else its the current target height
86 private float m_linearMotorDecayTimescale = 0; 120 private float m_VehicleBuoyancy = 0f; //KF: m_VehicleBuoyancy is set by VEHICLE_BUOYANCY for a vehicle.
87 private float m_linearMotorTimescale = 0; 121 // Modifies gravity. Slider between -1 (double-gravity) and 1 (full anti-gravity)
122 // KF: So far I have found no good method to combine a script-requested .Z velocity and gravity.
123 // Therefore only m_VehicleBuoyancy=1 (0g) will use the script-requested .Z velocity.
124
125 //Attractor properties
88 private float m_verticalAttractionEfficiency = 0; 126 private float m_verticalAttractionEfficiency = 0;
89 private float m_verticalAttractionTimescale = 0; 127 private float m_verticalAttractionTimescale = 0;
90 private Vector3 m_lastLinearVelocityVector = Vector3.Zero; 128
91 private Vector3 m_lastAngularVelocityVector = Vector3.Zero;
92 private VehicleFlag m_flags = (VehicleFlag) 0;
93
94 // private bool m_LinearMotorSetLastFrame = false;
95 129
96 130
97 131
@@ -129,17 +163,21 @@ namespace OpenSim.Region.Physics.OdePlugin
129 // m_bankingTimescale = pValue; 163 // m_bankingTimescale = pValue;
130 break; 164 break;
131 case Vehicle.BUOYANCY: 165 case Vehicle.BUOYANCY:
132 // m_buoyancy = pValue; 166 if (pValue < -1f) pValue = -1f;
167 if (pValue > 1f) pValue = 1f;
168 m_VehicleBuoyancy = pValue;
133 break; 169 break;
134 case Vehicle.HOVER_EFFICIENCY: 170 case Vehicle.HOVER_EFFICIENCY:
135 // m_hoverEfficiency = pValue; 171 if (pValue < 0f) pValue = 0f;
172 if (pValue > 1f) pValue = 1f;
173 m_VhoverEfficiency = pValue;
136 break; 174 break;
137 case Vehicle.HOVER_HEIGHT: 175 case Vehicle.HOVER_HEIGHT:
138 // m_hoverHeight = pValue; 176 m_VhoverHeight = pValue;
139 break; 177 break;
140 case Vehicle.HOVER_TIMESCALE: 178 case Vehicle.HOVER_TIMESCALE:
141 if (pValue < 0.01f) pValue = 0.01f; 179 if (pValue < 0.01f) pValue = 0.01f;
142 // m_hoverTimescale = pValue; 180 m_VhoverTimescale = pValue;
143 break; 181 break;
144 case Vehicle.LINEAR_DEFLECTION_EFFICIENCY: 182 case Vehicle.LINEAR_DEFLECTION_EFFICIENCY:
145 if (pValue < 0.01f) pValue = 0.01f; 183 if (pValue < 0.01f) pValue = 0.01f;
@@ -158,7 +196,8 @@ namespace OpenSim.Region.Physics.OdePlugin
158 m_linearMotorTimescale = pValue; 196 m_linearMotorTimescale = pValue;
159 break; 197 break;
160 case Vehicle.VERTICAL_ATTRACTION_EFFICIENCY: 198 case Vehicle.VERTICAL_ATTRACTION_EFFICIENCY:
161 if (pValue < 0.01f) pValue = 0.01f; 199 if (pValue < 0.0f) pValue = 0.0f;
200 if (pValue > 1.0f) pValue = 1.0f;
162 m_verticalAttractionEfficiency = pValue; 201 m_verticalAttractionEfficiency = pValue;
163 break; 202 break;
164 case Vehicle.VERTICAL_ATTRACTION_TIMESCALE: 203 case Vehicle.VERTICAL_ATTRACTION_TIMESCALE:
@@ -187,8 +226,8 @@ namespace OpenSim.Region.Physics.OdePlugin
187 break; 226 break;
188 227
189 } 228 }
190 Reset(); 229
191 } 230 }//end ProcessFloatVehicleParam
192 231
193 internal void ProcessVectorVehicleParam(Vehicle pParam, PhysicsVector pValue) 232 internal void ProcessVectorVehicleParam(Vehicle pParam, PhysicsVector pValue)
194 { 233 {
@@ -212,8 +251,8 @@ namespace OpenSim.Region.Physics.OdePlugin
212 // m_linearMotorOffset = new Vector3(pValue.X, pValue.Y, pValue.Z); 251 // m_linearMotorOffset = new Vector3(pValue.X, pValue.Y, pValue.Z);
213 break; 252 break;
214 } 253 }
215 Reset(); 254
216 } 255 }//end ProcessVectorVehicleParam
217 256
218 internal void ProcessRotationVehicleParam(Vehicle pParam, Quaternion pValue) 257 internal void ProcessRotationVehicleParam(Vehicle pParam, Quaternion pValue)
219 { 258 {
@@ -223,113 +262,14 @@ namespace OpenSim.Region.Physics.OdePlugin
223 // m_referenceFrame = pValue; 262 // m_referenceFrame = pValue;
224 break; 263 break;
225 } 264 }
226 Reset();
227 }
228
229 internal void ProcessTypeChange(Vehicle pType)
230 {
231 if (m_type == Vehicle.TYPE_NONE && pType != Vehicle.TYPE_NONE)
232 {
233 // Activate whatever it is
234 SetDefaultsForType(pType);
235 Reset();
236 }
237 else if (m_type != Vehicle.TYPE_NONE && pType != Vehicle.TYPE_NONE)
238 {
239 // Set properties
240 SetDefaultsForType(pType);
241 // then reset
242 Reset();
243 }
244 else if (m_type != Vehicle.TYPE_NONE && pType == Vehicle.TYPE_NONE)
245 {
246 m_type = pType;
247 Destroy();
248 }
249 }
250
251 internal void Disable()
252 {
253 if (m_body == IntPtr.Zero || m_type == Vehicle.TYPE_NONE)
254 return;
255
256 if (m_aMotor != IntPtr.Zero)
257 {
258
259 }
260
261 }
262
263 internal void Enable(IntPtr pBody, OdeScene pParentScene)
264 {
265 if (m_type == Vehicle.TYPE_NONE)
266 return;
267
268 m_body = pBody;
269 // m_parentScene = pParentScene;
270 if (m_jointGroup == IntPtr.Zero)
271 m_jointGroup = d.JointGroupCreate(3);
272
273 if (pBody != IntPtr.Zero)
274 {
275
276 if (m_lMotor1 == IntPtr.Zero)
277 {
278 d.BodySetAutoDisableFlag(Body, false);
279 m_lMotor1 = d.JointCreateLMotor(pParentScene.world, m_jointGroup);
280 d.JointSetLMotorNumAxes(m_lMotor1, 1);
281 d.JointAttach(m_lMotor1, Body, IntPtr.Zero);
282 }
283
284 if (m_aMotor == IntPtr.Zero)
285 {
286 m_aMotor = d.JointCreateAMotor(pParentScene.world, m_jointGroup);
287 d.JointSetAMotorNumAxes(m_aMotor, 3);
288 d.JointAttach(m_aMotor, Body, IntPtr.Zero);
289 }
290 }
291 }
292
293 internal void Reset()
294 {
295 if (m_body == IntPtr.Zero || m_type == Vehicle.TYPE_NONE)
296 return;
297 265
298 } 266 }//end ProcessRotationVehicleParam
299 267
300 internal void Destroy() 268 internal void ProcessTypeChange(Vehicle pType)
301 {
302 if (m_body == IntPtr.Zero || m_type == Vehicle.TYPE_NONE)
303 return;
304 if (m_aMotor != IntPtr.Zero)
305 {
306 d.JointDestroy(m_aMotor);
307 }
308 if (m_lMotor1 != IntPtr.Zero)
309 {
310 d.JointDestroy(m_lMotor1);
311 }
312
313 }
314
315 internal void Step(float pTimestep)
316 {
317 if (m_body == IntPtr.Zero || m_type == Vehicle.TYPE_NONE)
318 return;
319 frcount++;
320 if (frcount > 100)
321 frcount = 0;
322
323 VerticalAttractor(pTimestep);
324 LinearMotor(pTimestep);
325
326
327 AngularMotor(pTimestep);
328
329 }
330
331 private void SetDefaultsForType(Vehicle pType)
332 { 269 {
270Console.WriteLine("ProcessTypeChange to " + pType);
271
272 // Set Defaults For Type
333 m_type = pType; 273 m_type = pType;
334 switch (pType) 274 switch (pType)
335 { 275 {
@@ -342,10 +282,10 @@ namespace OpenSim.Region.Physics.OdePlugin
342 m_angularMotorDirection = Vector3.Zero; 282 m_angularMotorDirection = Vector3.Zero;
343 m_angularMotorTimescale = 1000; 283 m_angularMotorTimescale = 1000;
344 m_angularMotorDecayTimescale = 120; 284 m_angularMotorDecayTimescale = 120;
345 // m_hoverHeight = 0; 285 m_VhoverHeight = 0;
346 // m_hoverEfficiency = 10; 286 m_VhoverEfficiency = 1;
347 // m_hoverTimescale = 10; 287 m_VhoverTimescale = 10;
348 // m_buoyancy = 0; 288 m_VehicleBuoyancy = 0;
349 // m_linearDeflectionEfficiency = 1; 289 // m_linearDeflectionEfficiency = 1;
350 // m_linearDeflectionTimescale = 1; 290 // m_linearDeflectionTimescale = 1;
351 // m_angularDeflectionEfficiency = 1; 291 // m_angularDeflectionEfficiency = 1;
@@ -368,10 +308,10 @@ namespace OpenSim.Region.Physics.OdePlugin
368 m_angularMotorDirection = Vector3.Zero; 308 m_angularMotorDirection = Vector3.Zero;
369 m_angularMotorTimescale = 1; 309 m_angularMotorTimescale = 1;
370 m_angularMotorDecayTimescale = 0.8f; 310 m_angularMotorDecayTimescale = 0.8f;
371 // m_hoverHeight = 0; 311 m_VhoverHeight = 0;
372 // // m_hoverEfficiency = 0; 312 m_VhoverEfficiency = 0;
373 // // m_hoverTimescale = 1000; 313 m_VhoverTimescale = 1000;
374 // // m_buoyancy = 0; 314 m_VehicleBuoyancy = 0;
375 // // m_linearDeflectionEfficiency = 1; 315 // // m_linearDeflectionEfficiency = 1;
376 // // m_linearDeflectionTimescale = 2; 316 // // m_linearDeflectionTimescale = 2;
377 // // m_angularDeflectionEfficiency = 0; 317 // // m_angularDeflectionEfficiency = 0;
@@ -395,10 +335,10 @@ namespace OpenSim.Region.Physics.OdePlugin
395 m_angularMotorDirection = Vector3.Zero; 335 m_angularMotorDirection = Vector3.Zero;
396 m_angularMotorTimescale = 4; 336 m_angularMotorTimescale = 4;
397 m_angularMotorDecayTimescale = 4; 337 m_angularMotorDecayTimescale = 4;
398 // m_hoverHeight = 0; 338 m_VhoverHeight = 0;
399 // m_hoverEfficiency = 0.5f; 339 m_VhoverEfficiency = 0.5f;
400 // m_hoverTimescale = 2; 340 m_VhoverTimescale = 2;
401 // m_buoyancy = 1; 341 m_VehicleBuoyancy = 1;
402 // m_linearDeflectionEfficiency = 0.5f; 342 // m_linearDeflectionEfficiency = 0.5f;
403 // m_linearDeflectionTimescale = 3; 343 // m_linearDeflectionTimescale = 3;
404 // m_angularDeflectionEfficiency = 0.5f; 344 // m_angularDeflectionEfficiency = 0.5f;
@@ -409,8 +349,9 @@ namespace OpenSim.Region.Physics.OdePlugin
409 // m_bankingMix = 0.8f; 349 // m_bankingMix = 0.8f;
410 // m_bankingTimescale = 1; 350 // m_bankingTimescale = 1;
411 // m_referenceFrame = Quaternion.Identity; 351 // m_referenceFrame = Quaternion.Identity;
412 m_flags &= ~(VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.LIMIT_ROLL_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT); 352 m_flags &= ~(VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.LIMIT_ROLL_ONLY |
413 m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_UP_ONLY | 353 VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY);
354 m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.HOVER_WATER_ONLY |
414 VehicleFlag.LIMIT_MOTOR_UP); 355 VehicleFlag.LIMIT_MOTOR_UP);
415 break; 356 break;
416 case Vehicle.TYPE_AIRPLANE: 357 case Vehicle.TYPE_AIRPLANE:
@@ -422,10 +363,10 @@ namespace OpenSim.Region.Physics.OdePlugin
422 m_angularMotorDirection = Vector3.Zero; 363 m_angularMotorDirection = Vector3.Zero;
423 m_angularMotorTimescale = 4; 364 m_angularMotorTimescale = 4;
424 m_angularMotorDecayTimescale = 4; 365 m_angularMotorDecayTimescale = 4;
425 // m_hoverHeight = 0; 366 m_VhoverHeight = 0;
426 // m_hoverEfficiency = 0.5f; 367 m_VhoverEfficiency = 0.5f;
427 // m_hoverTimescale = 1000; 368 m_VhoverTimescale = 1000;
428 // m_buoyancy = 0; 369 m_VehicleBuoyancy = 0;
429 // m_linearDeflectionEfficiency = 0.5f; 370 // m_linearDeflectionEfficiency = 0.5f;
430 // m_linearDeflectionTimescale = 3; 371 // m_linearDeflectionTimescale = 3;
431 // m_angularDeflectionEfficiency = 1; 372 // m_angularDeflectionEfficiency = 1;
@@ -449,10 +390,10 @@ namespace OpenSim.Region.Physics.OdePlugin
449 m_angularMotorDirection = Vector3.Zero; 390 m_angularMotorDirection = Vector3.Zero;
450 m_angularMotorTimescale = 6; 391 m_angularMotorTimescale = 6;
451 m_angularMotorDecayTimescale = 10; 392 m_angularMotorDecayTimescale = 10;
452 // m_hoverHeight = 5; 393 m_VhoverHeight = 5;
453 // m_hoverEfficiency = 0.8f; 394 m_VhoverEfficiency = 0.8f;
454 // m_hoverTimescale = 10; 395 m_VhoverTimescale = 10;
455 // m_buoyancy = 1; 396 m_VehicleBuoyancy = 1;
456 // m_linearDeflectionEfficiency = 0; 397 // m_linearDeflectionEfficiency = 0;
457 // m_linearDeflectionTimescale = 5; 398 // m_linearDeflectionTimescale = 5;
458 // m_angularDeflectionEfficiency = 0; 399 // m_angularDeflectionEfficiency = 0;
@@ -463,106 +404,165 @@ namespace OpenSim.Region.Physics.OdePlugin
463 // m_bankingMix = 0.7f; 404 // m_bankingMix = 0.7f;
464 // m_bankingTimescale = 5; 405 // m_bankingTimescale = 5;
465 // m_referenceFrame = Quaternion.Identity; 406 // m_referenceFrame = Quaternion.Identity;
466 m_flags = (VehicleFlag)0; 407 m_flags &= ~(VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY |
408 VehicleFlag.HOVER_UP_ONLY | VehicleFlag.LIMIT_MOTOR_UP);
409 m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT);
467 break; 410 break;
468 411
469 } 412 }
470 } 413 }//end SetDefaultsForType
471
472 private void VerticalAttractor(float pTimestep)
473 {
474 // The purpose of this routine here is to quickly stabilize the Body while it's popped up in the air.
475 // The amotor needs a few seconds to stabilize so without it, the avatar shoots up sky high when you
476 // change appearance and when you enter the simulator
477 // After this routine is done, the amotor stabilizes much quicker
478 d.Mass objMass;
479 d.BodyGetMass(Body, out objMass);
480 //d.BodyGetS
481 414
482 d.Vector3 feet; 415 internal void Enable(IntPtr pBody, OdeScene pParentScene)
483 d.Vector3 head; 416 {
484 d.BodyGetRelPointPos(m_body, 0.0f, 0.0f, -1.0f, out feet); 417//Console.WriteLine("Enable m_type=" + m_type + " m_VehicleBuoyancy=" + m_VehicleBuoyancy);
485 d.BodyGetRelPointPos(m_body, 0.0f, 0.0f, 1.0f, out head); 418 if (m_type == Vehicle.TYPE_NONE)
486 float posture = head.Z - feet.Z; 419 return;
487 420
488 //Console.WriteLine(String.Format("head: <{0},{1},{2}>, feet:<{3},{4},{5}> diff:<{6},{7},{8}>", head.X, head.Y, head.Z, feet.X, 421 m_body = pBody;
489 // feet.Y, feet.Z, head.X - feet.X, head.Y - feet.Y, head.Z - feet.Z)); 422 //KF: This used to set up the linear and angular joints
490 //Console.WriteLine(String.Format("diff:<{0},{1},{2}>",head.X - feet.X, head.Y - feet.Y, head.Z - feet.Z));
491
492 // restoring force proportional to lack of posture:
493 float servo = (2.5f - posture) * (objMass.mass * m_verticalAttractionEfficiency / (m_verticalAttractionTimescale * pTimestep)) * objMass.mass;
494 d.BodyAddForceAtRelPos(m_body, 0.0f, 0.0f, servo, 0.0f, 0.0f, 1.0f);
495 d.BodyAddForceAtRelPos(m_body, 0.0f, 0.0f, -servo, 0.0f, 0.0f, -1.0f);
496 //d.BodyAddTorque(m_body, (head.X - feet.X) * servo, (head.Y - feet.Y) * servo, (head.Z - feet.Z) * servo);
497 //d.Matrix3 bodyrotation = d.BodyGetRotation(Body);
498 //m_log.Info("[PHYSICSAV]: Rotation: " + bodyrotation.M00 + " : " + bodyrotation.M01 + " : " + bodyrotation.M02 + " : " + bodyrotation.M10 + " : " + bodyrotation.M11 + " : " + bodyrotation.M12 + " : " + bodyrotation.M20 + " : " + bodyrotation.M21 + " : " + bodyrotation.M22);
499 } 423 }
500 424
501 private void LinearMotor(float pTimestep) 425 internal void Step(float pTimestep, OdeScene pParentScene)
502 { 426 {
427 if (m_body == IntPtr.Zero || m_type == Vehicle.TYPE_NONE)
428 return;
429 frcount++; // used to limit debug comment output
430 if (frcount > 100)
431 frcount = 0;
503 432
504 if (!m_linearMotorDirection.ApproxEquals(Vector3.Zero, 0.01f)) 433 MoveLinear(pTimestep, pParentScene);
434 MoveAngular(pTimestep);
435 }// end Step
436
437 private void MoveLinear(float pTimestep, OdeScene _pParentScene)
438 {
439 if (!m_linearMotorDirection.ApproxEquals(Vector3.Zero, 0.01f)) // requested m_linearMotorDirection is significant
505 { 440 {
506 441 if(!d.BodyIsEnabled (Body)) d.BodyEnable (Body);
507 Vector3 addAmount = m_linearMotorDirection/(m_linearMotorTimescale/pTimestep);
508 m_lastLinearVelocityVector += (addAmount*10);
509 442
443 // add drive to body
444 Vector3 addAmount = m_linearMotorDirection/(m_linearMotorTimescale/pTimestep);
445 m_lastLinearVelocityVector += (addAmount*10); // lastLinearVelocityVector is the current body velocity vector?
446
510 // This will work temporarily, but we really need to compare speed on an axis 447 // This will work temporarily, but we really need to compare speed on an axis
448 // KF: Limit body velocity to applied velocity?
511 if (Math.Abs(m_lastLinearVelocityVector.X) > Math.Abs(m_linearMotorDirectionLASTSET.X)) 449 if (Math.Abs(m_lastLinearVelocityVector.X) > Math.Abs(m_linearMotorDirectionLASTSET.X))
512 m_lastLinearVelocityVector.X = m_linearMotorDirectionLASTSET.X; 450 m_lastLinearVelocityVector.X = m_linearMotorDirectionLASTSET.X;
513 if (Math.Abs(m_lastLinearVelocityVector.Y) > Math.Abs(m_linearMotorDirectionLASTSET.Y)) 451 if (Math.Abs(m_lastLinearVelocityVector.Y) > Math.Abs(m_linearMotorDirectionLASTSET.Y))
514 m_lastLinearVelocityVector.Y = m_linearMotorDirectionLASTSET.Y; 452 m_lastLinearVelocityVector.Y = m_linearMotorDirectionLASTSET.Y;
515 if (Math.Abs(m_lastLinearVelocityVector.Z) > Math.Abs(m_linearMotorDirectionLASTSET.Z)) 453 if (Math.Abs(m_lastLinearVelocityVector.Z) > Math.Abs(m_linearMotorDirectionLASTSET.Z))
516 m_lastLinearVelocityVector.Z = m_linearMotorDirectionLASTSET.Z; 454 m_lastLinearVelocityVector.Z = m_linearMotorDirectionLASTSET.Z;
517 //Console.WriteLine("add: " + addAmount); 455
518 456 // decay applied velocity
519 Vector3 decayfraction = ((Vector3.One/(m_linearMotorDecayTimescale/pTimestep))); 457 Vector3 decayfraction = ((Vector3.One/(m_linearMotorDecayTimescale/pTimestep)));
520 //Console.WriteLine("decay: " + decayfraction); 458 //Console.WriteLine("decay: " + decayfraction);
521
522 m_linearMotorDirection -= m_linearMotorDirection * decayfraction; 459 m_linearMotorDirection -= m_linearMotorDirection * decayfraction;
523 //Console.WriteLine("actual: " + m_linearMotorDirection); 460 //Console.WriteLine("actual: " + m_linearMotorDirection);
524 } 461 }
525 462 else
526 //System.Console.WriteLine(m_linearMotorDirection + " " + m_lastLinearVelocityVector); 463 { // requested is not significant
527 464 // if what remains of applied is small, zero it.
528 SetLinearMotorProperties(); 465 if (m_lastLinearVelocityVector.ApproxEquals(Vector3.Zero, 0.01f))
529 466 m_lastLinearVelocityVector = Vector3.Zero;
467 }
468
469
470 // convert requested object velocity to world-referenced vector
471 m_dir = m_lastLinearVelocityVector;
472 d.Quaternion rot = d.BodyGetQuaternion(Body);
473 Quaternion rotq = new Quaternion(rot.X, rot.Y, rot.Z, rot.W); // rotq = rotation of object
474 m_dir *= rotq; // apply obj rotation to velocity vector
475
476 // add Gravity andBuoyancy
477 // KF: So far I have found no good method to combine a script-requested
478 // .Z velocity and gravity. Therefore only 0g will used script-requested
479 // .Z velocity. >0g (m_VehicleBuoyancy < 1) will used modified gravity only.
480 Vector3 grav = Vector3.Zero;
481 if(m_VehicleBuoyancy < 1.0f)
482 {
483 // There is some gravity, make a gravity force vector
484 // that is applied after object velocity.
485 d.Mass objMass;
486 d.BodyGetMass(Body, out objMass);
487 // m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g;
488 grav.Z = _pParentScene.gravityz * objMass.mass * (1f - m_VehicleBuoyancy);
489 // Preserve the current Z velocity
490 d.Vector3 vel_now = d.BodyGetLinearVel(Body);
491 m_dir.Z = vel_now.Z; // Preserve the accumulated falling velocity
492 } // else its 1.0, no gravity.
493
494 // Check if hovering
495 if( (m_flags & (VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT)) != 0)
496 {
497 // We should hover, get the target height
498 d.Vector3 pos = d.BodyGetPosition(Body);
499 if((m_flags & VehicleFlag.HOVER_WATER_ONLY) == VehicleFlag.HOVER_WATER_ONLY)
500 {
501 m_VhoverTargetHeight = _pParentScene.GetWaterLevel() + m_VhoverHeight;
502 }
503 else if((m_flags & VehicleFlag.HOVER_TERRAIN_ONLY) == VehicleFlag.HOVER_TERRAIN_ONLY)
504 {
505 m_VhoverTargetHeight = _pParentScene.GetTerrainHeightAtXY(pos.X, pos.Y) + m_VhoverHeight;
506 }
507 else if((m_flags & VehicleFlag.HOVER_GLOBAL_HEIGHT) == VehicleFlag.HOVER_GLOBAL_HEIGHT)
508 {
509 m_VhoverTargetHeight = m_VhoverHeight;
510 }
511
512 if((m_flags & VehicleFlag.HOVER_UP_ONLY) == VehicleFlag.HOVER_UP_ONLY)
513 {
514 // If body is aready heigher, use its height as target height
515 if(pos.Z > m_VhoverTargetHeight) m_VhoverTargetHeight = pos.Z;
516 }
517
518// m_VhoverEfficiency = 0f; // 0=boucy, 1=Crit.damped
519// m_VhoverTimescale = 0f; // time to acheive height
520// pTimestep is time since last frame,in secs
521 float herr0 = pos.Z - m_VhoverTargetHeight;
522//if(frcount == 0) Console.WriteLine("herr0=" + herr0);
523 // Replace Vertical speed with correction figure if significant
524 if(Math.Abs(herr0) > 0.01f )
525 {
526 d.Mass objMass;
527 d.BodyGetMass(Body, out objMass);
528 m_dir.Z = - ( (herr0 * pTimestep * 50.0f) / m_VhoverTimescale);
529 // m_VhoverEfficiency is not yet implemented
530 }
531 else
532 {
533 m_dir.Z = 0f;
534 }
535 }
536
537 // Apply velocity
538 d.BodySetLinearVel(Body, m_dir.X, m_dir.Y, m_dir.Z);
539//if(frcount == 0) Console.WriteLine("Move " + Body + ":"+ m_dir.X + " " + m_dir.Y + " " + m_dir.Z);
540 // apply gravity force
541 d.BodyAddForce(Body, grav.X, grav.Y, grav.Z);
542//if(frcount == 0) Console.WriteLine("Force " + Body + ":" + grav.X + " " + grav.Y + " " + grav.Z);
543
544
545 // apply friction
530 Vector3 decayamount = Vector3.One / (m_linearFrictionTimescale / pTimestep); 546 Vector3 decayamount = Vector3.One / (m_linearFrictionTimescale / pTimestep);
531 m_lastLinearVelocityVector -= m_lastLinearVelocityVector * decayamount; 547 m_lastLinearVelocityVector -= m_lastLinearVelocityVector * decayamount;
532 548 } // end MoveLinear()
533 //m_linearMotorDirection *= decayamount; 549
534 550 private void MoveAngular(float pTimestep)
535 }
536
537 private void SetLinearMotorProperties()
538 {
539 Vector3 dirNorm = m_lastLinearVelocityVector;
540 dirNorm.Normalize();
541
542 d.Mass objMass;
543 d.BodyGetMass(Body, out objMass);
544 d.Quaternion rot = d.BodyGetQuaternion(Body);
545 Quaternion rotq = new Quaternion(rot.X, rot.Y, rot.Z, rot.W);
546 dirNorm *= rotq;
547 if (m_lMotor1 != IntPtr.Zero)
548 {
549
550 d.JointSetLMotorAxis(m_lMotor1, 0, 1, dirNorm.X, dirNorm.Y, dirNorm.Z);
551 d.JointSetLMotorParam(m_lMotor1, (int)dParam.Vel, m_lastLinearVelocityVector.Length());
552
553 d.JointSetLMotorParam(m_lMotor1, (int)dParam.FMax, 35f * objMass.mass);
554 }
555
556 }
557
558 private void AngularMotor(float pTimestep)
559 { 551 {
552
553 // m_angularMotorDirection is the latest value from the script, and is decayed here
554 // m_angularMotorDirectionLASTSET is the latest value from the script
555 // m_lastAngularVelocityVector is what is being applied to the Body, varied up and down here
556
560 if (!m_angularMotorDirection.ApproxEquals(Vector3.Zero, 0.01f)) 557 if (!m_angularMotorDirection.ApproxEquals(Vector3.Zero, 0.01f))
561 { 558 {
562 559 if(!d.BodyIsEnabled (Body)) d.BodyEnable (Body);
560 // ramp up to new value
563 Vector3 addAmount = m_angularMotorDirection / (m_angularMotorTimescale / pTimestep); 561 Vector3 addAmount = m_angularMotorDirection / (m_angularMotorTimescale / pTimestep);
564 m_lastAngularVelocityVector += (addAmount * 10); 562 m_lastAngularVelocityVector += (addAmount * 10f);
563//if(frcount == 0) Console.WriteLine("add: " + addAmount);
565 564
565 // limit applied value to what was set by script
566 // This will work temporarily, but we really need to compare speed on an axis 566 // This will work temporarily, but we really need to compare speed on an axis
567 if (Math.Abs(m_lastAngularVelocityVector.X) > Math.Abs(m_angularMotorDirectionLASTSET.X)) 567 if (Math.Abs(m_lastAngularVelocityVector.X) > Math.Abs(m_angularMotorDirectionLASTSET.X))
568 m_lastAngularVelocityVector.X = m_angularMotorDirectionLASTSET.X; 568 m_lastAngularVelocityVector.X = m_angularMotorDirectionLASTSET.X;
@@ -570,57 +570,61 @@ namespace OpenSim.Region.Physics.OdePlugin
570 m_lastAngularVelocityVector.Y = m_angularMotorDirectionLASTSET.Y; 570 m_lastAngularVelocityVector.Y = m_angularMotorDirectionLASTSET.Y;
571 if (Math.Abs(m_lastAngularVelocityVector.Z) > Math.Abs(m_angularMotorDirectionLASTSET.Z)) 571 if (Math.Abs(m_lastAngularVelocityVector.Z) > Math.Abs(m_angularMotorDirectionLASTSET.Z))
572 m_lastAngularVelocityVector.Z = m_angularMotorDirectionLASTSET.Z; 572 m_lastAngularVelocityVector.Z = m_angularMotorDirectionLASTSET.Z;
573 //Console.WriteLine("add: " + addAmount);
574 573
574 // decay the requested value
575 Vector3 decayfraction = ((Vector3.One / (m_angularMotorDecayTimescale / pTimestep))); 575 Vector3 decayfraction = ((Vector3.One / (m_angularMotorDecayTimescale / pTimestep)));
576 //Console.WriteLine("decay: " + decayfraction); 576 //Console.WriteLine("decay: " + decayfraction);
577
578 m_angularMotorDirection -= m_angularMotorDirection * decayfraction; 577 m_angularMotorDirection -= m_angularMotorDirection * decayfraction;
579 //Console.WriteLine("actual: " + m_linearMotorDirection); 578 //Console.WriteLine("actual: " + m_linearMotorDirection);
580 } 579 }
581 580 // KF: m_lastAngularVelocityVector is rotational speed in rad/sec ?
582 //System.Console.WriteLine(m_linearMotorDirection + " " + m_lastLinearVelocityVector); 581
583 582 // Vertical attractor section
584 SetAngularMotorProperties(); 583
585 584// d.Mass objMass;
585// d.BodyGetMass(Body, out objMass);
586// float servo = 100f * objMass.mass * m_verticalAttractionEfficiency / (m_verticalAttractionTimescale * pTimestep);
587 float servo = 0.1f * m_verticalAttractionEfficiency / (m_verticalAttractionTimescale * pTimestep);
588 // get present body rotation
589 d.Quaternion rot = d.BodyGetQuaternion(Body);
590 Quaternion rotq = new Quaternion(rot.X, rot.Y, rot.Z, rot.W);
591 // make a vector pointing up
592 Vector3 verterr = Vector3.Zero;
593 verterr.Z = 1.0f;
594 // rotate it to Body Angle
595 verterr = verterr * rotq;
596 // verterr.X and .Y are the World error ammounts. They are 0 when there is no error (Vehicle Body is 'vertical'), and .Z will be 1.
597 // As the body leans to its side |.X| will increase to 1 and .Z fall to 0. As body inverts |.X| will fall and .Z will go
598 // negative. Similar for tilt and |.Y|. .X and .Y must be modulated to prevent a stable inverted body.
599 if (verterr.Z < 0.0f)
600 {
601 verterr.X = 2.0f - verterr.X;
602 verterr.Y = 2.0f - verterr.Y;
603 }
604 // Error is 0 (no error) to +/- 2 (max error)
605 // scale it by servo
606 verterr = verterr * servo;
607
608 // rotate to object frame
609 // verterr = verterr * rotq;
610
611 // As the body rotates around the X axis, then verterr.Y increases; Rotated around Y then .X increases, so
612 // Change Body angular velocity X based on Y, and Y based on X. Z is not changed.
613 m_lastAngularVelocityVector.X += verterr.Y;
614 m_lastAngularVelocityVector.Y -= verterr.X;
615/*
616if(frcount == 0)
617 {
618// Console.WriteLine("AngleMotor " + m_lastAngularVelocityVector);
619 Console.WriteLine(String.Format("VA Body:{0} servo:{1} err:<{2},{3},{4}> VAE:{5}",
620 Body, servo, verterr.X, verterr.Y, verterr.Z, m_verticalAttractionEfficiency));
621 }
622 */
623 d.BodySetAngularVel (Body, m_lastAngularVelocityVector.X, m_lastAngularVelocityVector.Y, m_lastAngularVelocityVector.Z);
624 // apply friction
586 Vector3 decayamount = Vector3.One / (m_angularFrictionTimescale / pTimestep); 625 Vector3 decayamount = Vector3.One / (m_angularFrictionTimescale / pTimestep);
587 m_lastAngularVelocityVector -= m_lastAngularVelocityVector * decayamount; 626 m_lastAngularVelocityVector -= m_lastAngularVelocityVector * decayamount;
588 627
589 //m_linearMotorDirection *= decayamount; 628 } //end MoveAngular
590
591 }
592 private void SetAngularMotorProperties()
593 {
594
595
596
597 d.Mass objMass;
598 d.BodyGetMass(Body, out objMass);
599 //d.Quaternion rot = d.BodyGetQuaternion(Body);
600 //Quaternion rotq = new Quaternion(rot.X, rot.Y, rot.Z, rot.W);
601 Vector3 axis0 = Vector3.UnitX;
602 Vector3 axis1 = Vector3.UnitY;
603 Vector3 axis2 = Vector3.UnitZ;
604 //axis0 *= rotq;
605 //axis1 *= rotq;
606 //axis2 *= rotq;
607
608
609
610 if (m_aMotor != IntPtr.Zero)
611 {
612 d.JointSetAMotorAxis(m_aMotor, 0, 1, axis0.X, axis0.Y, axis0.Z);
613 d.JointSetAMotorAxis(m_aMotor, 1, 1, axis1.X, axis1.Y, axis1.Z);
614 d.JointSetAMotorAxis(m_aMotor, 2, 1, axis2.X, axis2.Y, axis2.Z);
615 d.JointSetAMotorParam(m_aMotor, (int)dParam.FMax, 30*objMass.mass);
616 d.JointSetAMotorParam(m_aMotor, (int)dParam.FMax2, 30*objMass.mass);
617 d.JointSetAMotorParam(m_aMotor, (int)dParam.FMax3, 30 * objMass.mass);
618 d.JointSetAMotorParam(m_aMotor, (int)dParam.Vel, m_lastAngularVelocityVector.X);
619 d.JointSetAMotorParam(m_aMotor, (int)dParam.Vel2, m_lastAngularVelocityVector.Y);
620 d.JointSetAMotorParam(m_aMotor, (int)dParam.Vel3, m_lastAngularVelocityVector.Z);
621
622 }
623 }
624
625 } 629 }
626} 630}
diff --git a/OpenSim/Region/Physics/OdePlugin/ODEDynamics.cs b/OpenSim/Region/Physics/OdePlugin/ODEDynamics.cs
new file mode 100644
index 0000000..467eba0
--- /dev/null
+++ b/OpenSim/Region/Physics/OdePlugin/ODEDynamics.cs
@@ -0,0 +1,658 @@
1/*
2 * Revised Aug, Sept 2009 by Kitto Flora. ODEDynamics.cs replaces
3 * ODEVehicleSettings.cs. It and ODEPrim.cs are re-organised:
4 * ODEPrim.cs contains methods dealing with Prim editing, Prim
5 * characteristics and Kinetic motion.
6 * ODEDynamics.cs contains methods dealing with Prim Physical motion
7 * (dynamics) and the associated settings. Old Linear and angular
8 * motors for dynamic motion have been replace with MoveLinear()
9 * and MoveAngular(); 'Physical' is used only to switch ODE dynamic
10 * simualtion on/off; VEHICAL_TYPE_NONE/VEHICAL_TYPE_<other> is to
11 * switch between 'VEHICLE' parameter use and general dynamics
12 * settings use.
13 *
14 * Copyright (c) Contributors, http://opensimulator.org/
15 * See CONTRIBUTORS.TXT for a full list of copyright holders.
16 *
17 * Redistribution and use in source and binary forms, with or without
18 * modification, are permitted provided that the following conditions are met:
19 * * Redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer.
21 * * Redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution.
24 * * Neither the name of the OpenSimulator Project nor the
25 * names of its contributors may be used to endorse or promote products
26 * derived from this software without specific prior written permission.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
29 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
30 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
31 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
32 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
33 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
34 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
35 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
36 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
37 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 */
39
40using System;
41using System.Collections.Generic;
42using System.Reflection;
43using System.Runtime.InteropServices;
44using log4net;
45using OpenMetaverse;
46using Ode.NET;
47using OpenSim.Framework;
48using OpenSim.Region.Physics.Manager;
49
50namespace OpenSim.Region.Physics.OdePlugin
51{
52 public class ODEDynamics
53 {
54 public Vehicle Type
55 {
56 get { return m_type; }
57 }
58
59 public IntPtr Body
60 {
61 get { return m_body; }
62 }
63
64 private int frcount = 0; // Used to limit dynamics debug output to
65 // every 100th frame
66
67 // private OdeScene m_parentScene = null;
68 private IntPtr m_body = IntPtr.Zero;
69 private IntPtr m_jointGroup = IntPtr.Zero;
70 private IntPtr m_aMotor = IntPtr.Zero;
71
72
73 // Vehicle properties
74 private Vehicle m_type = Vehicle.TYPE_NONE; // If a 'VEHICLE', and what kind
75 // private Quaternion m_referenceFrame = Quaternion.Identity; // Axis modifier
76 private VehicleFlag m_flags = (VehicleFlag) 0; // Boolean settings:
77 // HOVER_TERRAIN_ONLY
78 // HOVER_GLOBAL_HEIGHT
79 // NO_DEFLECTION_UP
80 // HOVER_WATER_ONLY
81 // HOVER_UP_ONLY
82 // LIMIT_MOTOR_UP
83 // LIMIT_ROLL_ONLY
84
85 // Linear properties
86 private Vector3 m_linearMotorDirection = Vector3.Zero; // velocity requested by LSL, decayed by time
87 private Vector3 m_linearMotorDirectionLASTSET = Vector3.Zero; // velocity requested by LSL
88 private Vector3 m_dir = Vector3.Zero; // velocity applied to body
89 private Vector3 m_linearFrictionTimescale = Vector3.Zero;
90 private float m_linearMotorDecayTimescale = 0;
91 private float m_linearMotorTimescale = 0;
92 private Vector3 m_lastLinearVelocityVector = Vector3.Zero;
93 // private bool m_LinearMotorSetLastFrame = false;
94 // private Vector3 m_linearMotorOffset = Vector3.Zero;
95
96 //Angular properties
97 private Vector3 m_angularMotorDirection = Vector3.Zero; // angular velocity requested by LSL motor
98 private int m_angularMotorApply = 0; // application frame counter
99 private Vector3 m_angularMotorVelocity = Vector3.Zero; // current angular motor velocity
100 private float m_angularMotorTimescale = 0; // motor angular velocity ramp up rate
101 private float m_angularMotorDecayTimescale = 0; // motor angular velocity decay rate
102 private Vector3 m_angularFrictionTimescale = Vector3.Zero; // body angular velocity decay rate
103 private Vector3 m_lastAngularVelocity = Vector3.Zero; // what was last applied to body
104 // private Vector3 m_lastVertAttractor = Vector3.Zero; // what VA was last applied to body
105
106 //Deflection properties
107 // private float m_angularDeflectionEfficiency = 0;
108 // private float m_angularDeflectionTimescale = 0;
109 // private float m_linearDeflectionEfficiency = 0;
110 // private float m_linearDeflectionTimescale = 0;
111
112 //Banking properties
113 // private float m_bankingEfficiency = 0;
114 // private float m_bankingMix = 0;
115 // private float m_bankingTimescale = 0;
116
117 //Hover and Buoyancy properties
118 private float m_VhoverHeight = 0f;
119 private float m_VhoverEfficiency = 0f;
120 private float m_VhoverTimescale = 0f;
121 private float m_VhoverTargetHeight = -1.0f; // if <0 then no hover, else its the current target height
122 private float m_VehicleBuoyancy = 0f; //KF: m_VehicleBuoyancy is set by VEHICLE_BUOYANCY for a vehicle.
123 // Modifies gravity. Slider between -1 (double-gravity) and 1 (full anti-gravity)
124 // KF: So far I have found no good method to combine a script-requested .Z velocity and gravity.
125 // Therefore only m_VehicleBuoyancy=1 (0g) will use the script-requested .Z velocity.
126
127 //Attractor properties
128 private float m_verticalAttractionEfficiency = 1.0f; // damped
129 private float m_verticalAttractionTimescale = 500f; // Timescale > 300 means no vert attractor.
130
131
132
133
134
135 internal void ProcessFloatVehicleParam(Vehicle pParam, float pValue)
136 {
137 switch (pParam)
138 {
139 case Vehicle.ANGULAR_DEFLECTION_EFFICIENCY:
140 if (pValue < 0.01f) pValue = 0.01f;
141 // m_angularDeflectionEfficiency = pValue;
142 break;
143 case Vehicle.ANGULAR_DEFLECTION_TIMESCALE:
144 if (pValue < 0.01f) pValue = 0.01f;
145 // m_angularDeflectionTimescale = pValue;
146 break;
147 case Vehicle.ANGULAR_MOTOR_DECAY_TIMESCALE:
148 if (pValue < 0.01f) pValue = 0.01f;
149 m_angularMotorDecayTimescale = pValue;
150 break;
151 case Vehicle.ANGULAR_MOTOR_TIMESCALE:
152 if (pValue < 0.01f) pValue = 0.01f;
153 m_angularMotorTimescale = pValue;
154 break;
155 case Vehicle.BANKING_EFFICIENCY:
156 if (pValue < 0.01f) pValue = 0.01f;
157 // m_bankingEfficiency = pValue;
158 break;
159 case Vehicle.BANKING_MIX:
160 if (pValue < 0.01f) pValue = 0.01f;
161 // m_bankingMix = pValue;
162 break;
163 case Vehicle.BANKING_TIMESCALE:
164 if (pValue < 0.01f) pValue = 0.01f;
165 // m_bankingTimescale = pValue;
166 break;
167 case Vehicle.BUOYANCY:
168 if (pValue < -1f) pValue = -1f;
169 if (pValue > 1f) pValue = 1f;
170 m_VehicleBuoyancy = pValue;
171 break;
172 case Vehicle.HOVER_EFFICIENCY:
173 if (pValue < 0f) pValue = 0f;
174 if (pValue > 1f) pValue = 1f;
175 m_VhoverEfficiency = pValue;
176 break;
177 case Vehicle.HOVER_HEIGHT:
178 m_VhoverHeight = pValue;
179 break;
180 case Vehicle.HOVER_TIMESCALE:
181 if (pValue < 0.01f) pValue = 0.01f;
182 m_VhoverTimescale = pValue;
183 break;
184 case Vehicle.LINEAR_DEFLECTION_EFFICIENCY:
185 if (pValue < 0.01f) pValue = 0.01f;
186 // m_linearDeflectionEfficiency = pValue;
187 break;
188 case Vehicle.LINEAR_DEFLECTION_TIMESCALE:
189 if (pValue < 0.01f) pValue = 0.01f;
190 // m_linearDeflectionTimescale = pValue;
191 break;
192 case Vehicle.LINEAR_MOTOR_DECAY_TIMESCALE:
193 if (pValue < 0.01f) pValue = 0.01f;
194 m_linearMotorDecayTimescale = pValue;
195 break;
196 case Vehicle.LINEAR_MOTOR_TIMESCALE:
197 if (pValue < 0.01f) pValue = 0.01f;
198 m_linearMotorTimescale = pValue;
199 break;
200 case Vehicle.VERTICAL_ATTRACTION_EFFICIENCY:
201 if (pValue < 0.1f) pValue = 0.1f; // Less goes unstable
202 if (pValue > 1.0f) pValue = 1.0f;
203 m_verticalAttractionEfficiency = pValue;
204 break;
205 case Vehicle.VERTICAL_ATTRACTION_TIMESCALE:
206 if (pValue < 0.01f) pValue = 0.01f;
207 m_verticalAttractionTimescale = pValue;
208 break;
209
210 // These are vector properties but the engine lets you use a single float value to
211 // set all of the components to the same value
212 case Vehicle.ANGULAR_FRICTION_TIMESCALE:
213 m_angularFrictionTimescale = new Vector3(pValue, pValue, pValue);
214 break;
215 case Vehicle.ANGULAR_MOTOR_DIRECTION:
216 m_angularMotorDirection = new Vector3(pValue, pValue, pValue);
217 m_angularMotorApply = 10;
218 break;
219 case Vehicle.LINEAR_FRICTION_TIMESCALE:
220 m_linearFrictionTimescale = new Vector3(pValue, pValue, pValue);
221 break;
222 case Vehicle.LINEAR_MOTOR_DIRECTION:
223 m_linearMotorDirection = new Vector3(pValue, pValue, pValue);
224 m_linearMotorDirectionLASTSET = new Vector3(pValue, pValue, pValue);
225 break;
226 case Vehicle.LINEAR_MOTOR_OFFSET:
227 // m_linearMotorOffset = new Vector3(pValue, pValue, pValue);
228 break;
229
230 }
231
232 }//end ProcessFloatVehicleParam
233
234 internal void ProcessVectorVehicleParam(Vehicle pParam, PhysicsVector pValue)
235 {
236 switch (pParam)
237 {
238 case Vehicle.ANGULAR_FRICTION_TIMESCALE:
239 m_angularFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z);
240 break;
241 case Vehicle.ANGULAR_MOTOR_DIRECTION:
242 m_angularMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z);
243 // Limit requested angular speed to 2 rps= 4 pi rads/sec
244 if(m_angularMotorDirection.X > 12.56f) m_angularMotorDirection.X = 12.56f;
245 if(m_angularMotorDirection.X < - 12.56f) m_angularMotorDirection.X = - 12.56f;
246 if(m_angularMotorDirection.Y > 12.56f) m_angularMotorDirection.Y = 12.56f;
247 if(m_angularMotorDirection.Y < - 12.56f) m_angularMotorDirection.Y = - 12.56f;
248 if(m_angularMotorDirection.Z > 12.56f) m_angularMotorDirection.Z = 12.56f;
249 if(m_angularMotorDirection.Z < - 12.56f) m_angularMotorDirection.Z = - 12.56f;
250 m_angularMotorApply = 10;
251 break;
252 case Vehicle.LINEAR_FRICTION_TIMESCALE:
253 m_linearFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z);
254 break;
255 case Vehicle.LINEAR_MOTOR_DIRECTION:
256 m_linearMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z);
257 m_linearMotorDirectionLASTSET = new Vector3(pValue.X, pValue.Y, pValue.Z);
258 break;
259 case Vehicle.LINEAR_MOTOR_OFFSET:
260 // m_linearMotorOffset = new Vector3(pValue.X, pValue.Y, pValue.Z);
261 break;
262 }
263
264 }//end ProcessVectorVehicleParam
265
266 internal void ProcessRotationVehicleParam(Vehicle pParam, Quaternion pValue)
267 {
268 switch (pParam)
269 {
270 case Vehicle.REFERENCE_FRAME:
271 // m_referenceFrame = pValue;
272 break;
273 }
274
275 }//end ProcessRotationVehicleParam
276
277 internal void ProcessTypeChange(Vehicle pType)
278 {
279 // Set Defaults For Type
280 m_type = pType;
281 switch (pType)
282 {
283 case Vehicle.TYPE_SLED:
284 m_linearFrictionTimescale = new Vector3(30, 1, 1000);
285 m_angularFrictionTimescale = new Vector3(1000, 1000, 1000);
286 m_linearMotorDirection = Vector3.Zero;
287 m_linearMotorTimescale = 1000;
288 m_linearMotorDecayTimescale = 120;
289 m_angularMotorDirection = Vector3.Zero;
290 m_angularMotorTimescale = 1000;
291 m_angularMotorDecayTimescale = 120;
292 m_VhoverHeight = 0;
293 m_VhoverEfficiency = 1;
294 m_VhoverTimescale = 10;
295 m_VehicleBuoyancy = 0;
296 // m_linearDeflectionEfficiency = 1;
297 // m_linearDeflectionTimescale = 1;
298 // m_angularDeflectionEfficiency = 1;
299 // m_angularDeflectionTimescale = 1000;
300 // m_bankingEfficiency = 0;
301 // m_bankingMix = 1;
302 // m_bankingTimescale = 10;
303 // m_referenceFrame = Quaternion.Identity;
304 m_flags &=
305 ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY |
306 VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY);
307 m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_ROLL_ONLY | VehicleFlag.LIMIT_MOTOR_UP);
308 break;
309 case Vehicle.TYPE_CAR:
310 m_linearFrictionTimescale = new Vector3(100, 2, 1000);
311 m_angularFrictionTimescale = new Vector3(1000, 1000, 1000);
312 m_linearMotorDirection = Vector3.Zero;
313 m_linearMotorTimescale = 1;
314 m_linearMotorDecayTimescale = 60;
315 m_angularMotorDirection = Vector3.Zero;
316 m_angularMotorTimescale = 1;
317 m_angularMotorDecayTimescale = 0.8f;
318 m_VhoverHeight = 0;
319 m_VhoverEfficiency = 0;
320 m_VhoverTimescale = 1000;
321 m_VehicleBuoyancy = 0;
322 // // m_linearDeflectionEfficiency = 1;
323 // // m_linearDeflectionTimescale = 2;
324 // // m_angularDeflectionEfficiency = 0;
325 // m_angularDeflectionTimescale = 10;
326 m_verticalAttractionEfficiency = 1f;
327 m_verticalAttractionTimescale = 10f;
328 // m_bankingEfficiency = -0.2f;
329 // m_bankingMix = 1;
330 // m_bankingTimescale = 1;
331 // m_referenceFrame = Quaternion.Identity;
332 m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT);
333 m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_ROLL_ONLY | VehicleFlag.HOVER_UP_ONLY |
334 VehicleFlag.LIMIT_MOTOR_UP);
335 break;
336 case Vehicle.TYPE_BOAT:
337 m_linearFrictionTimescale = new Vector3(10, 3, 2);
338 m_angularFrictionTimescale = new Vector3(10,10,10);
339 m_linearMotorDirection = Vector3.Zero;
340 m_linearMotorTimescale = 5;
341 m_linearMotorDecayTimescale = 60;
342 m_angularMotorDirection = Vector3.Zero;
343 m_angularMotorTimescale = 4;
344 m_angularMotorDecayTimescale = 4;
345 m_VhoverHeight = 0;
346 m_VhoverEfficiency = 0.5f;
347 m_VhoverTimescale = 2;
348 m_VehicleBuoyancy = 1;
349 // m_linearDeflectionEfficiency = 0.5f;
350 // m_linearDeflectionTimescale = 3;
351 // m_angularDeflectionEfficiency = 0.5f;
352 // m_angularDeflectionTimescale = 5;
353 m_verticalAttractionEfficiency = 0.5f;
354 m_verticalAttractionTimescale = 5f;
355 // m_bankingEfficiency = -0.3f;
356 // m_bankingMix = 0.8f;
357 // m_bankingTimescale = 1;
358 // m_referenceFrame = Quaternion.Identity;
359 m_flags &= ~(VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.LIMIT_ROLL_ONLY |
360 VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY);
361 m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.HOVER_WATER_ONLY |
362 VehicleFlag.LIMIT_MOTOR_UP);
363 break;
364 case Vehicle.TYPE_AIRPLANE:
365 m_linearFrictionTimescale = new Vector3(200, 10, 5);
366 m_angularFrictionTimescale = new Vector3(20, 20, 20);
367 m_linearMotorDirection = Vector3.Zero;
368 m_linearMotorTimescale = 2;
369 m_linearMotorDecayTimescale = 60;
370 m_angularMotorDirection = Vector3.Zero;
371 m_angularMotorTimescale = 4;
372 m_angularMotorDecayTimescale = 4;
373 m_VhoverHeight = 0;
374 m_VhoverEfficiency = 0.5f;
375 m_VhoverTimescale = 1000;
376 m_VehicleBuoyancy = 0;
377 // m_linearDeflectionEfficiency = 0.5f;
378 // m_linearDeflectionTimescale = 3;
379 // m_angularDeflectionEfficiency = 1;
380 // m_angularDeflectionTimescale = 2;
381 m_verticalAttractionEfficiency = 0.9f;
382 m_verticalAttractionTimescale = 2f;
383 // m_bankingEfficiency = 1;
384 // m_bankingMix = 0.7f;
385 // m_bankingTimescale = 2;
386 // m_referenceFrame = Quaternion.Identity;
387 m_flags &= ~(VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY |
388 VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY | VehicleFlag.LIMIT_MOTOR_UP);
389 m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY);
390 break;
391 case Vehicle.TYPE_BALLOON:
392 m_linearFrictionTimescale = new Vector3(5, 5, 5);
393 m_angularFrictionTimescale = new Vector3(10, 10, 10);
394 m_linearMotorDirection = Vector3.Zero;
395 m_linearMotorTimescale = 5;
396 m_linearMotorDecayTimescale = 60;
397 m_angularMotorDirection = Vector3.Zero;
398 m_angularMotorTimescale = 6;
399 m_angularMotorDecayTimescale = 10;
400 m_VhoverHeight = 5;
401 m_VhoverEfficiency = 0.8f;
402 m_VhoverTimescale = 10;
403 m_VehicleBuoyancy = 1;
404 // m_linearDeflectionEfficiency = 0;
405 // m_linearDeflectionTimescale = 5;
406 // m_angularDeflectionEfficiency = 0;
407 // m_angularDeflectionTimescale = 5;
408 m_verticalAttractionEfficiency = 1f;
409 m_verticalAttractionTimescale = 100f;
410 // m_bankingEfficiency = 0;
411 // m_bankingMix = 0.7f;
412 // m_bankingTimescale = 5;
413 // m_referenceFrame = Quaternion.Identity;
414 m_flags &= ~(VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY |
415 VehicleFlag.HOVER_UP_ONLY | VehicleFlag.LIMIT_MOTOR_UP);
416 m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT);
417 break;
418
419 }
420 }//end SetDefaultsForType
421
422 internal void Enable(IntPtr pBody, OdeScene pParentScene)
423 {
424 if (m_type == Vehicle.TYPE_NONE)
425 return;
426
427 m_body = pBody;
428 }
429
430 internal void Step(float pTimestep, OdeScene pParentScene)
431 {
432 if (m_body == IntPtr.Zero || m_type == Vehicle.TYPE_NONE)
433 return;
434 frcount++; // used to limit debug comment output
435 if (frcount > 100)
436 frcount = 0;
437
438 MoveLinear(pTimestep, pParentScene);
439 MoveAngular(pTimestep);
440 }// end Step
441
442 private void MoveLinear(float pTimestep, OdeScene _pParentScene)
443 {
444 if (!m_linearMotorDirection.ApproxEquals(Vector3.Zero, 0.01f)) // requested m_linearMotorDirection is significant
445 {
446 if(!d.BodyIsEnabled (Body)) d.BodyEnable (Body);
447
448 // add drive to body
449 Vector3 addAmount = m_linearMotorDirection/(m_linearMotorTimescale/pTimestep);
450 m_lastLinearVelocityVector += (addAmount*10); // lastLinearVelocityVector is the current body velocity vector?
451
452 // This will work temporarily, but we really need to compare speed on an axis
453 // KF: Limit body velocity to applied velocity?
454 if (Math.Abs(m_lastLinearVelocityVector.X) > Math.Abs(m_linearMotorDirectionLASTSET.X))
455 m_lastLinearVelocityVector.X = m_linearMotorDirectionLASTSET.X;
456 if (Math.Abs(m_lastLinearVelocityVector.Y) > Math.Abs(m_linearMotorDirectionLASTSET.Y))
457 m_lastLinearVelocityVector.Y = m_linearMotorDirectionLASTSET.Y;
458 if (Math.Abs(m_lastLinearVelocityVector.Z) > Math.Abs(m_linearMotorDirectionLASTSET.Z))
459 m_lastLinearVelocityVector.Z = m_linearMotorDirectionLASTSET.Z;
460
461 // decay applied velocity
462 Vector3 decayfraction = ((Vector3.One/(m_linearMotorDecayTimescale/pTimestep)));
463 //Console.WriteLine("decay: " + decayfraction);
464 m_linearMotorDirection -= m_linearMotorDirection * decayfraction * 0.5f;
465 //Console.WriteLine("actual: " + m_linearMotorDirection);
466 }
467 else
468 { // requested is not significant
469 // if what remains of applied is small, zero it.
470 if (m_lastLinearVelocityVector.ApproxEquals(Vector3.Zero, 0.01f))
471 m_lastLinearVelocityVector = Vector3.Zero;
472 }
473
474
475 // convert requested object velocity to world-referenced vector
476 m_dir = m_lastLinearVelocityVector;
477 d.Quaternion rot = d.BodyGetQuaternion(Body);
478 Quaternion rotq = new Quaternion(rot.X, rot.Y, rot.Z, rot.W); // rotq = rotation of object
479 m_dir *= rotq; // apply obj rotation to velocity vector
480
481 // add Gravity andBuoyancy
482 // KF: So far I have found no good method to combine a script-requested
483 // .Z velocity and gravity. Therefore only 0g will used script-requested
484 // .Z velocity. >0g (m_VehicleBuoyancy < 1) will used modified gravity only.
485 Vector3 grav = Vector3.Zero;
486 if(m_VehicleBuoyancy < 1.0f)
487 {
488 // There is some gravity, make a gravity force vector
489 // that is applied after object velocity.
490 d.Mass objMass;
491 d.BodyGetMass(Body, out objMass);
492 // m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g;
493 grav.Z = _pParentScene.gravityz * objMass.mass * (1f - m_VehicleBuoyancy);
494 // Preserve the current Z velocity
495 d.Vector3 vel_now = d.BodyGetLinearVel(Body);
496 m_dir.Z = vel_now.Z; // Preserve the accumulated falling velocity
497 } // else its 1.0, no gravity.
498
499 // Check if hovering
500 if( (m_flags & (VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT)) != 0)
501 {
502 // We should hover, get the target height
503 d.Vector3 pos = d.BodyGetPosition(Body);
504 if((m_flags & VehicleFlag.HOVER_WATER_ONLY) == VehicleFlag.HOVER_WATER_ONLY)
505 {
506 m_VhoverTargetHeight = _pParentScene.GetWaterLevel() + m_VhoverHeight;
507 }
508 else if((m_flags & VehicleFlag.HOVER_TERRAIN_ONLY) == VehicleFlag.HOVER_TERRAIN_ONLY)
509 {
510 m_VhoverTargetHeight = _pParentScene.GetTerrainHeightAtXY(pos.X, pos.Y) + m_VhoverHeight;
511 }
512 else if((m_flags & VehicleFlag.HOVER_GLOBAL_HEIGHT) == VehicleFlag.HOVER_GLOBAL_HEIGHT)
513 {
514 m_VhoverTargetHeight = m_VhoverHeight;
515 }
516
517 if((m_flags & VehicleFlag.HOVER_UP_ONLY) == VehicleFlag.HOVER_UP_ONLY)
518 {
519 // If body is aready heigher, use its height as target height
520 if(pos.Z > m_VhoverTargetHeight) m_VhoverTargetHeight = pos.Z;
521 }
522
523// m_VhoverEfficiency = 0f; // 0=boucy, 1=Crit.damped
524// m_VhoverTimescale = 0f; // time to acheive height
525// pTimestep is time since last frame,in secs
526 float herr0 = pos.Z - m_VhoverTargetHeight;
527 // Replace Vertical speed with correction figure if significant
528 if(Math.Abs(herr0) > 0.01f )
529 {
530 d.Mass objMass;
531 d.BodyGetMass(Body, out objMass);
532 m_dir.Z = - ( (herr0 * pTimestep * 50.0f) / m_VhoverTimescale);
533 //KF: m_VhoverEfficiency is not yet implemented
534 }
535 else
536 {
537 m_dir.Z = 0f;
538 }
539 }
540
541 // Apply velocity
542 d.BodySetLinearVel(Body, m_dir.X, m_dir.Y, m_dir.Z);
543 // apply gravity force
544 d.BodyAddForce(Body, grav.X, grav.Y, grav.Z);
545
546
547 // apply friction
548 Vector3 decayamount = Vector3.One / (m_linearFrictionTimescale / pTimestep);
549 m_lastLinearVelocityVector -= m_lastLinearVelocityVector * decayamount;
550 } // end MoveLinear()
551
552 private void MoveAngular(float pTimestep)
553 {
554 /*
555 private Vector3 m_angularMotorDirection = Vector3.Zero; // angular velocity requested by LSL motor
556 private int m_angularMotorApply = 0; // application frame counter
557 private float m_angularMotorVelocity = 0; // current angular motor velocity (ramps up and down)
558 private float m_angularMotorTimescale = 0; // motor angular velocity ramp up rate
559 private float m_angularMotorDecayTimescale = 0; // motor angular velocity decay rate
560 private Vector3 m_angularFrictionTimescale = Vector3.Zero; // body angular velocity decay rate
561 private Vector3 m_lastAngularVelocity = Vector3.Zero; // what was last applied to body
562 */
563
564 // Get what the body is doing, this includes 'external' influences
565 d.Vector3 angularVelocity = d.BodyGetAngularVel(Body);
566 // Vector3 angularVelocity = Vector3.Zero;
567
568 if (m_angularMotorApply > 0)
569 {
570 // ramp up to new value
571 // current velocity += error / ( time to get there / step interval )
572 // requested speed - last motor speed
573 m_angularMotorVelocity.X += (m_angularMotorDirection.X - m_angularMotorVelocity.X) / (m_angularMotorTimescale / pTimestep);
574 m_angularMotorVelocity.Y += (m_angularMotorDirection.Y - m_angularMotorVelocity.Y) / (m_angularMotorTimescale / pTimestep);
575 m_angularMotorVelocity.Z += (m_angularMotorDirection.Z - m_angularMotorVelocity.Z) / (m_angularMotorTimescale / pTimestep);
576
577 m_angularMotorApply--; // This is done so that if script request rate is less than phys frame rate the expected
578 // velocity may still be acheived.
579 }
580 else
581 {
582 // no motor recently applied, keep the body velocity
583 /* m_angularMotorVelocity.X = angularVelocity.X;
584 m_angularMotorVelocity.Y = angularVelocity.Y;
585 m_angularMotorVelocity.Z = angularVelocity.Z; */
586
587 // and decay the velocity
588 m_angularMotorVelocity -= m_angularMotorVelocity / (m_angularMotorDecayTimescale / pTimestep);
589 } // end motor section
590
591
592 // Vertical attractor section
593 Vector3 vertattr = Vector3.Zero;
594
595 if(m_verticalAttractionTimescale < 300)
596 {
597 float VAservo = 0.2f / (m_verticalAttractionTimescale * pTimestep);
598 // get present body rotation
599 d.Quaternion rot = d.BodyGetQuaternion(Body);
600 Quaternion rotq = new Quaternion(rot.X, rot.Y, rot.Z, rot.W);
601 // make a vector pointing up
602 Vector3 verterr = Vector3.Zero;
603 verterr.Z = 1.0f;
604 // rotate it to Body Angle
605 verterr = verterr * rotq;
606 // verterr.X and .Y are the World error ammounts. They are 0 when there is no error (Vehicle Body is 'vertical'), and .Z will be 1.
607 // As the body leans to its side |.X| will increase to 1 and .Z fall to 0. As body inverts |.X| will fall and .Z will go
608 // negative. Similar for tilt and |.Y|. .X and .Y must be modulated to prevent a stable inverted body.
609 if (verterr.Z < 0.0f)
610 {
611 verterr.X = 2.0f - verterr.X;
612 verterr.Y = 2.0f - verterr.Y;
613 }
614 // Error is 0 (no error) to +/- 2 (max error)
615 // scale it by VAservo
616 verterr = verterr * VAservo;
617//if(frcount == 0) Console.WriteLine("VAerr=" + verterr);
618
619 // As the body rotates around the X axis, then verterr.Y increases; Rotated around Y then .X increases, so
620 // Change Body angular velocity X based on Y, and Y based on X. Z is not changed.
621 vertattr.X = verterr.Y;
622 vertattr.Y = - verterr.X;
623 vertattr.Z = 0f;
624
625 // scaling appears better usingsquare-law
626 float bounce = 1.0f - (m_verticalAttractionEfficiency * m_verticalAttractionEfficiency);
627 vertattr.X += bounce * angularVelocity.X;
628 vertattr.Y += bounce * angularVelocity.Y;
629
630 } // else vertical attractor is off
631
632 // m_lastVertAttractor = vertattr;
633
634 // Bank section tba
635 // Deflection section tba
636
637 // Sum velocities
638 m_lastAngularVelocity = m_angularMotorVelocity + vertattr; // + bank + deflection
639
640 if (!m_lastAngularVelocity.ApproxEquals(Vector3.Zero, 0.01f))
641 {
642 if(!d.BodyIsEnabled (Body)) d.BodyEnable (Body);
643 }
644 else
645 {
646 m_lastAngularVelocity = Vector3.Zero; // Reduce small value to zero.
647 }
648
649 // apply friction
650 Vector3 decayamount = Vector3.One / (m_angularFrictionTimescale / pTimestep);
651 m_lastAngularVelocity -= m_lastAngularVelocity * decayamount;
652
653 // Apply to the body
654 d.BodySetAngularVel (Body, m_lastAngularVelocity.X, m_lastAngularVelocity.Y, m_lastAngularVelocity.Z);
655
656 } //end MoveAngular
657 }
658}
diff --git a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs
index 673ae39..34844c0 100644
--- a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs
+++ b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs
@@ -1,4 +1,15 @@
1/* 1/*
2 * Revised August 26 2009 by Kitto Flora. ODEDynamics.cs replaces
3 * ODEVehicleSettings.cs. It and ODEPrim.cs are re-organised:
4 * ODEPrim.cs contains methods dealing with Prim editing, Prim
5 * characteristics and Kinetic motion.
6 * ODEDynamics.cs contains methods dealing with Prim Physical motion
7 * (dynamics) and the associated settings. Old Linear and angular
8 * motors for dynamic motion have been replace with MoveLinear()
9 * and MoveAngular(); 'Physical' is used only to switch ODE dynamic
10 * simualtion on/off; VEHICAL_TYPE_NONE/VEHICAL_TYPE_<other> is to
11 * switch between 'VEHICLE' parameter use and general dynamics
12 * settings use.
2 * Copyright (c) Contributors, http://opensimulator.org/ 13 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders. 14 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 * 15 *
@@ -72,6 +83,9 @@ namespace OpenSim.Region.Physics.OdePlugin
72 private float PID_G = 25f; 83 private float PID_G = 25f;
73 private bool m_usePID = false; 84 private bool m_usePID = false;
74 85
86 // KF: These next 7 params apply to llSetHoverHeight(float height, integer water, float tau),
87 // and are for non-VEHICLES only.
88
75 private float m_PIDHoverHeight = 0f; 89 private float m_PIDHoverHeight = 0f;
76 private float m_PIDHoverTau = 0f; 90 private float m_PIDHoverTau = 0f;
77 private bool m_useHoverPID = false; 91 private bool m_useHoverPID = false;
@@ -79,6 +93,7 @@ namespace OpenSim.Region.Physics.OdePlugin
79 private float m_targetHoverHeight = 0f; 93 private float m_targetHoverHeight = 0f;
80 private float m_groundHeight = 0f; 94 private float m_groundHeight = 0f;
81 private float m_waterHeight = 0f; 95 private float m_waterHeight = 0f;
96 private float m_buoyancy = 0f; //KF: m_buoyancy should be set by llSetBuoyancy() for non-vehicle.
82 97
83 // private float m_tensor = 5f; 98 // private float m_tensor = 5f;
84 private int body_autodisable_frames = 20; 99 private int body_autodisable_frames = 20;
@@ -147,8 +162,6 @@ namespace OpenSim.Region.Physics.OdePlugin
147 public int m_roundsUnderMotionThreshold = 0; 162 public int m_roundsUnderMotionThreshold = 0;
148 private int m_crossingfailures = 0; 163 private int m_crossingfailures = 0;
149 164
150 public float m_buoyancy = 0f;
151
152 public bool outofBounds = false; 165 public bool outofBounds = false;
153 private float m_density = 10.000006836f; // Aluminum g/cm3; 166 private float m_density = 10.000006836f; // Aluminum g/cm3;
154 167
@@ -156,7 +169,8 @@ namespace OpenSim.Region.Physics.OdePlugin
156 private bool m_lastUpdateSent = false; 169 private bool m_lastUpdateSent = false;
157 170
158 public IntPtr Body = (IntPtr) 0; 171 public IntPtr Body = (IntPtr) 0;
159 private String m_primName; 172 public String m_primName;
173// private String m_primName;
160 private PhysicsVector _target_velocity; 174 private PhysicsVector _target_velocity;
161 public d.Mass pMass; 175 public d.Mass pMass;
162 176
@@ -167,7 +181,7 @@ namespace OpenSim.Region.Physics.OdePlugin
167 181
168 public volatile bool childPrim = false; 182 public volatile bool childPrim = false;
169 183
170 private ODEVehicleSettings m_vehicle; 184 private ODEDynamics m_vehicle;
171 185
172 internal int m_material = (int)Material.Wood; 186 internal int m_material = (int)Material.Wood;
173 187
@@ -175,7 +189,7 @@ namespace OpenSim.Region.Physics.OdePlugin
175 Quaternion rotation, IMesh mesh, PrimitiveBaseShape pbs, bool pisPhysical, CollisionLocker dode) 189 Quaternion rotation, IMesh mesh, PrimitiveBaseShape pbs, bool pisPhysical, CollisionLocker dode)
176 { 190 {
177 _target_velocity = new PhysicsVector(0, 0, 0); 191 _target_velocity = new PhysicsVector(0, 0, 0);
178 m_vehicle = new ODEVehicleSettings(); 192 m_vehicle = new ODEDynamics();
179 //gc = GCHandle.Alloc(prim_geom, GCHandleType.Pinned); 193 //gc = GCHandle.Alloc(prim_geom, GCHandleType.Pinned);
180 ode = dode; 194 ode = dode;
181 _velocity = new PhysicsVector(); 195 _velocity = new PhysicsVector();
@@ -260,11 +274,6 @@ namespace OpenSim.Region.Physics.OdePlugin
260 m_localID = value; } 274 m_localID = value; }
261 } 275 }
262 276
263 public override int GetHashCode()
264 {
265 return (int)m_localID;
266 }
267
268 public override bool Grabbed 277 public override bool Grabbed
269 { 278 {
270 set { return; } 279 set { return; }
@@ -273,6 +282,8 @@ namespace OpenSim.Region.Physics.OdePlugin
273 public override bool Selected 282 public override bool Selected
274 { 283 {
275 set { 284 set {
285
286
276 // This only makes the object not collidable if the object 287 // This only makes the object not collidable if the object
277 // is physical or the object is modified somehow *IN THE FUTURE* 288 // is physical or the object is modified somehow *IN THE FUTURE*
278 // without this, if an avatar selects prim, they can walk right 289 // without this, if an avatar selects prim, they can walk right
@@ -288,6 +299,7 @@ namespace OpenSim.Region.Physics.OdePlugin
288 m_taintselected = value; 299 m_taintselected = value;
289 m_isSelected = value; 300 m_isSelected = value;
290 } 301 }
302 if(m_isSelected) disableBodySoft();
291 } 303 }
292 } 304 }
293 305
@@ -295,6 +307,7 @@ namespace OpenSim.Region.Physics.OdePlugin
295 { 307 {
296 prev_geom = prim_geom; 308 prev_geom = prim_geom;
297 prim_geom = geom; 309 prim_geom = geom;
310//Console.WriteLine("SetGeom to " + prim_geom + " for " + m_primName);
298 if (prim_geom != IntPtr.Zero) 311 if (prim_geom != IntPtr.Zero)
299 { 312 {
300 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories); 313 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
@@ -306,6 +319,7 @@ namespace OpenSim.Region.Physics.OdePlugin
306 if (_parent != null && _parent is OdePrim) 319 if (_parent != null && _parent is OdePrim)
307 { 320 {
308 OdePrim parent = (OdePrim)_parent; 321 OdePrim parent = (OdePrim)_parent;
322//Console.WriteLine("SetGeom calls ChildSetGeom");
309 parent.ChildSetGeom(this); 323 parent.ChildSetGeom(this);
310 } 324 }
311 } 325 }
@@ -321,7 +335,8 @@ namespace OpenSim.Region.Physics.OdePlugin
321 if (m_isphysical && Body != IntPtr.Zero) 335 if (m_isphysical && Body != IntPtr.Zero)
322 { 336 {
323 d.BodyEnable(Body); 337 d.BodyEnable(Body);
324 m_vehicle.Enable(Body, _parent_scene); 338 if (m_vehicle.Type != Vehicle.TYPE_NONE)
339 m_vehicle.Enable(Body, _parent_scene);
325 } 340 }
326 341
327 m_disabled = false; 342 m_disabled = false;
@@ -335,7 +350,6 @@ namespace OpenSim.Region.Physics.OdePlugin
335 if (m_isphysical && Body != IntPtr.Zero) 350 if (m_isphysical && Body != IntPtr.Zero)
336 { 351 {
337 d.BodyDisable(Body); 352 d.BodyDisable(Body);
338 m_vehicle.Disable();
339 } 353 }
340 } 354 }
341 355
@@ -365,6 +379,9 @@ namespace OpenSim.Region.Physics.OdePlugin
365 379
366 d.BodySetAutoDisableFlag(Body, true); 380 d.BodySetAutoDisableFlag(Body, true);
367 d.BodySetAutoDisableSteps(Body, body_autodisable_frames); 381 d.BodySetAutoDisableSteps(Body, body_autodisable_frames);
382
383 // disconnect from world gravity so we can apply buoyancy
384 d.BodySetGravityMode (Body, false);
368 385
369 m_interpenetrationcount = 0; 386 m_interpenetrationcount = 0;
370 m_collisionscore = 0; 387 m_collisionscore = 0;
@@ -711,13 +728,8 @@ namespace OpenSim.Region.Physics.OdePlugin
711 break; 728 break;
712 } 729 }
713 } 730 }
714
715
716
717
718
719 return returnMass; 731 return returnMass;
720 } 732 }// end CalculateMass
721 733
722 #endregion 734 #endregion
723 735
@@ -743,7 +755,6 @@ namespace OpenSim.Region.Physics.OdePlugin
743 if (Body != IntPtr.Zero) 755 if (Body != IntPtr.Zero)
744 { 756 {
745 _parent_scene.remActivePrim(this); 757 _parent_scene.remActivePrim(this);
746 m_vehicle.Destroy();
747 m_collisionCategories &= ~CollisionCategories.Body; 758 m_collisionCategories &= ~CollisionCategories.Body;
748 m_collisionFlags &= ~(CollisionCategories.Wind | CollisionCategories.Land); 759 m_collisionFlags &= ~(CollisionCategories.Wind | CollisionCategories.Land);
749 760
@@ -838,6 +849,7 @@ namespace OpenSim.Region.Physics.OdePlugin
838 { 849 {
839 if (prim_geom == IntPtr.Zero) 850 if (prim_geom == IntPtr.Zero)
840 { 851 {
852//Console.WriteLine(" setMesh 1");
841 SetGeom(d.CreateTriMesh(m_targetSpace, _triMeshData, parent_scene.triCallback, null, null)); 853 SetGeom(d.CreateTriMesh(m_targetSpace, _triMeshData, parent_scene.triCallback, null, null));
842 } 854 }
843 } 855 }
@@ -865,19 +877,35 @@ namespace OpenSim.Region.Physics.OdePlugin
865 877
866 public void ProcessTaints(float timestep) 878 public void ProcessTaints(float timestep)
867 { 879 {
880//Console.WriteLine("ProcessTaints for " + m_primName );
868 if (m_taintadd) 881 if (m_taintadd)
869 { 882 {
870 changeadd(timestep); 883 changeadd(timestep);
871 } 884 }
885
872 if (prim_geom != IntPtr.Zero) 886 if (prim_geom != IntPtr.Zero)
873 { 887 {
874 if (!_position.IsIdentical(m_taintposition,0f)) 888 if (!_position.IsIdentical(m_taintposition,0f))
875 changemove(timestep); 889 changemove(timestep);
876 890
877 if (m_taintrot != _orientation) 891 if (m_taintrot != _orientation)
878 rotate(timestep); 892 {
893 if(childPrim && IsPhysical) // For physical child prim...
894 {
895 rotate(timestep);
896 // KF: ODE will also rotate the parent prim!
897 // so rotate the root back to where it was
898 OdePrim parent = (OdePrim)_parent;
899 parent.rotate(timestep);
900 }
901 else
902 {
903 //Just rotate the prim
904 rotate(timestep);
905 }
906 }
879 // 907 //
880 908
881 if (m_taintPhysics != m_isphysical && !(m_taintparent != _parent)) 909 if (m_taintPhysics != m_isphysical && !(m_taintparent != _parent))
882 changePhysicsStatus(timestep); 910 changePhysicsStatus(timestep);
883 // 911 //
@@ -916,8 +944,7 @@ namespace OpenSim.Region.Physics.OdePlugin
916 944
917 if (!m_angularlock.IsIdentical(m_taintAngularLock,0)) 945 if (!m_angularlock.IsIdentical(m_taintAngularLock,0))
918 changeAngularLock(timestep); 946 changeAngularLock(timestep);
919 947
920
921 } 948 }
922 else 949 else
923 { 950 {
@@ -949,11 +976,6 @@ namespace OpenSim.Region.Physics.OdePlugin
949 Amotor = IntPtr.Zero; 976 Amotor = IntPtr.Zero;
950 } 977 }
951 } 978 }
952
953 if (m_vehicle.Type != Vehicle.TYPE_NONE)
954 {
955 m_vehicle.Reset();
956 }
957 } 979 }
958 } 980 }
959 // Store this for later in case we get turned into a separate body 981 // Store this for later in case we get turned into a separate body
@@ -971,7 +993,7 @@ namespace OpenSim.Region.Physics.OdePlugin
971 { 993 {
972 OdePrim obj = (OdePrim)m_taintparent; 994 OdePrim obj = (OdePrim)m_taintparent;
973 //obj.disableBody(); 995 //obj.disableBody();
974 996//Console.WriteLine("changelink calls ParentPrim");
975 obj.ParentPrim(this); 997 obj.ParentPrim(this);
976 998
977 /* 999 /*
@@ -989,6 +1011,8 @@ namespace OpenSim.Region.Physics.OdePlugin
989 // destroy link 1011 // destroy link
990 else if (_parent != null && m_taintparent == null) 1012 else if (_parent != null && m_taintparent == null)
991 { 1013 {
1014//Console.WriteLine(" changelink B");
1015
992 if (_parent is OdePrim) 1016 if (_parent is OdePrim)
993 { 1017 {
994 OdePrim obj = (OdePrim)_parent; 1018 OdePrim obj = (OdePrim)_parent;
@@ -1005,7 +1029,7 @@ namespace OpenSim.Region.Physics.OdePlugin
1005 m_linkJoint = (IntPtr)0; 1029 m_linkJoint = (IntPtr)0;
1006 */ 1030 */
1007 } 1031 }
1008 1032
1009 _parent = m_taintparent; 1033 _parent = m_taintparent;
1010 m_taintPhysics = m_isphysical; 1034 m_taintPhysics = m_isphysical;
1011 } 1035 }
@@ -1014,6 +1038,7 @@ namespace OpenSim.Region.Physics.OdePlugin
1014 // prim is the child 1038 // prim is the child
1015 public void ParentPrim(OdePrim prim) 1039 public void ParentPrim(OdePrim prim)
1016 { 1040 {
1041//Console.WriteLine("ParentPrim " + m_primName);
1017 if (this.m_localID != prim.m_localID) 1042 if (this.m_localID != prim.m_localID)
1018 { 1043 {
1019 if (Body == IntPtr.Zero) 1044 if (Body == IntPtr.Zero)
@@ -1027,6 +1052,7 @@ namespace OpenSim.Region.Physics.OdePlugin
1027 { 1052 {
1028 if (!childrenPrim.Contains(prim)) 1053 if (!childrenPrim.Contains(prim))
1029 { 1054 {
1055//Console.WriteLine("childrenPrim.Add " + prim);
1030 childrenPrim.Add(prim); 1056 childrenPrim.Add(prim);
1031 1057
1032 foreach (OdePrim prm in childrenPrim) 1058 foreach (OdePrim prm in childrenPrim)
@@ -1050,6 +1076,7 @@ namespace OpenSim.Region.Physics.OdePlugin
1050 } 1076 }
1051 foreach (OdePrim prm in childrenPrim) 1077 foreach (OdePrim prm in childrenPrim)
1052 { 1078 {
1079
1053 prm.m_collisionCategories |= CollisionCategories.Body; 1080 prm.m_collisionCategories |= CollisionCategories.Body;
1054 prm.m_collisionFlags |= (CollisionCategories.Land | CollisionCategories.Wind); 1081 prm.m_collisionFlags |= (CollisionCategories.Land | CollisionCategories.Wind);
1055 1082
@@ -1058,7 +1085,7 @@ namespace OpenSim.Region.Physics.OdePlugin
1058 m_log.Warn("[PHYSICS]: Unable to link one of the linkset elements. No geom yet"); 1085 m_log.Warn("[PHYSICS]: Unable to link one of the linkset elements. No geom yet");
1059 continue; 1086 continue;
1060 } 1087 }
1061 1088//Console.WriteLine(" GeomSetCategoryBits 1: " + prm.prim_geom + " - " + (int)prm.m_collisionCategories + " for " + m_primName);
1062 d.GeomSetCategoryBits(prm.prim_geom, (int)prm.m_collisionCategories); 1089 d.GeomSetCategoryBits(prm.prim_geom, (int)prm.m_collisionCategories);
1063 d.GeomSetCollideBits(prm.prim_geom, (int)prm.m_collisionFlags); 1090 d.GeomSetCollideBits(prm.prim_geom, (int)prm.m_collisionFlags);
1064 1091
@@ -1103,11 +1130,12 @@ namespace OpenSim.Region.Physics.OdePlugin
1103 prm.Body = Body; 1130 prm.Body = Body;
1104 _parent_scene.addActivePrim(prm); 1131 _parent_scene.addActivePrim(prm);
1105 } 1132 }
1106
1107 m_collisionCategories |= CollisionCategories.Body; 1133 m_collisionCategories |= CollisionCategories.Body;
1108 m_collisionFlags |= (CollisionCategories.Land | CollisionCategories.Wind); 1134 m_collisionFlags |= (CollisionCategories.Land | CollisionCategories.Wind);
1109 1135
1136//Console.WriteLine("GeomSetCategoryBits 2: " + prim_geom + " - " + (int)m_collisionCategories + " for " + m_primName);
1110 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories); 1137 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
1138//Console.WriteLine(" Post GeomSetCategoryBits 2");
1111 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); 1139 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
1112 1140
1113 1141
@@ -1143,7 +1171,7 @@ namespace OpenSim.Region.Physics.OdePlugin
1143 createAMotor(m_angularlock); 1171 createAMotor(m_angularlock);
1144 } 1172 }
1145 d.BodySetPosition(Body, Position.X, Position.Y, Position.Z); 1173 d.BodySetPosition(Body, Position.X, Position.Y, Position.Z);
1146 m_vehicle.Enable(Body, _parent_scene); 1174 if (m_vehicle.Type != Vehicle.TYPE_NONE) m_vehicle.Enable(Body, _parent_scene);
1147 _parent_scene.addActivePrim(this); 1175 _parent_scene.addActivePrim(this);
1148 } 1176 }
1149 } 1177 }
@@ -1180,6 +1208,7 @@ namespace OpenSim.Region.Physics.OdePlugin
1180 { 1208 {
1181 foreach (OdePrim prm in childrenPrim) 1209 foreach (OdePrim prm in childrenPrim)
1182 { 1210 {
1211//Console.WriteLine("ChildSetGeom calls ParentPrim");
1183 ParentPrim(prm); 1212 ParentPrim(prm);
1184 } 1213 }
1185 } 1214 }
@@ -1206,6 +1235,7 @@ namespace OpenSim.Region.Physics.OdePlugin
1206 1235
1207 lock (childrenPrim) 1236 lock (childrenPrim)
1208 { 1237 {
1238 //Console.WriteLine("childrenPrim.Remove " + odePrim);
1209 childrenPrim.Remove(odePrim); 1239 childrenPrim.Remove(odePrim);
1210 } 1240 }
1211 1241
@@ -1223,6 +1253,7 @@ namespace OpenSim.Region.Physics.OdePlugin
1223 { 1253 {
1224 foreach (OdePrim prm in childrenPrim) 1254 foreach (OdePrim prm in childrenPrim)
1225 { 1255 {
1256//Console.WriteLine("ChildDelink calls ParentPrim");
1226 ParentPrim(prm); 1257 ParentPrim(prm);
1227 } 1258 }
1228 } 1259 }
@@ -1307,7 +1338,7 @@ namespace OpenSim.Region.Physics.OdePlugin
1307 1338
1308 resetCollisionAccounting(); 1339 resetCollisionAccounting();
1309 m_isSelected = m_taintselected; 1340 m_isSelected = m_taintselected;
1310 } 1341 }//end changeSelectedStatus
1311 1342
1312 public void ResetTaints() 1343 public void ResetTaints()
1313 { 1344 {
@@ -1324,6 +1355,7 @@ namespace OpenSim.Region.Physics.OdePlugin
1324 1355
1325 public void CreateGeom(IntPtr m_targetSpace, IMesh _mesh) 1356 public void CreateGeom(IntPtr m_targetSpace, IMesh _mesh)
1326 { 1357 {
1358//Console.WriteLine("CreateGeom:");
1327 if (_mesh != null) 1359 if (_mesh != null)
1328 { 1360 {
1329 setMesh(_parent_scene, _mesh); 1361 setMesh(_parent_scene, _mesh);
@@ -1339,6 +1371,7 @@ namespace OpenSim.Region.Physics.OdePlugin
1339 _parent_scene.waitForSpaceUnlock(m_targetSpace); 1371 _parent_scene.waitForSpaceUnlock(m_targetSpace);
1340 try 1372 try
1341 { 1373 {
1374//Console.WriteLine(" CreateGeom 1");
1342 SetGeom(d.CreateSphere(m_targetSpace, _size.X / 2)); 1375 SetGeom(d.CreateSphere(m_targetSpace, _size.X / 2));
1343 } 1376 }
1344 catch (AccessViolationException) 1377 catch (AccessViolationException)
@@ -1353,6 +1386,7 @@ namespace OpenSim.Region.Physics.OdePlugin
1353 _parent_scene.waitForSpaceUnlock(m_targetSpace); 1386 _parent_scene.waitForSpaceUnlock(m_targetSpace);
1354 try 1387 try
1355 { 1388 {
1389//Console.WriteLine(" CreateGeom 2");
1356 SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z)); 1390 SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z));
1357 } 1391 }
1358 catch (AccessViolationException) 1392 catch (AccessViolationException)
@@ -1368,6 +1402,7 @@ namespace OpenSim.Region.Physics.OdePlugin
1368 _parent_scene.waitForSpaceUnlock(m_targetSpace); 1402 _parent_scene.waitForSpaceUnlock(m_targetSpace);
1369 try 1403 try
1370 { 1404 {
1405//Console.WriteLine(" CreateGeom 3");
1371 SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z)); 1406 SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z));
1372 } 1407 }
1373 catch (AccessViolationException) 1408 catch (AccessViolationException)
@@ -1384,6 +1419,7 @@ namespace OpenSim.Region.Physics.OdePlugin
1384 _parent_scene.waitForSpaceUnlock(m_targetSpace); 1419 _parent_scene.waitForSpaceUnlock(m_targetSpace);
1385 try 1420 try
1386 { 1421 {
1422//Console.WriteLine(" CreateGeom 4");
1387 SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z)); 1423 SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z));
1388 } 1424 }
1389 catch (AccessViolationException) 1425 catch (AccessViolationException)
@@ -1420,6 +1456,7 @@ namespace OpenSim.Region.Physics.OdePlugin
1420 1456
1421 lock (_parent_scene.OdeLock) 1457 lock (_parent_scene.OdeLock)
1422 { 1458 {
1459//Console.WriteLine("changeadd 1");
1423 CreateGeom(m_targetSpace, _mesh); 1460 CreateGeom(m_targetSpace, _mesh);
1424 1461
1425 if (prim_geom != IntPtr.Zero) 1462 if (prim_geom != IntPtr.Zero)
@@ -1475,6 +1512,8 @@ namespace OpenSim.Region.Physics.OdePlugin
1475 OdePrim odParent = (OdePrim)_parent; 1512 OdePrim odParent = (OdePrim)_parent;
1476 if (Body != (IntPtr)0 && odParent.Body != (IntPtr)0 && Body != odParent.Body) 1513 if (Body != (IntPtr)0 && odParent.Body != (IntPtr)0 && Body != odParent.Body)
1477 { 1514 {
1515// KF: Fixed Joints were removed? Anyway - this Console.WriteLine does not show up, so routine is not used??
1516Console.WriteLine(" JointCreateFixed");
1478 m_linkJoint = d.JointCreateFixed(_parent_scene.world, _linkJointGroup); 1517 m_linkJoint = d.JointCreateFixed(_parent_scene.world, _linkJointGroup);
1479 d.JointAttach(m_linkJoint, Body, odParent.Body); 1518 d.JointAttach(m_linkJoint, Body, odParent.Body);
1480 d.JointSetFixed(m_linkJoint); 1519 d.JointSetFixed(m_linkJoint);
@@ -1528,239 +1567,236 @@ namespace OpenSim.Region.Physics.OdePlugin
1528 float fz = 0; 1567 float fz = 0;
1529 1568
1530 1569
1531 if (IsPhysical && Body != IntPtr.Zero && !m_isSelected) 1570 if (IsPhysical && (Body != IntPtr.Zero) && !m_isSelected && !childPrim) // KF: Only move root prims.
1532 { 1571 {
1533 if (d.BodyIsEnabled(Body) && !m_angularlock.IsIdentical(PhysicsVector.Zero, 0.003f)) 1572 if (m_vehicle.Type != Vehicle.TYPE_NONE)
1534 { 1573 {
1535 d.Vector3 avel2 = d.BodyGetAngularVel(Body); 1574 // 'VEHICLES' are dealt with in ODEDynamics.cs
1536 if (m_angularlock.X == 1) 1575 m_vehicle.Step(timestep, _parent_scene);
1537 avel2.X = 0; 1576 }
1538 if (m_angularlock.Y == 1) 1577 else
1539 avel2.Y = 0; 1578 {
1540 if (m_angularlock.Z == 1) 1579 // NON-'VEHICLES' are dealt with here
1541 avel2.Z = 0; 1580 if (d.BodyIsEnabled(Body) && !m_angularlock.IsIdentical(PhysicsVector.Zero, 0.003f))
1542 d.BodySetAngularVel(Body, avel2.X, avel2.Y, avel2.Z); 1581 {
1543 } 1582 d.Vector3 avel2 = d.BodyGetAngularVel(Body);
1544 //float PID_P = 900.0f; 1583 if (m_angularlock.X == 1)
1545 1584 avel2.X = 0;
1546 float m_mass = CalculateMass(); 1585 if (m_angularlock.Y == 1)
1547 1586 avel2.Y = 0;
1548 fz = 0f; 1587 if (m_angularlock.Z == 1)
1588 avel2.Z = 0;
1589 d.BodySetAngularVel(Body, avel2.X, avel2.Y, avel2.Z);
1590 }
1591 //float PID_P = 900.0f;
1592
1593 float m_mass = CalculateMass();
1594
1595// fz = 0f;
1549 //m_log.Info(m_collisionFlags.ToString()); 1596 //m_log.Info(m_collisionFlags.ToString());
1550 1597
1551 if (m_buoyancy != 0) 1598
1552 { 1599 //KF: m_buoyancy should be set by llSetBuoyancy() for non-vehicle.
1553 if (m_buoyancy > 0) 1600 // would come from SceneObjectPart.cs, public void SetBuoyancy(float fvalue) , PhysActor.Buoyancy = fvalue; ??
1554 { 1601 // m_buoyancy: (unlimited value) <0=Falls fast; 0=1g; 1=0g; >1 = floats up
1555 fz = (((-1 * _parent_scene.gravityz) * m_buoyancy) * m_mass); 1602 // gravityz multiplier = 1 - m_buoyancy
1556 1603 fz = _parent_scene.gravityz * (1.0f - m_buoyancy) * m_mass;
1557 //d.Vector3 l_velocity = d.BodyGetLinearVel(Body); 1604
1558 //m_log.Info("Using Buoyancy: " + buoyancy + " G: " + (_parent_scene.gravityz * m_buoyancy) + "mass:" + m_mass + " Pos: " + Position.ToString()); 1605 if (m_usePID)
1559 } 1606 {
1560 else 1607 // KF - this is for object move? eg. llSetPos() ?
1561 { 1608 //if (!d.BodyIsEnabled(Body))
1562 fz = (-1 * (((-1 * _parent_scene.gravityz) * (-1 * m_buoyancy)) * m_mass)); 1609 //d.BodySetForce(Body, 0f, 0f, 0f);
1563 } 1610 // If we're using the PID controller, then we have no gravity
1564 } 1611 //fz = (-1 * _parent_scene.gravityz) * m_mass; //KF: ?? Prims have no global gravity,so simply...
1565 1612 fz = 0f;
1566 if (m_usePID) 1613
1567 { 1614 // no lock; for now it's only called from within Simulate()
1615
1616 // If the PID Controller isn't active then we set our force
1617 // calculating base velocity to the current position
1618
1619 if ((m_PIDTau < 1) && (m_PIDTau != 0))
1620 {
1621 //PID_G = PID_G / m_PIDTau;
1622 m_PIDTau = 1;
1623 }
1624
1625 if ((PID_G - m_PIDTau) <= 0)
1626 {
1627 PID_G = m_PIDTau + 1;
1628 }
1629 //PidStatus = true;
1630
1631 // PhysicsVector vec = new PhysicsVector();
1632 d.Vector3 vel = d.BodyGetLinearVel(Body);
1633
1634 d.Vector3 pos = d.BodyGetPosition(Body);
1635 _target_velocity =
1636 new PhysicsVector(
1637 (m_PIDTarget.X - pos.X) * ((PID_G - m_PIDTau) * timestep),
1638 (m_PIDTarget.Y - pos.Y) * ((PID_G - m_PIDTau) * timestep),
1639 (m_PIDTarget.Z - pos.Z) * ((PID_G - m_PIDTau) * timestep)
1640 );
1641
1642 // if velocity is zero, use position control; otherwise, velocity control
1643
1644 if (_target_velocity.IsIdentical(PhysicsVector.Zero,0.1f))
1645 {
1646 // keep track of where we stopped. No more slippin' & slidin'
1647
1648 // We only want to deactivate the PID Controller if we think we want to have our surrogate
1649 // react to the physics scene by moving it's position.
1650 // Avatar to Avatar collisions
1651 // Prim to avatar collisions
1652
1653 //fx = (_target_velocity.X - vel.X) * (PID_D) + (_zeroPosition.X - pos.X) * (PID_P * 2);
1654 //fy = (_target_velocity.Y - vel.Y) * (PID_D) + (_zeroPosition.Y - pos.Y) * (PID_P * 2);
1655 //fz = fz + (_target_velocity.Z - vel.Z) * (PID_D) + (_zeroPosition.Z - pos.Z) * PID_P;
1656 d.BodySetPosition(Body, m_PIDTarget.X, m_PIDTarget.Y, m_PIDTarget.Z);
1657 d.BodySetLinearVel(Body, 0, 0, 0);
1658 d.BodyAddForce(Body, 0, 0, fz);
1659 return;
1660 }
1661 else
1662 {
1663 _zeroFlag = false;
1664
1665 // We're flying and colliding with something
1666 fx = ((_target_velocity.X) - vel.X) * (PID_D);
1667 fy = ((_target_velocity.Y) - vel.Y) * (PID_D);
1668
1669 // vec.Z = (_target_velocity.Z - vel.Z) * PID_D + (_zeroPosition.Z - pos.Z) * PID_P;
1670
1671 fz = fz + ((_target_velocity.Z - vel.Z) * (PID_D) * m_mass);
1672 }
1673 } // end if (m_usePID)
1674
1675 // Hover PID Controller needs to be mutually exlusive to MoveTo PID controller
1676 if (m_useHoverPID && !m_usePID)
1677 {
1678 // If we're using the PID controller, then we have no gravity
1679 fz = (-1 * _parent_scene.gravityz) * m_mass;
1680
1681 // no lock; for now it's only called from within Simulate()
1682
1683 // If the PID Controller isn't active then we set our force
1684 // calculating base velocity to the current position
1685
1686 if ((m_PIDTau < 1))
1687 {
1688 PID_G = PID_G / m_PIDTau;
1689 }
1690
1691 if ((PID_G - m_PIDTau) <= 0)
1692 {
1693 PID_G = m_PIDTau + 1;
1694 }
1568 1695
1569 //if (!d.BodyIsEnabled(Body))
1570 //d.BodySetForce(Body, 0f, 0f, 0f);
1571 // If we're using the PID controller, then we have no gravity
1572 fz = (-1 * _parent_scene.gravityz) * m_mass;
1573 1696
1574 // no lock; for now it's only called from within Simulate() 1697 // Where are we, and where are we headed?
1698 d.Vector3 pos = d.BodyGetPosition(Body);
1699 d.Vector3 vel = d.BodyGetLinearVel(Body);
1700
1701
1702 // Non-Vehicles have a limited set of Hover options.
1703 // determine what our target height really is based on HoverType
1704 switch (m_PIDHoverType)
1705 {
1706 case PIDHoverType.Ground:
1707 m_groundHeight = _parent_scene.GetTerrainHeightAtXY(pos.X, pos.Y);
1708 m_targetHoverHeight = m_groundHeight + m_PIDHoverHeight;
1709 break;
1710 case PIDHoverType.GroundAndWater:
1711 m_groundHeight = _parent_scene.GetTerrainHeightAtXY(pos.X, pos.Y);
1712 m_waterHeight = _parent_scene.GetWaterLevel();
1713 if (m_groundHeight > m_waterHeight)
1714 {
1715 m_targetHoverHeight = m_groundHeight + m_PIDHoverHeight;
1716 }
1717 else
1718 {
1719 m_targetHoverHeight = m_waterHeight + m_PIDHoverHeight;
1720 }
1721 break;
1722
1723 } // end switch (m_PIDHoverType)
1724
1725
1726 _target_velocity =
1727 new PhysicsVector(0.0f, 0.0f,
1728 (m_targetHoverHeight - pos.Z) * ((PID_G - m_PIDHoverTau) * timestep)
1729 );
1730
1731 // if velocity is zero, use position control; otherwise, velocity control
1732
1733 if (_target_velocity.IsIdentical(PhysicsVector.Zero, 0.1f))
1734 {
1735 // keep track of where we stopped. No more slippin' & slidin'
1736
1737 // We only want to deactivate the PID Controller if we think we want to have our surrogate
1738 // react to the physics scene by moving it's position.
1739 // Avatar to Avatar collisions
1740 // Prim to avatar collisions
1741
1742 d.BodySetPosition(Body, pos.X, pos.Y, m_targetHoverHeight);
1743 d.BodySetLinearVel(Body, vel.X, vel.Y, 0);
1744 d.BodyAddForce(Body, 0, 0, fz);
1745 return;
1746 }
1747 else
1748 {
1749 _zeroFlag = false;
1750
1751 // We're flying and colliding with something
1752 fz = fz + ((_target_velocity.Z - vel.Z) * (PID_D) * m_mass);
1753 }
1754 }
1755
1756 fx *= m_mass;
1757 fy *= m_mass;
1758 //fz *= m_mass;
1759
1760 fx += m_force.X;
1761 fy += m_force.Y;
1762 fz += m_force.Z;
1763
1764 //m_log.Info("[OBJPID]: X:" + fx.ToString() + " Y:" + fy.ToString() + " Z:" + fz.ToString());
1765 if (fx != 0 || fy != 0 || fz != 0)
1766 {
1767 //m_taintdisable = true;
1768 //base.RaiseOutOfBounds(Position);
1769 //d.BodySetLinearVel(Body, fx, fy, 0f);
1770 if (!d.BodyIsEnabled(Body))
1771 {
1772 // A physical body at rest on a surface will auto-disable after a while,
1773 // this appears to re-enable it incase the surface it is upon vanishes,
1774 // and the body should fall again.
1775 d.BodySetLinearVel(Body, 0f, 0f, 0f);
1776 d.BodySetForce(Body, 0, 0, 0);
1777 enableBodySoft();
1778 }
1779
1780 // 35x10 = 350n times the mass per second applied maximum.
1781 float nmax = 35f * m_mass;
1782 float nmin = -35f * m_mass;
1575 1783
1576 // If the PID Controller isn't active then we set our force
1577 // calculating base velocity to the current position
1578
1579 if ((m_PIDTau < 1) && (m_PIDTau != 0))
1580 {
1581 //PID_G = PID_G / m_PIDTau;
1582 m_PIDTau = 1;
1583 }
1584
1585 if ((PID_G - m_PIDTau) <= 0)
1586 {
1587 PID_G = m_PIDTau + 1;
1588 }
1589 //PidStatus = true;
1590
1591 // PhysicsVector vec = new PhysicsVector();
1592 d.Vector3 vel = d.BodyGetLinearVel(Body);
1593
1594 d.Vector3 pos = d.BodyGetPosition(Body);
1595 _target_velocity =
1596 new PhysicsVector(
1597 (m_PIDTarget.X - pos.X) * ((PID_G - m_PIDTau) * timestep),
1598 (m_PIDTarget.Y - pos.Y) * ((PID_G - m_PIDTau) * timestep),
1599 (m_PIDTarget.Z - pos.Z) * ((PID_G - m_PIDTau) * timestep)
1600 );
1601
1602 // if velocity is zero, use position control; otherwise, velocity control
1603
1604 if (_target_velocity.IsIdentical(PhysicsVector.Zero,0.1f))
1605 {
1606 // keep track of where we stopped. No more slippin' & slidin'
1607
1608 // We only want to deactivate the PID Controller if we think we want to have our surrogate
1609 // react to the physics scene by moving it's position.
1610 // Avatar to Avatar collisions
1611 // Prim to avatar collisions
1612
1613 //fx = (_target_velocity.X - vel.X) * (PID_D) + (_zeroPosition.X - pos.X) * (PID_P * 2);
1614 //fy = (_target_velocity.Y - vel.Y) * (PID_D) + (_zeroPosition.Y - pos.Y) * (PID_P * 2);
1615 //fz = fz + (_target_velocity.Z - vel.Z) * (PID_D) + (_zeroPosition.Z - pos.Z) * PID_P;
1616 d.BodySetPosition(Body, m_PIDTarget.X, m_PIDTarget.Y, m_PIDTarget.Z);
1617 d.BodySetLinearVel(Body, 0, 0, 0);
1618 d.BodyAddForce(Body, 0, 0, fz);
1619 return;
1620 }
1621 else
1622 {
1623 _zeroFlag = false;
1624
1625 // We're flying and colliding with something
1626 fx = ((_target_velocity.X) - vel.X) * (PID_D);
1627 fy = ((_target_velocity.Y) - vel.Y) * (PID_D);
1628
1629 // vec.Z = (_target_velocity.Z - vel.Z) * PID_D + (_zeroPosition.Z - pos.Z) * PID_P;
1630
1631 fz = fz + ((_target_velocity.Z - vel.Z) * (PID_D) * m_mass);
1632 }
1633 }
1634
1635 // Hover PID Controller needs to be mutually exlusive to MoveTo PID controller
1636 if (m_useHoverPID && !m_usePID)
1637 {
1638 // If we're using the PID controller, then we have no gravity
1639 fz = (-1 * _parent_scene.gravityz) * m_mass;
1640
1641 // no lock; for now it's only called from within Simulate()
1642
1643 // If the PID Controller isn't active then we set our force
1644 // calculating base velocity to the current position
1645
1646 if ((m_PIDTau < 1))
1647 {
1648 PID_G = PID_G / m_PIDTau;
1649 }
1650
1651 if ((PID_G - m_PIDTau) <= 0)
1652 {
1653 PID_G = m_PIDTau + 1;
1654 }
1655 1784
1656 1785 if (fx > nmax)
1657 // Where are we, and where are we headed? 1786 fx = nmax;
1658 d.Vector3 pos = d.BodyGetPosition(Body); 1787 if (fx < nmin)
1659 d.Vector3 vel = d.BodyGetLinearVel(Body); 1788 fx = nmin;
1660 1789 if (fy > nmax)
1661 // determine what our target height really is based on HoverType 1790 fy = nmax;
1662 switch (m_PIDHoverType) 1791 if (fy < nmin)
1663 { 1792 fy = nmin;
1664 case PIDHoverType.Absolute: 1793 d.BodyAddForce(Body, fx, fy, fz);
1665 m_targetHoverHeight = m_PIDHoverHeight; 1794 }
1666 break; 1795 }
1667 case PIDHoverType.Ground:
1668 m_groundHeight = _parent_scene.GetTerrainHeightAtXY(pos.X, pos.Y);
1669 m_targetHoverHeight = m_groundHeight + m_PIDHoverHeight;
1670 break;
1671 case PIDHoverType.GroundAndWater:
1672 m_groundHeight = _parent_scene.GetTerrainHeightAtXY(pos.X, pos.Y);
1673 m_waterHeight = _parent_scene.GetWaterLevel();
1674 if (m_groundHeight > m_waterHeight)
1675 {
1676 m_targetHoverHeight = m_groundHeight + m_PIDHoverHeight;
1677 }
1678 else
1679 {
1680 m_targetHoverHeight = m_waterHeight + m_PIDHoverHeight;
1681 }
1682 break;
1683 case PIDHoverType.Water:
1684 m_waterHeight = _parent_scene.GetWaterLevel();
1685 m_targetHoverHeight = m_waterHeight + m_PIDHoverHeight;
1686 break;
1687 }
1688
1689
1690 _target_velocity =
1691 new PhysicsVector(0.0f, 0.0f,
1692 (m_targetHoverHeight - pos.Z) * ((PID_G - m_PIDHoverTau) * timestep)
1693 );
1694
1695 // if velocity is zero, use position control; otherwise, velocity control
1696
1697 if (_target_velocity.IsIdentical(PhysicsVector.Zero, 0.1f))
1698 {
1699 // keep track of where we stopped. No more slippin' & slidin'
1700
1701 // We only want to deactivate the PID Controller if we think we want to have our surrogate
1702 // react to the physics scene by moving it's position.
1703 // Avatar to Avatar collisions
1704 // Prim to avatar collisions
1705
1706 d.BodySetPosition(Body, pos.X, pos.Y, m_targetHoverHeight);
1707 d.BodySetLinearVel(Body, vel.X, vel.Y, 0);
1708 d.BodyAddForce(Body, 0, 0, fz);
1709 return;
1710 }
1711 else
1712 {
1713 _zeroFlag = false;
1714
1715 // We're flying and colliding with something
1716 fz = fz + ((_target_velocity.Z - vel.Z) * (PID_D) * m_mass);
1717 }
1718 }
1719
1720 fx *= m_mass;
1721 fy *= m_mass;
1722 //fz *= m_mass;
1723
1724 fx += m_force.X;
1725 fy += m_force.Y;
1726 fz += m_force.Z;
1727
1728 //m_log.Info("[OBJPID]: X:" + fx.ToString() + " Y:" + fy.ToString() + " Z:" + fz.ToString());
1729 if (fx != 0 || fy != 0 || fz != 0)
1730 {
1731 //m_taintdisable = true;
1732 //base.RaiseOutOfBounds(Position);
1733 //d.BodySetLinearVel(Body, fx, fy, 0f);
1734 if (!d.BodyIsEnabled(Body))
1735 {
1736 d.BodySetLinearVel(Body, 0f, 0f, 0f);
1737 d.BodySetForce(Body, 0, 0, 0);
1738 enableBodySoft();
1739 }
1740
1741 // 35x10 = 350n times the mass per second applied maximum.
1742 float nmax = 35f * m_mass;
1743 float nmin = -35f * m_mass;
1744
1745
1746 if (fx > nmax)
1747 fx = nmax;
1748 if (fx < nmin)
1749 fx = nmin;
1750 if (fy > nmax)
1751 fy = nmax;
1752 if (fy < nmin)
1753 fy = nmin;
1754 d.BodyAddForce(Body, fx, fy, fz);
1755 }
1756 if (m_vehicle.Body == IntPtr.Zero && m_vehicle.Type != Vehicle.TYPE_NONE)
1757 m_vehicle.Enable(Body, _parent_scene);
1758
1759 m_vehicle.Step(timestep);
1760 } 1796 }
1761 else 1797 else
1762 { 1798 { // is not physical, or is not a body or is selected
1763 // _zeroPosition = d.BodyGetPosition(Body); 1799 // _zeroPosition = d.BodyGetPosition(Body);
1764 return; 1800 return;
1765 } 1801 }
1766 } 1802 }
@@ -1774,14 +1810,22 @@ namespace OpenSim.Region.Physics.OdePlugin
1774 myrot.Y = _orientation.Y; 1810 myrot.Y = _orientation.Y;
1775 myrot.Z = _orientation.Z; 1811 myrot.Z = _orientation.Z;
1776 myrot.W = _orientation.W; 1812 myrot.W = _orientation.W;
1777 d.GeomSetQuaternion(prim_geom, ref myrot); 1813 if (Body != IntPtr.Zero)
1778 if (m_isphysical && Body != IntPtr.Zero)
1779 { 1814 {
1815 // KF: If this is a root prim do BodySet
1780 d.BodySetQuaternion(Body, ref myrot); 1816 d.BodySetQuaternion(Body, ref myrot);
1781 if (!m_angularlock.IsIdentical(new PhysicsVector(1, 1, 1), 0)) 1817 if (m_isphysical)
1782 createAMotor(m_angularlock); 1818 {
1819 if (!m_angularlock.IsIdentical(new PhysicsVector(1, 1, 1), 0))
1820 createAMotor(m_angularlock);
1821 }
1822 }
1823 else
1824 {
1825 // daughter prim, do Geom set
1826 d.GeomSetQuaternion(prim_geom, ref myrot);
1783 } 1827 }
1784 1828
1785 resetCollisionAccounting(); 1829 resetCollisionAccounting();
1786 m_taintrot = _orientation; 1830 m_taintrot = _orientation;
1787 } 1831 }
@@ -1843,7 +1887,7 @@ namespace OpenSim.Region.Physics.OdePlugin
1843 m_log.Error("[PHYSICS]: PrimGeom dead"); 1887 m_log.Error("[PHYSICS]: PrimGeom dead");
1844 } 1888 }
1845 } 1889 }
1846 1890//Console.WriteLine("changePhysicsStatus for " + m_primName );
1847 changeadd(2f); 1891 changeadd(2f);
1848 } 1892 }
1849 if (childPrim) 1893 if (childPrim)
@@ -1921,7 +1965,7 @@ namespace OpenSim.Region.Physics.OdePlugin
1921 mesh = _parent_scene.mesher.CreateMesh(oldname, _pbs, _size, meshlod, IsPhysical); 1965 mesh = _parent_scene.mesher.CreateMesh(oldname, _pbs, _size, meshlod, IsPhysical);
1922 1966
1923 //IMesh mesh = _parent_scene.mesher.CreateMesh(oldname, _pbs, _size, meshlod, IsPhysical); 1967 //IMesh mesh = _parent_scene.mesher.CreateMesh(oldname, _pbs, _size, meshlod, IsPhysical);
1924 1968//Console.WriteLine("changesize 1");
1925 CreateGeom(m_targetSpace, mesh); 1969 CreateGeom(m_targetSpace, mesh);
1926 1970
1927 1971
@@ -1929,6 +1973,7 @@ namespace OpenSim.Region.Physics.OdePlugin
1929 else 1973 else
1930 { 1974 {
1931 _mesh = null; 1975 _mesh = null;
1976//Console.WriteLine("changesize 2");
1932 CreateGeom(m_targetSpace, _mesh); 1977 CreateGeom(m_targetSpace, _mesh);
1933 } 1978 }
1934 1979
@@ -2035,6 +2080,7 @@ namespace OpenSim.Region.Physics.OdePlugin
2035 else 2080 else
2036 { 2081 {
2037 _mesh = null; 2082 _mesh = null;
2083//Console.WriteLine("changeshape");
2038 CreateGeom(m_targetSpace, null); 2084 CreateGeom(m_targetSpace, null);
2039 } 2085 }
2040 2086
@@ -2376,7 +2422,9 @@ namespace OpenSim.Region.Physics.OdePlugin
2376 set 2422 set
2377 { 2423 {
2378 if (QuaternionIsFinite(value)) 2424 if (QuaternionIsFinite(value))
2425 {
2379 _orientation = value; 2426 _orientation = value;
2427 }
2380 else 2428 else
2381 m_log.Warn("[PHYSICS]: Got NaN quaternion Orientation from Scene in Object"); 2429 m_log.Warn("[PHYSICS]: Got NaN quaternion Orientation from Scene in Object");
2382 2430
@@ -2595,12 +2643,16 @@ namespace OpenSim.Region.Physics.OdePlugin
2595 //outofBounds = true; 2643 //outofBounds = true;
2596 } 2644 }
2597 2645
2646 float Adiff = 1.0f - Math.Abs(Quaternion.Dot(m_lastorientation, l_orientation));
2647//Console.WriteLine("Adiff " + m_primName + " = " + Adiff);
2598 if ((Math.Abs(m_lastposition.X - l_position.X) < 0.02) 2648 if ((Math.Abs(m_lastposition.X - l_position.X) < 0.02)
2599 && (Math.Abs(m_lastposition.Y - l_position.Y) < 0.02) 2649 && (Math.Abs(m_lastposition.Y - l_position.Y) < 0.02)
2600 && (Math.Abs(m_lastposition.Z - l_position.Z) < 0.02) 2650 && (Math.Abs(m_lastposition.Z - l_position.Z) < 0.02)
2601 && (1.0 - Math.Abs(Quaternion.Dot(m_lastorientation, l_orientation)) < 0.01)) 2651// && (1.0 - Math.Abs(Quaternion.Dot(m_lastorientation, l_orientation)) < 0.01))
2652 && (1.0 - Math.Abs(Quaternion.Dot(m_lastorientation, l_orientation)) < 0.0001)) // KF 0.01 is far to large
2602 { 2653 {
2603 _zeroFlag = true; 2654 _zeroFlag = true;
2655//Console.WriteLine("ZFT 2");
2604 m_throttleUpdates = false; 2656 m_throttleUpdates = false;
2605 } 2657 }
2606 else 2658 else
diff --git a/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs b/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs
index 94223d8..b7afa27 100644
--- a/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs
+++ b/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs
@@ -238,7 +238,8 @@ namespace OpenSim.Region.Physics.OdePlugin
238 private readonly HashSet<OdeCharacter> _characters = new HashSet<OdeCharacter>(); 238 private readonly HashSet<OdeCharacter> _characters = new HashSet<OdeCharacter>();
239 private readonly HashSet<OdePrim> _prims = new HashSet<OdePrim>(); 239 private readonly HashSet<OdePrim> _prims = new HashSet<OdePrim>();
240 private readonly HashSet<OdePrim> _activeprims = new HashSet<OdePrim>(); 240 private readonly HashSet<OdePrim> _activeprims = new HashSet<OdePrim>();
241 private readonly HashSet<OdePrim> _taintedPrim = new HashSet<OdePrim>(); 241 private readonly HashSet<OdePrim> _taintedPrimH = new HashSet<OdePrim>();
242 private readonly List<OdePrim> _taintedPrimL = new List<OdePrim>();
242 private readonly HashSet<OdeCharacter> _taintedActors = new HashSet<OdeCharacter>(); 243 private readonly HashSet<OdeCharacter> _taintedActors = new HashSet<OdeCharacter>();
243 private readonly List<d.ContactGeom> _perloopContact = new List<d.ContactGeom>(); 244 private readonly List<d.ContactGeom> _perloopContact = new List<d.ContactGeom>();
244 private readonly List<PhysicsActor> _collisionEventPrim = new List<PhysicsActor>(); 245 private readonly List<PhysicsActor> _collisionEventPrim = new List<PhysicsActor>();
@@ -2112,6 +2113,7 @@ namespace OpenSim.Region.Physics.OdePlugin
2112 /// <param name="prim"></param> 2113 /// <param name="prim"></param>
2113 public void RemovePrimThreadLocked(OdePrim prim) 2114 public void RemovePrimThreadLocked(OdePrim prim)
2114 { 2115 {
2116//Console.WriteLine("RemovePrimThreadLocked " + prim.m_primName);
2115 lock (prim) 2117 lock (prim)
2116 { 2118 {
2117 remCollisionEventReporting(prim); 2119 remCollisionEventReporting(prim);
@@ -2559,11 +2561,15 @@ namespace OpenSim.Region.Physics.OdePlugin
2559 if (prim is OdePrim) 2561 if (prim is OdePrim)
2560 { 2562 {
2561 OdePrim taintedprim = ((OdePrim) prim); 2563 OdePrim taintedprim = ((OdePrim) prim);
2562 lock (_taintedPrim) 2564 lock (_taintedPrimH)
2563 { 2565 {
2564 if (!(_taintedPrim.Contains(taintedprim))) 2566 if (!(_taintedPrimH.Contains(taintedprim)))
2565 _taintedPrim.Add(taintedprim); 2567 {
2566 } 2568//Console.WriteLine("AddPhysicsActorTaint to " + taintedprim.m_primName);
2569 _taintedPrimH.Add(taintedprim); // HashSet for searching
2570 _taintedPrimL.Add(taintedprim); // List for ordered readout
2571 }
2572 }
2567 return; 2573 return;
2568 } 2574 }
2569 else if (prim is OdeCharacter) 2575 else if (prim is OdeCharacter)
@@ -2599,7 +2605,7 @@ namespace OpenSim.Region.Physics.OdePlugin
2599 float fps = 0; 2605 float fps = 0;
2600 //m_log.Info(timeStep.ToString()); 2606 //m_log.Info(timeStep.ToString());
2601 step_time += timeStep; 2607 step_time += timeStep;
2602 2608
2603 // If We're loaded down by something else, 2609 // If We're loaded down by something else,
2604 // or debugging with the Visual Studio project on pause 2610 // or debugging with the Visual Studio project on pause
2605 // skip a few frames to catch up gracefully. 2611 // skip a few frames to catch up gracefully.
@@ -2679,16 +2685,20 @@ namespace OpenSim.Region.Physics.OdePlugin
2679 // Modify other objects in the scene. 2685 // Modify other objects in the scene.
2680 processedtaints = false; 2686 processedtaints = false;
2681 2687
2682 lock (_taintedPrim) 2688 lock (_taintedPrimL)
2683 { 2689 {
2684 foreach (OdePrim prim in _taintedPrim) 2690 foreach (OdePrim prim in _taintedPrimL)
2685 { 2691 {
2692
2693
2686 if (prim.m_taintremove) 2694 if (prim.m_taintremove)
2687 { 2695 {
2696//Console.WriteLine("Simulate calls RemovePrimThreadLocked");
2688 RemovePrimThreadLocked(prim); 2697 RemovePrimThreadLocked(prim);
2689 } 2698 }
2690 else 2699 else
2691 { 2700 {
2701//Console.WriteLine("Simulate calls ProcessTaints");
2692 prim.ProcessTaints(timeStep); 2702 prim.ProcessTaints(timeStep);
2693 } 2703 }
2694 processedtaints = true; 2704 processedtaints = true;
@@ -2878,7 +2888,9 @@ namespace OpenSim.Region.Physics.OdePlugin
2878 } 2888 }
2879 2889
2880 if (processedtaints) 2890 if (processedtaints)
2881 _taintedPrim.Clear(); 2891//Console.WriteLine("Simulate calls Clear of _taintedPrim list");
2892 _taintedPrimH.Clear();
2893 _taintedPrimL.Clear();
2882 } 2894 }
2883 2895
2884 // Move characters 2896 // Move characters
@@ -3488,7 +3500,7 @@ namespace OpenSim.Region.Physics.OdePlugin
3488 { 3500 {
3489 if (geom == localGround) 3501 if (geom == localGround)
3490 { 3502 {
3491 //localHeightfield = TerrainHeightFieldHeights[geom]; 3503 localHeightfield = TerrainHeightFieldHeights[geom];
3492 proceed = true; 3504 proceed = true;
3493 } 3505 }
3494 else 3506 else
@@ -3510,7 +3522,7 @@ namespace OpenSim.Region.Physics.OdePlugin
3510 // memory corruption 3522 // memory corruption
3511 if (TerrainHeightFieldHeights.ContainsKey(g)) 3523 if (TerrainHeightFieldHeights.ContainsKey(g))
3512 { 3524 {
3513 //float[] removingHeightField = TerrainHeightFieldHeights[g]; 3525 float[] removingHeightField = TerrainHeightFieldHeights[g];
3514 TerrainHeightFieldHeights.Remove(g); 3526 TerrainHeightFieldHeights.Remove(g);
3515 3527
3516 if (RegionTerrain.ContainsKey(g)) 3528 if (RegionTerrain.ContainsKey(g))
@@ -3519,17 +3531,27 @@ namespace OpenSim.Region.Physics.OdePlugin
3519 } 3531 }
3520 3532
3521 d.GeomDestroy(g); 3533 d.GeomDestroy(g);
3522 //removingHeightField = new float[0]; 3534 removingHeightField = new float[0];
3523 } 3535
3536
3537
3538 }
3539
3524 } 3540 }
3541
3525 } 3542 }
3526 else 3543 else
3527 { 3544 {
3528 m_log.Warn("[PHYSICS]: Couldn't proceed with UnCombine. Region has inconsistant data."); 3545 m_log.Warn("[PHYSICS]: Couldn't proceed with UnCombine. Region has inconsistant data.");
3546
3529 } 3547 }
3530 } 3548
3549 }
3550
3531 } 3551 }
3532 } 3552 }
3553
3554
3533 3555
3534 public override void SetWaterLevel(float baseheight) 3556 public override void SetWaterLevel(float baseheight)
3535 { 3557 {