aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics/UbitOdePlugin
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Physics/UbitOdePlugin')
-rw-r--r--OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs7426
-rw-r--r--OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs32
2 files changed, 3754 insertions, 3704 deletions
diff --git a/OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs
index 39b89d3..71aec4c 100644
--- a/OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs
+++ b/OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs
@@ -1,3703 +1,3725 @@
1/* 1/*
2 * Copyright (c) Contributors, http://opensimulator.org/ 2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders. 3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 * 4 *
5 * Redistribution and use in source and binary forms, with or without 5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met: 6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright 7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer. 8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright 9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the 10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution. 11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the 12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products 13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission. 14 * derived from this software without specific prior written permission.
15 * 15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY 16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY 19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27 27
28/* Revision 2011/12 by Ubit Umarov 28/* Revision 2011/12 by Ubit Umarov
29 * 29 *
30 * 30 *
31 */ 31 */
32 32
33/* 33/*
34 * Revised August 26 2009 by Kitto Flora. ODEDynamics.cs replaces 34 * Revised August 26 2009 by Kitto Flora. ODEDynamics.cs replaces
35 * ODEVehicleSettings.cs. It and ODEPrim.cs are re-organised: 35 * ODEVehicleSettings.cs. It and ODEPrim.cs are re-organised:
36 * ODEPrim.cs contains methods dealing with Prim editing, Prim 36 * ODEPrim.cs contains methods dealing with Prim editing, Prim
37 * characteristics and Kinetic motion. 37 * characteristics and Kinetic motion.
38 * ODEDynamics.cs contains methods dealing with Prim Physical motion 38 * ODEDynamics.cs contains methods dealing with Prim Physical motion
39 * (dynamics) and the associated settings. Old Linear and angular 39 * (dynamics) and the associated settings. Old Linear and angular
40 * motors for dynamic motion have been replace with MoveLinear() 40 * motors for dynamic motion have been replace with MoveLinear()
41 * and MoveAngular(); 'Physical' is used only to switch ODE dynamic 41 * and MoveAngular(); 'Physical' is used only to switch ODE dynamic
42 * simualtion on/off; VEHICAL_TYPE_NONE/VEHICAL_TYPE_<other> is to 42 * simualtion on/off; VEHICAL_TYPE_NONE/VEHICAL_TYPE_<other> is to
43 * switch between 'VEHICLE' parameter use and general dynamics 43 * switch between 'VEHICLE' parameter use and general dynamics
44 * settings use. 44 * settings use.
45 */ 45 */
46 46
47//#define SPAM 47//#define SPAM
48 48
49using System; 49using System;
50using System.Collections.Generic; 50using System.Collections.Generic;
51using System.Reflection; 51using System.Reflection;
52using System.Runtime.InteropServices; 52using System.Runtime.InteropServices;
53using System.Threading; 53using System.Threading;
54using log4net; 54using log4net;
55using OpenMetaverse; 55using OpenMetaverse;
56using OdeAPI; 56using OdeAPI;
57using OpenSim.Framework; 57using OpenSim.Framework;
58using OpenSim.Region.Physics.Manager; 58using OpenSim.Region.Physics.Manager;
59 59
60 60
61namespace OpenSim.Region.Physics.OdePlugin 61namespace OpenSim.Region.Physics.OdePlugin
62{ 62{
63 public class OdePrim : PhysicsActor 63 public class OdePrim : PhysicsActor
64 { 64 {
65 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 65 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
66 66
67 private bool m_isphysical; 67 private bool m_isphysical;
68 private bool m_fakeisphysical; 68 private bool m_fakeisphysical;
69 private bool m_isphantom; 69 private bool m_isphantom;
70 private bool m_fakeisphantom; 70 private bool m_fakeisphantom;
71 71
72 protected bool m_building; 72 protected bool m_building;
73 private Quaternion m_lastorientation = new Quaternion(); 73 private Quaternion m_lastorientation = new Quaternion();
74 private Quaternion _orientation; 74 private Quaternion _orientation;
75 75
76 private Vector3 _position; 76 private Vector3 _position;
77 private Vector3 _velocity; 77 private Vector3 _velocity;
78 private Vector3 _torque; 78 private Vector3 _torque;
79 private Vector3 m_lastVelocity; 79 private Vector3 m_lastVelocity;
80 private Vector3 m_lastposition; 80 private Vector3 m_lastposition;
81 private Vector3 m_rotationalVelocity; 81 private Vector3 m_rotationalVelocity;
82 private Vector3 _size; 82 private Vector3 _size;
83 private Vector3 _acceleration; 83 private Vector3 _acceleration;
84 private Vector3 m_angularlock = Vector3.One; 84 private Vector3 m_angularlock = Vector3.One;
85 private IntPtr Amotor = IntPtr.Zero; 85 private IntPtr Amotor = IntPtr.Zero;
86 86
87 private Vector3 m_force; 87 private Vector3 m_force;
88 private Vector3 m_forceacc; 88 private Vector3 m_forceacc;
89 private Vector3 m_angularForceacc; 89 private Vector3 m_angularForceacc;
90 90
91 private Vector3 m_PIDTarget; 91 private Vector3 m_PIDTarget;
92 private float m_PIDTau; 92 private float m_PIDTau;
93 private float PID_D = 35f; 93 private float PID_D = 35f;
94 private float PID_G = 25f; 94 private float PID_G = 25f;
95 private bool m_usePID; 95 private bool m_usePID;
96 96
97 // KF: These next 7 params apply to llSetHoverHeight(float height, integer water, float tau), 97 // KF: These next 7 params apply to llSetHoverHeight(float height, integer water, float tau),
98 // and are for non-VEHICLES only. 98 // and are for non-VEHICLES only.
99 99
100 private float m_PIDHoverHeight; 100 private float m_PIDHoverHeight;
101 private float m_PIDHoverTau; 101 private float m_PIDHoverTau;
102 private bool m_useHoverPID; 102 private bool m_useHoverPID;
103 private PIDHoverType m_PIDHoverType = PIDHoverType.Ground; 103 private PIDHoverType m_PIDHoverType = PIDHoverType.Ground;
104 private float m_targetHoverHeight; 104 private float m_targetHoverHeight;
105 private float m_groundHeight; 105 private float m_groundHeight;
106 private float m_waterHeight; 106 private float m_waterHeight;
107 private float m_buoyancy; //KF: m_buoyancy should be set by llSetBuoyancy() for non-vehicle. 107 private float m_buoyancy; //KF: m_buoyancy should be set by llSetBuoyancy() for non-vehicle.
108 108
109 private int body_autodisable_frames = 20; 109 private int body_autodisable_frames = 20;
110 110
111 private const CollisionCategories m_default_collisionFlags = (CollisionCategories.Geom 111 private const CollisionCategories m_default_collisionFlags = (CollisionCategories.Geom
112 | CollisionCategories.Space 112 | CollisionCategories.Space
113 | CollisionCategories.Body 113 | CollisionCategories.Body
114 | CollisionCategories.Character 114 | CollisionCategories.Character
115 ); 115 );
116// private bool m_collidesLand = true; 116// private bool m_collidesLand = true;
117 private bool m_collidesWater; 117 private bool m_collidesWater;
118 public bool m_returnCollisions; 118 public bool m_returnCollisions;
119 private bool m_softcolide; 119 private bool m_softcolide;
120 120
121 private bool m_NoColide; // for now only for internal use for bad meshs 121 private bool m_NoColide; // for now only for internal use for bad meshs
122 122
123 // Default we're a Geometry 123 // Default we're a Geometry
124 private CollisionCategories m_collisionCategories = (CollisionCategories.Geom); 124 private CollisionCategories m_collisionCategories = (CollisionCategories.Geom);
125 125
126 // Default, Collide with Other Geometries, spaces and Bodies 126 // Default, Collide with Other Geometries, spaces and Bodies
127 private CollisionCategories m_collisionFlags = m_default_collisionFlags; 127 private CollisionCategories m_collisionFlags = m_default_collisionFlags;
128 128
129 public bool m_disabled; 129 public bool m_disabled;
130 130
131 131
132 public uint m_localID; 132 public uint m_localID;
133 133
134 private PrimitiveBaseShape _pbs; 134 private PrimitiveBaseShape _pbs;
135 public OdeScene _parent_scene; 135 public OdeScene _parent_scene;
136 136
137 /// <summary> 137 /// <summary>
138 /// The physics space which contains prim geometry 138 /// The physics space which contains prim geometry
139 /// </summary> 139 /// </summary>
140 public IntPtr m_targetSpace = IntPtr.Zero; 140 public IntPtr m_targetSpace = IntPtr.Zero;
141 141
142 public IntPtr prim_geom; 142 public IntPtr prim_geom;
143 public IntPtr _triMeshData; 143 public IntPtr _triMeshData;
144 144
145 private PhysicsActor _parent; 145 private PhysicsActor _parent;
146 146
147 private List<OdePrim> childrenPrim = new List<OdePrim>(); 147 private List<OdePrim> childrenPrim = new List<OdePrim>();
148 148
149 private bool m_iscolliding; 149 private bool m_iscolliding;
150 150
151 public bool m_isSelected; 151 public bool m_isSelected;
152 private bool m_delaySelect; 152 private bool m_delaySelect;
153 private bool m_lastdoneSelected; 153 private bool m_lastdoneSelected;
154 public bool m_outbounds; 154 public bool m_outbounds;
155 155
156 internal bool m_isVolumeDetect; // If true, this prim only detects collisions but doesn't collide actively 156 internal bool m_isVolumeDetect; // If true, this prim only detects collisions but doesn't collide actively
157 157
158 private bool m_throttleUpdates; 158 private bool m_throttleUpdates;
159 private int throttleCounter; 159 private int throttleCounter;
160 public float m_collisionscore; 160 public float m_collisionscore;
161 int m_colliderfilter = 0; 161 int m_colliderfilter = 0;
162 162
163 public IntPtr collide_geom; // for objects: geom if single prim space it linkset 163 public IntPtr collide_geom; // for objects: geom if single prim space it linkset
164 164
165 private float m_density = 10.000006836f; // Aluminum g/cm3; 165 private float m_density = 10.000006836f; // Aluminum g/cm3;
166 166 private byte m_shapetype;
167 public bool _zeroFlag; 167 public bool _zeroFlag;
168 private bool m_lastUpdateSent; 168 private bool m_lastUpdateSent;
169 169
170 public IntPtr Body = IntPtr.Zero; 170 public IntPtr Body = IntPtr.Zero;
171 public String Name { get; private set; } 171 public String Name { get; private set; }
172 private Vector3 _target_velocity; 172 private Vector3 _target_velocity;
173 173
174 public Vector3 primOOBsize; // prim real dimensions from mesh 174 public Vector3 primOOBsize; // prim real dimensions from mesh
175 public Vector3 primOOBoffset; // its centroid out of mesh or rest aabb 175 public Vector3 primOOBoffset; // its centroid out of mesh or rest aabb
176 public float primOOBradiusSQ; 176 public float primOOBradiusSQ;
177 public d.Mass primdMass; // prim inertia information on it's own referencial 177 public d.Mass primdMass; // prim inertia information on it's own referencial
178 float primMass; // prim own mass 178 float primMass; // prim own mass
179 float _mass; // object mass acording to case 179 float _mass; // object mass acording to case
180 private bool hasOOBoffsetFromMesh = false; // if true we did compute it form mesh centroid, else from aabb 180 private bool hasOOBoffsetFromMesh = false; // if true we did compute it form mesh centroid, else from aabb
181 181
182 public int givefakepos = 0; 182 public int givefakepos = 0;
183 private Vector3 fakepos; 183 private Vector3 fakepos;
184 public int givefakeori = 0; 184 public int givefakeori = 0;
185 private Quaternion fakeori; 185 private Quaternion fakeori;
186 186
187 public int m_eventsubscription; 187 public int m_eventsubscription;
188 private CollisionEventUpdate CollisionEventsThisFrame = new CollisionEventUpdate(); 188 private CollisionEventUpdate CollisionEventsThisFrame = new CollisionEventUpdate();
189 189
190 public volatile bool childPrim; 190 public volatile bool childPrim;
191 191
192 public ODEDynamics m_vehicle; 192 public ODEDynamics m_vehicle;
193 193
194 internal int m_material = (int)Material.Wood; 194 internal int m_material = (int)Material.Wood;
195 private float mu; 195 private float mu;
196 private float bounce; 196 private float bounce;
197 197
198 /// <summary> 198 /// <summary>
199 /// Is this prim subject to physics? Even if not, it's still solid for collision purposes. 199 /// Is this prim subject to physics? Even if not, it's still solid for collision purposes.
200 /// </summary> 200 /// </summary>
201 public override bool IsPhysical // this is not reliable for internal use 201 public override bool IsPhysical // this is not reliable for internal use
202 { 202 {
203 get { return m_fakeisphysical; } 203 get { return m_fakeisphysical; }
204 set 204 set
205 { 205 {
206 m_fakeisphysical = value; // we show imediatly to outside that we changed physical 206 m_fakeisphysical = value; // we show imediatly to outside that we changed physical
207 // and also to stop imediatly some updates 207 // and also to stop imediatly some updates
208 // but real change will only happen in taintprocessing 208 // but real change will only happen in taintprocessing
209 209
210 if (!value) // Zero the remembered last velocity 210 if (!value) // Zero the remembered last velocity
211 m_lastVelocity = Vector3.Zero; 211 m_lastVelocity = Vector3.Zero;
212 AddChange(changes.Physical, value); 212 AddChange(changes.Physical, value);
213 } 213 }
214 } 214 }
215 215
216 public override bool Phantom // this is not reliable for internal use 216 public override bool Phantom // this is not reliable for internal use
217 { 217 {
218 get { return m_fakeisphantom; } 218 get { return m_fakeisphantom; }
219 set 219 set
220 { 220 {
221 m_fakeisphantom = value; // we show imediatly to outside that we changed physical 221 m_fakeisphantom = value; // we show imediatly to outside that we changed physical
222 // and also to stop imediatly some updates 222 // and also to stop imediatly some updates
223 // but real change will only happen in taintprocessing 223 // but real change will only happen in taintprocessing
224 224
225 AddChange(changes.Phantom, value); 225 AddChange(changes.Phantom, value);
226 } 226 }
227 } 227 }
228 228
229 public override bool Building // this is not reliable for internal use 229 public override bool Building // this is not reliable for internal use
230 { 230 {
231 get { return m_building; } 231 get { return m_building; }
232 set 232 set
233 { 233 {
234 if (value) 234 if (value)
235 m_building = true; 235 m_building = true;
236 AddChange(changes.building, value); 236 AddChange(changes.building, value);
237 } 237 }
238 } 238 }
239 239
240 public override void getContactData(ref ContactData cdata) 240 public override void getContactData(ref ContactData cdata)
241 { 241 {
242 cdata.mu = mu; 242 cdata.mu = mu;
243 cdata.bounce = bounce; 243 cdata.bounce = bounce;
244 244
245 // cdata.softcolide = m_softcolide; 245 // cdata.softcolide = m_softcolide;
246 cdata.softcolide = false; 246 cdata.softcolide = false;
247 247
248 if (m_isphysical) 248 if (m_isphysical)
249 { 249 {
250 ODEDynamics veh; 250 ODEDynamics veh;
251 if (_parent != null) 251 if (_parent != null)
252 veh = ((OdePrim)_parent).m_vehicle; 252 veh = ((OdePrim)_parent).m_vehicle;
253 else 253 else
254 veh = m_vehicle; 254 veh = m_vehicle;
255 255
256 if (veh != null && veh.Type != Vehicle.TYPE_NONE) 256 if (veh != null && veh.Type != Vehicle.TYPE_NONE)
257 cdata.mu *= veh.FrictionFactor; 257 cdata.mu *= veh.FrictionFactor;
258 } 258 }
259 } 259 }
260 260
261 public override int PhysicsActorType 261 public override int PhysicsActorType
262 { 262 {
263 get { return (int)ActorTypes.Prim; } 263 get { return (int)ActorTypes.Prim; }
264 set { return; } 264 set { return; }
265 } 265 }
266 266
267 public override bool SetAlwaysRun 267 public override bool SetAlwaysRun
268 { 268 {
269 get { return false; } 269 get { return false; }
270 set { return; } 270 set { return; }
271 } 271 }
272 272
273 public override uint LocalID 273 public override uint LocalID
274 { 274 {
275 get 275 get
276 { 276 {
277 return m_localID; 277 return m_localID;
278 } 278 }
279 set 279 set
280 { 280 {
281 //m_log.Info("[PHYSICS]: Setting TrackerID: " + value); 281 //m_log.Info("[PHYSICS]: Setting TrackerID: " + value);
282 m_localID = value; 282 m_localID = value;
283 } 283 }
284 } 284 }
285 285
286 public override bool Grabbed 286 public override bool Grabbed
287 { 287 {
288 set { return; } 288 set { return; }
289 } 289 }
290 290
291 public override bool Selected 291 public override bool Selected
292 { 292 {
293 set 293 set
294 { 294 {
295 if (value) 295 if (value)
296 m_isSelected = value; // if true set imediatly to stop moves etc 296 m_isSelected = value; // if true set imediatly to stop moves etc
297 AddChange(changes.Selected, value); 297 AddChange(changes.Selected, value);
298 } 298 }
299 } 299 }
300 300
301 public override bool Flying 301 public override bool Flying
302 { 302 {
303 // no flying prims for you 303 // no flying prims for you
304 get { return false; } 304 get { return false; }
305 set { } 305 set { }
306 } 306 }
307 307
308 public override bool IsColliding 308 public override bool IsColliding
309 { 309 {
310 get { return m_iscolliding; } 310 get { return m_iscolliding; }
311 set 311 set
312 { 312 {
313 if (value) 313 if (value)
314 { 314 {
315 m_colliderfilter += 2; 315 m_colliderfilter += 2;
316 if (m_colliderfilter > 2) 316 if (m_colliderfilter > 2)
317 m_colliderfilter = 2; 317 m_colliderfilter = 2;
318 } 318 }
319 else 319 else
320 { 320 {
321 m_colliderfilter--; 321 m_colliderfilter--;
322 if (m_colliderfilter < 0) 322 if (m_colliderfilter < 0)
323 m_colliderfilter = 0; 323 m_colliderfilter = 0;
324 } 324 }
325 325
326 if (m_colliderfilter == 0) 326 if (m_colliderfilter == 0)
327 { 327 {
328 m_softcolide = false; 328 m_softcolide = false;
329 m_iscolliding = false; 329 m_iscolliding = false;
330 } 330 }
331 else 331 else
332 m_iscolliding = true; 332 m_iscolliding = true;
333 } 333 }
334 } 334 }
335 335
336 public override bool CollidingGround 336 public override bool CollidingGround
337 { 337 {
338 get { return false; } 338 get { return false; }
339 set { return; } 339 set { return; }
340 } 340 }
341 341
342 public override bool CollidingObj 342 public override bool CollidingObj
343 { 343 {
344 get { return false; } 344 get { return false; }
345 set { return; } 345 set { return; }
346 } 346 }
347 347
348 public override bool ThrottleUpdates 348 public override bool ThrottleUpdates
349 { 349 {
350 get { return m_throttleUpdates; } 350 get { return m_throttleUpdates; }
351 set { m_throttleUpdates = value; } 351 set { m_throttleUpdates = value; }
352 } 352 }
353 353
354 public override bool Stopped 354 public override bool Stopped
355 { 355 {
356 get { return _zeroFlag; } 356 get { return _zeroFlag; }
357 } 357 }
358 358
359 public override Vector3 Position 359 public override Vector3 Position
360 { 360 {
361 get 361 get
362 { 362 {
363 if (givefakepos > 0) 363 if (givefakepos > 0)
364 return fakepos; 364 return fakepos;
365 else 365 else
366 return _position; 366 return _position;
367 } 367 }
368 368
369 set 369 set
370 { 370 {
371 fakepos = value; 371 fakepos = value;
372 givefakepos++; 372 givefakepos++;
373 AddChange(changes.Position, value); 373 AddChange(changes.Position, value);
374 } 374 }
375 } 375 }
376 376
377 public override Vector3 Size 377 public override Vector3 Size
378 { 378 {
379 get { return _size; } 379 get { return _size; }
380 set 380 set
381 { 381 {
382 if (value.IsFinite()) 382 if (value.IsFinite())
383 { 383 {
384 AddChange(changes.Size, value); 384 AddChange(changes.Size, value);
385 } 385 }
386 else 386 else
387 { 387 {
388 m_log.WarnFormat("[PHYSICS]: Got NaN Size on object {0}", Name); 388 m_log.WarnFormat("[PHYSICS]: Got NaN Size on object {0}", Name);
389 } 389 }
390 } 390 }
391 } 391 }
392 392
393 public override float Mass 393 public override float Mass
394 { 394 {
395 get { return _mass; } 395 get { return _mass; }
396 } 396 }
397 397
398 public override Vector3 Force 398 public override Vector3 Force
399 { 399 {
400 //get { return Vector3.Zero; } 400 //get { return Vector3.Zero; }
401 get { return m_force; } 401 get { return m_force; }
402 set 402 set
403 { 403 {
404 if (value.IsFinite()) 404 if (value.IsFinite())
405 { 405 {
406 AddChange(changes.Force, value); 406 AddChange(changes.Force, value);
407 } 407 }
408 else 408 else
409 { 409 {
410 m_log.WarnFormat("[PHYSICS]: NaN in Force Applied to an Object {0}", Name); 410 m_log.WarnFormat("[PHYSICS]: NaN in Force Applied to an Object {0}", Name);
411 } 411 }
412 } 412 }
413 } 413 }
414 414
415 public override void SetVolumeDetect(int param) 415 public override void SetVolumeDetect(int param)
416 { 416 {
417 AddChange(changes.VolumeDtc, (param != 0)); 417 AddChange(changes.VolumeDtc, (param != 0));
418 } 418 }
419 419
420 public override Vector3 GeometricCenter 420 public override Vector3 GeometricCenter
421 { 421 {
422 get 422 get
423 { 423 {
424 return Vector3.Zero; 424 return Vector3.Zero;
425 } 425 }
426 } 426 }
427 427
428 public override Vector3 CenterOfMass 428 public override Vector3 CenterOfMass
429 { 429 {
430 get 430 get
431 { 431 {
432 d.Vector3 dtmp; 432 d.Vector3 dtmp;
433 if (IsPhysical && !childPrim && Body != IntPtr.Zero) 433 if (IsPhysical && !childPrim && Body != IntPtr.Zero)
434 { 434 {
435 dtmp = d.BodyGetPosition(Body); 435 dtmp = d.BodyGetPosition(Body);
436 return new Vector3(dtmp.X, dtmp.Y, dtmp.Z); 436 return new Vector3(dtmp.X, dtmp.Y, dtmp.Z);
437 } 437 }
438 else if (prim_geom != IntPtr.Zero) 438 else if (prim_geom != IntPtr.Zero)
439 { 439 {
440 d.Quaternion dq; 440 d.Quaternion dq;
441 d.GeomCopyQuaternion(prim_geom, out dq); 441 d.GeomCopyQuaternion(prim_geom, out dq);
442 Quaternion q; 442 Quaternion q;
443 q.X = dq.X; 443 q.X = dq.X;
444 q.Y = dq.Y; 444 q.Y = dq.Y;
445 q.Z = dq.Z; 445 q.Z = dq.Z;
446 q.W = dq.W; 446 q.W = dq.W;
447 447
448 Vector3 vtmp = primOOBoffset * q; 448 Vector3 vtmp = primOOBoffset * q;
449 dtmp = d.GeomGetPosition(prim_geom); 449 dtmp = d.GeomGetPosition(prim_geom);
450 return new Vector3(dtmp.X + vtmp.X, dtmp.Y + vtmp.Y, dtmp.Z + vtmp.Z); 450 return new Vector3(dtmp.X + vtmp.X, dtmp.Y + vtmp.Y, dtmp.Z + vtmp.Z);
451 } 451 }
452 else 452 else
453 return Vector3.Zero; 453 return Vector3.Zero;
454 } 454 }
455 } 455 }
456 /* 456 /*
457 public override Vector3 PrimOOBsize 457 public override Vector3 PrimOOBsize
458 { 458 {
459 get 459 get
460 { 460 {
461 return primOOBsize; 461 return primOOBsize;
462 } 462 }
463 } 463 }
464 464
465 public override Vector3 PrimOOBoffset 465 public override Vector3 PrimOOBoffset
466 { 466 {
467 get 467 get
468 { 468 {
469 return primOOBoffset; 469 return primOOBoffset;
470 } 470 }
471 } 471 }
472 472
473 public override float PrimOOBRadiusSQ 473 public override float PrimOOBRadiusSQ
474 { 474 {
475 get 475 get
476 { 476 {
477 return primOOBradiusSQ; 477 return primOOBradiusSQ;
478 } 478 }
479 } 479 }
480 */ 480 */
481 public override PrimitiveBaseShape Shape 481 public override PrimitiveBaseShape Shape
482 { 482 {
483 set 483 set
484 { 484 {
485 AddChange(changes.Shape, value); 485 AddChange(changes.Shape, value);
486 } 486 }
487 } 487 }
488 488
489 public override Vector3 Velocity 489 public override byte PhysicsShapeType
490 { 490 {
491 get 491 get
492 { 492 {
493 if (_zeroFlag) 493 return m_shapetype;
494 return Vector3.Zero; 494 }
495 return _velocity; 495 set
496 } 496 {
497 set 497 m_shapetype = value;
498 { 498 AddChange(changes.Shape, null);
499 if (value.IsFinite()) 499 }
500 { 500 }
501 AddChange(changes.Velocity, value); 501
502 // _velocity = value; 502 public override Vector3 Velocity
503 503 {
504 } 504 get
505 else 505 {
506 { 506 if (_zeroFlag)
507 m_log.WarnFormat("[PHYSICS]: Got NaN Velocity in Object {0}", Name); 507 return Vector3.Zero;
508 } 508 return _velocity;
509 509 }
510 } 510 set
511 } 511 {
512 512 if (value.IsFinite())
513 public override Vector3 Torque 513 {
514 { 514 AddChange(changes.Velocity, value);
515 get 515 // _velocity = value;
516 { 516
517 if (!IsPhysical || Body == IntPtr.Zero) 517 }
518 return Vector3.Zero; 518 else
519 519 {
520 return _torque; 520 m_log.WarnFormat("[PHYSICS]: Got NaN Velocity in Object {0}", Name);
521 } 521 }
522 522
523 set 523 }
524 { 524 }
525 if (value.IsFinite()) 525
526 { 526 public override Vector3 Torque
527 AddChange(changes.Torque, value); 527 {
528 } 528 get
529 else 529 {
530 { 530 if (!IsPhysical || Body == IntPtr.Zero)
531 m_log.WarnFormat("[PHYSICS]: Got NaN Torque in Object {0}", Name); 531 return Vector3.Zero;
532 } 532
533 } 533 return _torque;
534 } 534 }
535 535
536 public override float CollisionScore 536 set
537 { 537 {
538 get { return m_collisionscore; } 538 if (value.IsFinite())
539 set { m_collisionscore = value; } 539 {
540 } 540 AddChange(changes.Torque, value);
541 541 }
542 public override bool Kinematic 542 else
543 { 543 {
544 get { return false; } 544 m_log.WarnFormat("[PHYSICS]: Got NaN Torque in Object {0}", Name);
545 set { } 545 }
546 } 546 }
547 547 }
548 public override Quaternion Orientation 548
549 { 549 public override float CollisionScore
550 get 550 {
551 { 551 get { return m_collisionscore; }
552 if (givefakeori > 0) 552 set { m_collisionscore = value; }
553 return fakeori; 553 }
554 else 554
555 555 public override bool Kinematic
556 return _orientation; 556 {
557 } 557 get { return false; }
558 set 558 set { }
559 { 559 }
560 if (QuaternionIsFinite(value)) 560
561 { 561 public override Quaternion Orientation
562 fakeori = value; 562 {
563 givefakeori++; 563 get
564 AddChange(changes.Orientation, value); 564 {
565 } 565 if (givefakeori > 0)
566 else 566 return fakeori;
567 m_log.WarnFormat("[PHYSICS]: Got NaN quaternion Orientation from Scene in Object {0}", Name); 567 else
568 568
569 } 569 return _orientation;
570 } 570 }
571 571 set
572 public override Vector3 Acceleration 572 {
573 { 573 if (QuaternionIsFinite(value))
574 get { return _acceleration; } 574 {
575 set { } 575 fakeori = value;
576 } 576 givefakeori++;
577 577 AddChange(changes.Orientation, value);
578 public override Vector3 RotationalVelocity 578 }
579 { 579 else
580 get 580 m_log.WarnFormat("[PHYSICS]: Got NaN quaternion Orientation from Scene in Object {0}", Name);
581 { 581
582 Vector3 pv = Vector3.Zero; 582 }
583 if (_zeroFlag) 583 }
584 return pv; 584
585 m_lastUpdateSent = false; 585 public override Vector3 Acceleration
586 586 {
587 if (m_rotationalVelocity.ApproxEquals(pv, 0.0001f)) 587 get { return _acceleration; }
588 return pv; 588 set { }
589 589 }
590 return m_rotationalVelocity; 590
591 } 591 public override Vector3 RotationalVelocity
592 set 592 {
593 { 593 get
594 if (value.IsFinite()) 594 {
595 { 595 Vector3 pv = Vector3.Zero;
596 m_rotationalVelocity = value; 596 if (_zeroFlag)
597 if (Body != IntPtr.Zero && !d.BodyIsEnabled(Body)) 597 return pv;
598 d.BodyEnable(Body); 598 m_lastUpdateSent = false;
599 } 599
600 else 600 if (m_rotationalVelocity.ApproxEquals(pv, 0.0001f))
601 { 601 return pv;
602 m_log.WarnFormat("[PHYSICS]: Got NaN RotationalVelocity in Object {0}", Name); 602
603 } 603 return m_rotationalVelocity;
604 } 604 }
605 } 605 set
606 606 {
607 607 if (value.IsFinite())
608 public override float Buoyancy 608 {
609 { 609 m_rotationalVelocity = value;
610 get { return m_buoyancy; } 610 if (Body != IntPtr.Zero && !d.BodyIsEnabled(Body))
611 set 611 d.BodyEnable(Body);
612 { 612 }
613 m_buoyancy = value; 613 else
614 } 614 {
615 } 615 m_log.WarnFormat("[PHYSICS]: Got NaN RotationalVelocity in Object {0}", Name);
616 616 }
617 public override bool FloatOnWater 617 }
618 { 618 }
619 set 619
620 { 620
621 AddChange(changes.CollidesWater, value); 621 public override float Buoyancy
622 } 622 {
623 } 623 get { return m_buoyancy; }
624 624 set
625 public override Vector3 PIDTarget 625 {
626 { 626 m_buoyancy = value;
627 set 627 }
628 { 628 }
629 if (value.IsFinite()) 629
630 { 630 public override bool FloatOnWater
631 m_PIDTarget = value; 631 {
632 } 632 set
633 else 633 {
634 m_log.WarnFormat("[PHYSICS]: Got NaN PIDTarget from Scene on Object {0}", Name); 634 AddChange(changes.CollidesWater, value);
635 } 635 }
636 } 636 }
637 637
638 public override bool PIDActive { set { m_usePID = value; } } 638 public override Vector3 PIDTarget
639 public override float PIDTau { set { m_PIDTau = value; } } 639 {
640 640 set
641 public override float PIDHoverHeight { set { m_PIDHoverHeight = value; ; } } 641 {
642 public override bool PIDHoverActive { set { m_useHoverPID = value; } } 642 if (value.IsFinite())
643 public override PIDHoverType PIDHoverType { set { m_PIDHoverType = value; } } 643 {
644 public override float PIDHoverTau { set { m_PIDHoverTau = value; } } 644 m_PIDTarget = value;
645 645 }
646 public override Quaternion APIDTarget { set { return; } } 646 else
647 647 m_log.WarnFormat("[PHYSICS]: Got NaN PIDTarget from Scene on Object {0}", Name);
648 public override bool APIDActive { set { return; } } 648 }
649 649 }
650 public override float APIDStrength { set { return; } } 650
651 651 public override bool PIDActive { set { m_usePID = value; } }
652 public override float APIDDamping { set { return; } } 652 public override float PIDTau { set { m_PIDTau = value; } }
653 653
654 public override int VehicleType 654 public override float PIDHoverHeight { set { m_PIDHoverHeight = value; ; } }
655 { 655 public override bool PIDHoverActive { set { m_useHoverPID = value; } }
656 // we may need to put a fake on this 656 public override PIDHoverType PIDHoverType { set { m_PIDHoverType = value; } }
657 get 657 public override float PIDHoverTau { set { m_PIDHoverTau = value; } }
658 { 658
659 if (m_vehicle == null) 659 public override Quaternion APIDTarget { set { return; } }
660 return (int)Vehicle.TYPE_NONE; 660
661 else 661 public override bool APIDActive { set { return; } }
662 return (int)m_vehicle.Type; 662
663 } 663 public override float APIDStrength { set { return; } }
664 set 664
665 { 665 public override float APIDDamping { set { return; } }
666 AddChange(changes.VehicleType, value); 666
667 } 667 public override int VehicleType
668 } 668 {
669 669 // we may need to put a fake on this
670 public override void VehicleFloatParam(int param, float value) 670 get
671 { 671 {
672 strVehicleFloatParam fp = new strVehicleFloatParam(); 672 if (m_vehicle == null)
673 fp.param = param; 673 return (int)Vehicle.TYPE_NONE;
674 fp.value = value; 674 else
675 AddChange(changes.VehicleFloatParam, fp); 675 return (int)m_vehicle.Type;
676 } 676 }
677 677 set
678 public override void VehicleVectorParam(int param, Vector3 value) 678 {
679 { 679 AddChange(changes.VehicleType, value);
680 strVehicleVectorParam fp = new strVehicleVectorParam(); 680 }
681 fp.param = param; 681 }
682 fp.value = value; 682
683 AddChange(changes.VehicleVectorParam, fp); 683 public override void VehicleFloatParam(int param, float value)
684 } 684 {
685 685 strVehicleFloatParam fp = new strVehicleFloatParam();
686 public override void VehicleRotationParam(int param, Quaternion value) 686 fp.param = param;
687 { 687 fp.value = value;
688 strVehicleQuatParam fp = new strVehicleQuatParam(); 688 AddChange(changes.VehicleFloatParam, fp);
689 fp.param = param; 689 }
690 fp.value = value; 690
691 AddChange(changes.VehicleRotationParam, fp); 691 public override void VehicleVectorParam(int param, Vector3 value)
692 } 692 {
693 693 strVehicleVectorParam fp = new strVehicleVectorParam();
694 public override void VehicleFlags(int param, bool value) 694 fp.param = param;
695 { 695 fp.value = value;
696 strVehicleBoolParam bp = new strVehicleBoolParam(); 696 AddChange(changes.VehicleVectorParam, fp);
697 bp.param = param; 697 }
698 bp.value = value; 698
699 AddChange(changes.VehicleFlags, bp); 699 public override void VehicleRotationParam(int param, Quaternion value)
700 } 700 {
701 701 strVehicleQuatParam fp = new strVehicleQuatParam();
702 public override void SetVehicle(object vdata) 702 fp.param = param;
703 { 703 fp.value = value;
704 AddChange(changes.SetVehicle, vdata); 704 AddChange(changes.VehicleRotationParam, fp);
705 } 705 }
706 public void SetAcceleration(Vector3 accel) 706
707 { 707 public override void VehicleFlags(int param, bool value)
708 _acceleration = accel; 708 {
709 } 709 strVehicleBoolParam bp = new strVehicleBoolParam();
710 710 bp.param = param;
711 public override void AddForce(Vector3 force, bool pushforce) 711 bp.value = value;
712 { 712 AddChange(changes.VehicleFlags, bp);
713 if (force.IsFinite()) 713 }
714 { 714
715 AddChange(changes.AddForce, force / _parent_scene.ODE_STEPSIZE); 715 public override void SetVehicle(object vdata)
716 } 716 {
717 else 717 AddChange(changes.SetVehicle, vdata);
718 { 718 }
719 m_log.WarnFormat("[PHYSICS]: Got Invalid linear force vector from Scene in Object {0}", Name); 719 public void SetAcceleration(Vector3 accel)
720 } 720 {
721 //m_log.Info("[PHYSICS]: Added Force:" + force.ToString() + " to prim at " + Position.ToString()); 721 _acceleration = accel;
722 } 722 }
723 723
724 public override void AddAngularForce(Vector3 force, bool pushforce) 724 public override void AddForce(Vector3 force, bool pushforce)
725 { 725 {
726 if (force.IsFinite()) 726 if (force.IsFinite())
727 { 727 {
728 AddChange(changes.AddAngForce, force / _parent_scene.ODE_STEPSIZE); 728 AddChange(changes.AddForce, force / _parent_scene.ODE_STEPSIZE);
729 } 729 }
730 else 730 else
731 { 731 {
732 m_log.WarnFormat("[PHYSICS]: Got Invalid Angular force vector from Scene in Object {0}", Name); 732 m_log.WarnFormat("[PHYSICS]: Got Invalid linear force vector from Scene in Object {0}", Name);
733 } 733 }
734 } 734 //m_log.Info("[PHYSICS]: Added Force:" + force.ToString() + " to prim at " + Position.ToString());
735 735 }
736 public override void CrossingFailure() 736
737 { 737 public override void AddAngularForce(Vector3 force, bool pushforce)
738 if (m_outbounds) 738 {
739 { 739 if (force.IsFinite())
740 _position.X = Util.Clip(_position.X, 0.5f, _parent_scene.WorldExtents.X - 0.5f); 740 {
741 _position.Y = Util.Clip(_position.Y, 0.5f, _parent_scene.WorldExtents.Y - 0.5f); 741 AddChange(changes.AddAngForce, force / _parent_scene.ODE_STEPSIZE);
742 _position.Z = Util.Clip(_position.Z + 0.2f, -100f, 50000f); 742 }
743 743 else
744 m_lastposition = _position; 744 {
745 _velocity.X = 0; 745 m_log.WarnFormat("[PHYSICS]: Got Invalid Angular force vector from Scene in Object {0}", Name);
746 _velocity.Y = 0; 746 }
747 _velocity.Z = 0; 747 }
748 748
749 m_lastVelocity = _velocity; 749 public override void CrossingFailure()
750 if (m_vehicle != null && m_vehicle.Type != Vehicle.TYPE_NONE) 750 {
751 m_vehicle.Stop(); 751 if (m_outbounds)
752 752 {
753 if(Body != IntPtr.Zero) 753 _position.X = Util.Clip(_position.X, 0.5f, _parent_scene.WorldExtents.X - 0.5f);
754 d.BodySetLinearVel(Body, 0, 0, 0); // stop it 754 _position.Y = Util.Clip(_position.Y, 0.5f, _parent_scene.WorldExtents.Y - 0.5f);
755 if (prim_geom != IntPtr.Zero) 755 _position.Z = Util.Clip(_position.Z + 0.2f, -100f, 50000f);
756 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z); 756
757 757 m_lastposition = _position;
758 m_outbounds = false; 758 _velocity.X = 0;
759 changeDisable(false); 759 _velocity.Y = 0;
760 base.RequestPhysicsterseUpdate(); 760 _velocity.Z = 0;
761 } 761
762 } 762 m_lastVelocity = _velocity;
763 763 if (m_vehicle != null && m_vehicle.Type != Vehicle.TYPE_NONE)
764 public override void SetMomentum(Vector3 momentum) 764 m_vehicle.Stop();
765 { 765
766 } 766 if(Body != IntPtr.Zero)
767 767 d.BodySetLinearVel(Body, 0, 0, 0); // stop it
768 public override void SetMaterial(int pMaterial) 768 if (prim_geom != IntPtr.Zero)
769 { 769 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
770 m_material = pMaterial; 770
771 mu = _parent_scene.m_materialContactsData[pMaterial].mu; 771 m_outbounds = false;
772 bounce = _parent_scene.m_materialContactsData[pMaterial].bounce; 772 changeDisable(false);
773 } 773 base.RequestPhysicsterseUpdate();
774 774 }
775 public void setPrimForRemoval() 775 }
776 { 776
777 AddChange(changes.Remove, null); 777 public override void SetMomentum(Vector3 momentum)
778 } 778 {
779 779 }
780 public override void link(PhysicsActor obj) 780
781 { 781 public override void SetMaterial(int pMaterial)
782 AddChange(changes.Link, obj); 782 {
783 } 783 m_material = pMaterial;
784 784 mu = _parent_scene.m_materialContactsData[pMaterial].mu;
785 public override void delink() 785 bounce = _parent_scene.m_materialContactsData[pMaterial].bounce;
786 { 786 }
787 AddChange(changes.DeLink, null); 787
788 } 788 public void setPrimForRemoval()
789 789 {
790 public override void LockAngularMotion(Vector3 axis) 790 AddChange(changes.Remove, null);
791 { 791 }
792 // reverse the zero/non zero values for ODE. 792
793 if (axis.IsFinite()) 793 public override void link(PhysicsActor obj)
794 { 794 {
795 axis.X = (axis.X > 0) ? 1f : 0f; 795 AddChange(changes.Link, obj);
796 axis.Y = (axis.Y > 0) ? 1f : 0f; 796 }
797 axis.Z = (axis.Z > 0) ? 1f : 0f; 797
798 m_log.DebugFormat("[axislock]: <{0},{1},{2}>", axis.X, axis.Y, axis.Z); 798 public override void delink()
799 AddChange(changes.AngLock, axis); 799 {
800 } 800 AddChange(changes.DeLink, null);
801 else 801 }
802 { 802
803 m_log.WarnFormat("[PHYSICS]: Got NaN locking axis from Scene on Object {0}", Name); 803 public override void LockAngularMotion(Vector3 axis)
804 } 804 {
805 } 805 // reverse the zero/non zero values for ODE.
806 806 if (axis.IsFinite())
807 public override void SubscribeEvents(int ms) 807 {
808 { 808 axis.X = (axis.X > 0) ? 1f : 0f;
809 m_eventsubscription = ms; 809 axis.Y = (axis.Y > 0) ? 1f : 0f;
810 _parent_scene.AddCollisionEventReporting(this); 810 axis.Z = (axis.Z > 0) ? 1f : 0f;
811 } 811 m_log.DebugFormat("[axislock]: <{0},{1},{2}>", axis.X, axis.Y, axis.Z);
812 812 AddChange(changes.AngLock, axis);
813 public override void UnSubscribeEvents() 813 }
814 { 814 else
815 _parent_scene.RemoveCollisionEventReporting(this); 815 {
816 m_eventsubscription = 0; 816 m_log.WarnFormat("[PHYSICS]: Got NaN locking axis from Scene on Object {0}", Name);
817 } 817 }
818 818 }
819 public void AddCollisionEvent(uint CollidedWith, ContactPoint contact) 819
820 { 820 public override void SubscribeEvents(int ms)
821 if (CollisionEventsThisFrame == null) 821 {
822 CollisionEventsThisFrame = new CollisionEventUpdate(); 822 m_eventsubscription = ms;
823 823 _parent_scene.AddCollisionEventReporting(this);
824 CollisionEventsThisFrame.AddCollider(CollidedWith, contact); 824 }
825 } 825
826 826 public override void UnSubscribeEvents()
827 public void SendCollisions() 827 {
828 { 828 _parent_scene.RemoveCollisionEventReporting(this);
829 if (CollisionEventsThisFrame == null) 829 m_eventsubscription = 0;
830 return; 830 }
831 831
832 base.SendCollisionUpdate(CollisionEventsThisFrame); 832 public void AddCollisionEvent(uint CollidedWith, ContactPoint contact)
833 833 {
834 if (CollisionEventsThisFrame.m_objCollisionList.Count == 0) 834 if (CollisionEventsThisFrame == null)
835 CollisionEventsThisFrame = null; 835 CollisionEventsThisFrame = new CollisionEventUpdate();
836 else 836
837 CollisionEventsThisFrame = new CollisionEventUpdate(); 837 CollisionEventsThisFrame.AddCollider(CollidedWith, contact);
838 } 838 }
839 839
840 public override bool SubscribedEvents() 840 public void SendCollisions()
841 { 841 {
842 if (m_eventsubscription > 0) 842 if (CollisionEventsThisFrame == null)
843 return true; 843 return;
844 return false; 844
845 } 845 base.SendCollisionUpdate(CollisionEventsThisFrame);
846 846
847 847 if (CollisionEventsThisFrame.m_objCollisionList.Count == 0)
848 public OdePrim(String primName, OdeScene parent_scene, Vector3 pos, Vector3 size, 848 CollisionEventsThisFrame = null;
849 Quaternion rotation, PrimitiveBaseShape pbs, bool pisPhysical,bool pisPhantom,uint plocalID) 849 else
850 { 850 CollisionEventsThisFrame = new CollisionEventUpdate();
851 Name = primName; 851 }
852 LocalID = plocalID; 852
853 853 public override bool SubscribedEvents()
854 m_vehicle = null; 854 {
855 855 if (m_eventsubscription > 0)
856 if (!pos.IsFinite()) 856 return true;
857 { 857 return false;
858 pos = new Vector3(((float)Constants.RegionSize * 0.5f), ((float)Constants.RegionSize * 0.5f), 858 }
859 parent_scene.GetTerrainHeightAtXY(((float)Constants.RegionSize * 0.5f), ((float)Constants.RegionSize * 0.5f)) + 0.5f); 859
860 m_log.WarnFormat("[PHYSICS]: Got nonFinite Object create Position for {0}", Name); 860
861 } 861 public OdePrim(String primName, OdeScene parent_scene, Vector3 pos, Vector3 size,
862 _position = pos; 862 Quaternion rotation, PrimitiveBaseShape pbs, bool pisPhysical,bool pisPhantom,byte _shapeType,uint plocalID)
863 givefakepos = 0; 863 {
864 864 Name = primName;
865 PID_D = parent_scene.bodyPIDD; 865 LocalID = plocalID;
866 PID_G = parent_scene.bodyPIDG; 866
867 m_density = parent_scene.geomDefaultDensity; 867 m_vehicle = null;
868 // m_tensor = parent_scene.bodyMotorJointMaxforceTensor; 868
869 body_autodisable_frames = parent_scene.bodyFramesAutoDisable; 869 if (!pos.IsFinite())
870 870 {
871 prim_geom = IntPtr.Zero; 871 pos = new Vector3(((float)Constants.RegionSize * 0.5f), ((float)Constants.RegionSize * 0.5f),
872 collide_geom = IntPtr.Zero; 872 parent_scene.GetTerrainHeightAtXY(((float)Constants.RegionSize * 0.5f), ((float)Constants.RegionSize * 0.5f)) + 0.5f);
873 Body = IntPtr.Zero; 873 m_log.WarnFormat("[PHYSICS]: Got nonFinite Object create Position for {0}", Name);
874 874 }
875 if (!size.IsFinite()) 875 _position = pos;
876 { 876 givefakepos = 0;
877 size = new Vector3(0.5f, 0.5f, 0.5f); 877
878 m_log.WarnFormat("[PHYSICS]: Got nonFinite Object create Size for {0}", Name); 878 PID_D = parent_scene.bodyPIDD;
879 } 879 PID_G = parent_scene.bodyPIDG;
880 880 m_density = parent_scene.geomDefaultDensity;
881 if (size.X <= 0) size.X = 0.01f; 881 // m_tensor = parent_scene.bodyMotorJointMaxforceTensor;
882 if (size.Y <= 0) size.Y = 0.01f; 882 body_autodisable_frames = parent_scene.bodyFramesAutoDisable;
883 if (size.Z <= 0) size.Z = 0.01f; 883
884 884 prim_geom = IntPtr.Zero;
885 _size = size; 885 collide_geom = IntPtr.Zero;
886 886 Body = IntPtr.Zero;
887 if (!QuaternionIsFinite(rotation)) 887
888 { 888 if (!size.IsFinite())
889 rotation = Quaternion.Identity; 889 {
890 m_log.WarnFormat("[PHYSICS]: Got nonFinite Object create Rotation for {0}", Name); 890 size = new Vector3(0.5f, 0.5f, 0.5f);
891 } 891 m_log.WarnFormat("[PHYSICS]: Got nonFinite Object create Size for {0}", Name);
892 892 }
893 _orientation = rotation; 893
894 givefakeori = 0; 894 if (size.X <= 0) size.X = 0.01f;
895 895 if (size.Y <= 0) size.Y = 0.01f;
896 _pbs = pbs; 896 if (size.Z <= 0) size.Z = 0.01f;
897 897
898 _parent_scene = parent_scene; 898 _size = size;
899 m_targetSpace = IntPtr.Zero; 899
900 900 if (!QuaternionIsFinite(rotation))
901 if (pos.Z < 0) 901 {
902 { 902 rotation = Quaternion.Identity;
903 m_isphysical = false; 903 m_log.WarnFormat("[PHYSICS]: Got nonFinite Object create Rotation for {0}", Name);
904 } 904 }
905 else 905
906 { 906 _orientation = rotation;
907 m_isphysical = pisPhysical; 907 givefakeori = 0;
908 } 908
909 m_fakeisphysical = m_isphysical; 909 _pbs = pbs;
910 910
911 m_isVolumeDetect = false; 911 _parent_scene = parent_scene;
912 912 m_targetSpace = IntPtr.Zero;
913 m_force = Vector3.Zero; 913
914 914 if (pos.Z < 0)
915 m_iscolliding = false; 915 {
916 m_colliderfilter = 0; 916 m_isphysical = false;
917 m_softcolide = true; 917 }
918 m_NoColide = false; 918 else
919 919 {
920 hasOOBoffsetFromMesh = false; 920 m_isphysical = pisPhysical;
921 _triMeshData = IntPtr.Zero; 921 }
922 922 m_fakeisphysical = m_isphysical;
923 m_lastdoneSelected = false; 923
924 m_isSelected = false; 924 m_isVolumeDetect = false;
925 m_delaySelect = false; 925
926 926 m_force = Vector3.Zero;
927 m_isphantom = pisPhantom; 927
928 m_fakeisphantom = pisPhantom; 928 m_iscolliding = false;
929 929 m_colliderfilter = 0;
930 mu = parent_scene.m_materialContactsData[(int)Material.Wood].mu; 930 m_softcolide = true;
931 bounce = parent_scene.m_materialContactsData[(int)Material.Wood].bounce; 931 m_NoColide = false;
932 932
933 CalcPrimBodyData(); 933 hasOOBoffsetFromMesh = false;
934 934 _triMeshData = IntPtr.Zero;
935 m_building = true; // control must set this to false when done 935
936 936 m_shapetype = _shapeType;
937 AddChange(changes.Add, null); 937
938 } 938 m_lastdoneSelected = false;
939 939 m_isSelected = false;
940 private void resetCollisionAccounting() 940 m_delaySelect = false;
941 { 941
942 m_collisionscore = 0; 942 m_isphantom = pisPhantom;
943 } 943 m_fakeisphantom = pisPhantom;
944 944
945 private void createAMotor(Vector3 axis) 945 mu = parent_scene.m_materialContactsData[(int)Material.Wood].mu;
946 { 946 bounce = parent_scene.m_materialContactsData[(int)Material.Wood].bounce;
947 if (Body == IntPtr.Zero) 947
948 return; 948 CalcPrimBodyData();
949 949
950 if (Amotor != IntPtr.Zero) 950 m_building = true; // control must set this to false when done
951 { 951
952 d.JointDestroy(Amotor); 952 AddChange(changes.Add, null);
953 Amotor = IntPtr.Zero; 953 }
954 } 954
955 955 private void resetCollisionAccounting()
956 int axisnum = 3 - (int)(axis.X + axis.Y + axis.Z); 956 {
957 957 m_collisionscore = 0;
958 if (axisnum <= 0) 958 }
959 return; 959
960 960 private void createAMotor(Vector3 axis)
961 // stop it 961 {
962 d.BodySetTorque(Body, 0, 0, 0); 962 if (Body == IntPtr.Zero)
963 d.BodySetAngularVel(Body, 0, 0, 0); 963 return;
964 964
965 Amotor = d.JointCreateAMotor(_parent_scene.world, IntPtr.Zero); 965 if (Amotor != IntPtr.Zero)
966 d.JointAttach(Amotor, Body, IntPtr.Zero); 966 {
967 967 d.JointDestroy(Amotor);
968 d.JointSetAMotorMode(Amotor, 0); 968 Amotor = IntPtr.Zero;
969 969 }
970 d.JointSetAMotorNumAxes(Amotor, axisnum); 970
971 971 int axisnum = 3 - (int)(axis.X + axis.Y + axis.Z);
972 // get current orientation to lock 972
973 973 if (axisnum <= 0)
974 d.Quaternion dcur = d.BodyGetQuaternion(Body); 974 return;
975 Quaternion curr; // crap convertion between identical things 975
976 curr.X = dcur.X; 976 // stop it
977 curr.Y = dcur.Y; 977 d.BodySetTorque(Body, 0, 0, 0);
978 curr.Z = dcur.Z; 978 d.BodySetAngularVel(Body, 0, 0, 0);
979 curr.W = dcur.W; 979
980 Vector3 ax; 980 Amotor = d.JointCreateAMotor(_parent_scene.world, IntPtr.Zero);
981 981 d.JointAttach(Amotor, Body, IntPtr.Zero);
982 int i = 0; 982
983 int j = 0; 983 d.JointSetAMotorMode(Amotor, 0);
984 if (axis.X == 0) 984
985 { 985 d.JointSetAMotorNumAxes(Amotor, axisnum);
986 ax = (new Vector3(1, 0, 0)) * curr; // rotate world X to current local X 986
987 // ODE should do this with axis relative to body 1 but seems to fail 987 // get current orientation to lock
988 d.JointSetAMotorAxis(Amotor, 0, 0, ax.X, ax.Y, ax.Z); 988
989 d.JointSetAMotorAngle(Amotor, 0, 0); 989 d.Quaternion dcur = d.BodyGetQuaternion(Body);
990 d.JointSetAMotorParam(Amotor, (int)d.JointParam.LoStop, -0.000001f); 990 Quaternion curr; // crap convertion between identical things
991 d.JointSetAMotorParam(Amotor, (int)d.JointParam.HiStop, 0.000001f); 991 curr.X = dcur.X;
992 d.JointSetAMotorParam(Amotor, (int)d.JointParam.Vel, 0); 992 curr.Y = dcur.Y;
993 d.JointSetAMotorParam(Amotor, (int)d.JointParam.FudgeFactor, 0.0001f); 993 curr.Z = dcur.Z;
994 d.JointSetAMotorParam(Amotor, (int)d.JointParam.Bounce, 0f); 994 curr.W = dcur.W;
995 d.JointSetAMotorParam(Amotor, (int)d.JointParam.FMax, 5e8f); 995 Vector3 ax;
996 d.JointSetAMotorParam(Amotor, (int)d.JointParam.StopCFM, 0f); 996
997 d.JointSetAMotorParam(Amotor, (int)d.JointParam.StopERP, 0.8f); 997 int i = 0;
998 i++; 998 int j = 0;
999 j = 256; // move to next axis set 999 if (axis.X == 0)
1000 } 1000 {
1001 1001 ax = (new Vector3(1, 0, 0)) * curr; // rotate world X to current local X
1002 if (axis.Y == 0) 1002 // ODE should do this with axis relative to body 1 but seems to fail
1003 { 1003 d.JointSetAMotorAxis(Amotor, 0, 0, ax.X, ax.Y, ax.Z);
1004 ax = (new Vector3(0, 1, 0)) * curr; 1004 d.JointSetAMotorAngle(Amotor, 0, 0);
1005 d.JointSetAMotorAxis(Amotor, i, 0, ax.X, ax.Y, ax.Z); 1005 d.JointSetAMotorParam(Amotor, (int)d.JointParam.LoStop, -0.000001f);
1006 d.JointSetAMotorAngle(Amotor, i, 0); 1006 d.JointSetAMotorParam(Amotor, (int)d.JointParam.HiStop, 0.000001f);
1007 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.LoStop, -0.000001f); 1007 d.JointSetAMotorParam(Amotor, (int)d.JointParam.Vel, 0);
1008 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.HiStop, 0.000001f); 1008 d.JointSetAMotorParam(Amotor, (int)d.JointParam.FudgeFactor, 0.0001f);
1009 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.Vel, 0); 1009 d.JointSetAMotorParam(Amotor, (int)d.JointParam.Bounce, 0f);
1010 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.FudgeFactor, 0.0001f); 1010 d.JointSetAMotorParam(Amotor, (int)d.JointParam.FMax, 5e8f);
1011 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.Bounce, 0f); 1011 d.JointSetAMotorParam(Amotor, (int)d.JointParam.StopCFM, 0f);
1012 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.FMax, 5e8f); 1012 d.JointSetAMotorParam(Amotor, (int)d.JointParam.StopERP, 0.8f);
1013 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.StopCFM, 0f); 1013 i++;
1014 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.StopERP, 0.8f); 1014 j = 256; // move to next axis set
1015 i++; 1015 }
1016 j += 256; 1016
1017 } 1017 if (axis.Y == 0)
1018 1018 {
1019 if (axis.Z == 0) 1019 ax = (new Vector3(0, 1, 0)) * curr;
1020 { 1020 d.JointSetAMotorAxis(Amotor, i, 0, ax.X, ax.Y, ax.Z);
1021 ax = (new Vector3(0, 0, 1)) * curr; 1021 d.JointSetAMotorAngle(Amotor, i, 0);
1022 d.JointSetAMotorAxis(Amotor, i, 0, ax.X, ax.Y, ax.Z); 1022 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.LoStop, -0.000001f);
1023 d.JointSetAMotorAngle(Amotor, i, 0); 1023 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.HiStop, 0.000001f);
1024 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.LoStop, -0.000001f); 1024 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.Vel, 0);
1025 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.HiStop, 0.000001f); 1025 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.FudgeFactor, 0.0001f);
1026 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.Vel, 0); 1026 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.Bounce, 0f);
1027 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.FudgeFactor, 0.0001f); 1027 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.FMax, 5e8f);
1028 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.Bounce, 0f); 1028 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.StopCFM, 0f);
1029 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.FMax, 5e8f); 1029 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.StopERP, 0.8f);
1030 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.StopCFM, 0f); 1030 i++;
1031 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.StopERP, 0.8f); 1031 j += 256;
1032 } 1032 }
1033 } 1033
1034 1034 if (axis.Z == 0)
1035 private bool setMesh(OdeScene parent_scene) 1035 {
1036 { 1036 ax = (new Vector3(0, 0, 1)) * curr;
1037 if (Body != IntPtr.Zero) 1037 d.JointSetAMotorAxis(Amotor, i, 0, ax.X, ax.Y, ax.Z);
1038 { 1038 d.JointSetAMotorAngle(Amotor, i, 0);
1039 if (childPrim) 1039 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.LoStop, -0.000001f);
1040 { 1040 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.HiStop, 0.000001f);
1041 if (_parent != null) 1041 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.Vel, 0);
1042 { 1042 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.FudgeFactor, 0.0001f);
1043 OdePrim parent = (OdePrim)_parent; 1043 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.Bounce, 0f);
1044 parent.ChildDelink(this, false); 1044 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.FMax, 5e8f);
1045 } 1045 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.StopCFM, 0f);
1046 } 1046 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.StopERP, 0.8f);
1047 else 1047 }
1048 { 1048 }
1049 DestroyBody(); 1049
1050 } 1050 private bool setMesh(OdeScene parent_scene)
1051 } 1051 {
1052 1052 if (Body != IntPtr.Zero)
1053 IMesh mesh = _parent_scene.mesher.CreateMesh(Name, _pbs, _size, (int)LevelOfDetail.High, true); 1053 {
1054 if (mesh == null) 1054 if (childPrim)
1055 { 1055 {
1056 m_log.WarnFormat("[PHYSICS]: CreateMesh Failed on prim {0} at <{1},{2},{3}>.", Name, _position.X, _position.Y, _position.Z); 1056 if (_parent != null)
1057 return false; 1057 {
1058 } 1058 OdePrim parent = (OdePrim)_parent;
1059 1059 parent.ChildDelink(this, false);
1060 IntPtr vertices, indices; 1060 }
1061 int vertexCount, indexCount; 1061 }
1062 int vertexStride, triStride; 1062 else
1063 1063 {
1064 mesh.getVertexListAsPtrToFloatArray(out vertices, out vertexStride, out vertexCount); // Note, that vertices are fixed in unmanaged heap 1064 DestroyBody();
1065 mesh.getIndexListAsPtrToIntArray(out indices, out triStride, out indexCount); // Also fixed, needs release after usage 1065 }
1066 1066 }
1067 if (vertexCount == 0 || indexCount == 0) 1067
1068 { 1068 bool convex;
1069 m_log.WarnFormat("[PHYSICS]: Got invalid mesh on prim {0} at <{1},{2},{3}>. mesh UUID {4}", 1069 if (m_shapetype == 0)
1070 Name, _position.X, _position.Y, _position.Z, _pbs.SculptTexture.ToString()); 1070 convex = false;
1071 mesh.releaseSourceMeshData(); 1071 else
1072 return false; 1072 convex = true;
1073 } 1073
1074 1074 IMesh mesh = _parent_scene.mesher.CreateMesh(Name, _pbs, _size, (int)LevelOfDetail.High, true,convex);
1075 primOOBoffset = mesh.GetCentroid(); 1075 if (mesh == null)
1076 hasOOBoffsetFromMesh = true; 1076 {
1077 1077 m_log.WarnFormat("[PHYSICS]: CreateMesh Failed on prim {0} at <{1},{2},{3}>.", Name, _position.X, _position.Y, _position.Z);
1078 mesh.releaseSourceMeshData(); 1078 return false;
1079 1079 }
1080 IntPtr geo = IntPtr.Zero; 1080
1081 1081 IntPtr vertices, indices;
1082 try 1082 int vertexCount, indexCount;
1083 { 1083 int vertexStride, triStride;
1084 _triMeshData = d.GeomTriMeshDataCreate(); 1084
1085 1085 mesh.getVertexListAsPtrToFloatArray(out vertices, out vertexStride, out vertexCount); // Note, that vertices are fixed in unmanaged heap
1086 d.GeomTriMeshDataBuildSimple(_triMeshData, vertices, vertexStride, vertexCount, indices, indexCount, triStride); 1086 mesh.getIndexListAsPtrToIntArray(out indices, out triStride, out indexCount); // Also fixed, needs release after usage
1087 d.GeomTriMeshDataPreprocess(_triMeshData); 1087
1088 1088 if (vertexCount == 0 || indexCount == 0)
1089 _parent_scene.waitForSpaceUnlock(m_targetSpace); 1089 {
1090 geo = d.CreateTriMesh(m_targetSpace, _triMeshData, null, null, null); 1090 m_log.WarnFormat("[PHYSICS]: Got invalid mesh on prim {0} at <{1},{2},{3}>. mesh UUID {4}",
1091 } 1091 Name, _position.X, _position.Y, _position.Z, _pbs.SculptTexture.ToString());
1092 1092 mesh.releaseSourceMeshData();
1093 catch (Exception e) 1093 return false;
1094 { 1094 }
1095 m_log.ErrorFormat("[PHYSICS]: SetGeom Mesh failed for {0} exception: {1}", Name, e); 1095
1096 if (_triMeshData != IntPtr.Zero) 1096 primOOBoffset = mesh.GetCentroid();
1097 { 1097 hasOOBoffsetFromMesh = true;
1098 d.GeomTriMeshDataDestroy(_triMeshData); 1098
1099 _triMeshData = IntPtr.Zero; 1099 mesh.releaseSourceMeshData();
1100 } 1100
1101 return false; 1101 IntPtr geo = IntPtr.Zero;
1102 } 1102
1103 1103 try
1104 SetGeom(geo); 1104 {
1105 return true; 1105 _triMeshData = d.GeomTriMeshDataCreate();
1106 } 1106
1107 1107 d.GeomTriMeshDataBuildSimple(_triMeshData, vertices, vertexStride, vertexCount, indices, indexCount, triStride);
1108 private void SetGeom(IntPtr geom) 1108 d.GeomTriMeshDataPreprocess(_triMeshData);
1109 { 1109
1110 prim_geom = geom; 1110 _parent_scene.waitForSpaceUnlock(m_targetSpace);
1111 //Console.WriteLine("SetGeom to " + prim_geom + " for " + Name); 1111 geo = d.CreateTriMesh(m_targetSpace, _triMeshData, null, null, null);
1112 if (prim_geom != IntPtr.Zero) 1112 }
1113 { 1113
1114 if (m_NoColide) 1114 catch (Exception e)
1115 { 1115 {
1116 d.GeomSetCategoryBits(prim_geom, 0); 1116 m_log.ErrorFormat("[PHYSICS]: SetGeom Mesh failed for {0} exception: {1}", Name, e);
1117 if (m_isphysical) 1117 if (_triMeshData != IntPtr.Zero)
1118 { 1118 {
1119 d.GeomSetCollideBits(prim_geom, (int)CollisionCategories.Land); 1119 d.GeomTriMeshDataDestroy(_triMeshData);
1120 } 1120 _triMeshData = IntPtr.Zero;
1121 else 1121 }
1122 { 1122 return false;
1123 d.GeomSetCollideBits(prim_geom, 0); 1123 }
1124 d.GeomDisable(prim_geom); 1124
1125 } 1125 SetGeom(geo);
1126 } 1126 return true;
1127 else 1127 }
1128 { 1128
1129 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories); 1129 private void SetGeom(IntPtr geom)
1130 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); 1130 {
1131 } 1131 prim_geom = geom;
1132 1132 //Console.WriteLine("SetGeom to " + prim_geom + " for " + Name);
1133 CalcPrimBodyData(); 1133 if (prim_geom != IntPtr.Zero)
1134 1134 {
1135 _parent_scene.geom_name_map[prim_geom] = Name; 1135 if (m_NoColide)
1136 _parent_scene.actor_name_map[prim_geom] = this; 1136 {
1137 1137 d.GeomSetCategoryBits(prim_geom, 0);
1138 } 1138 if (m_isphysical)
1139 else 1139 {
1140 m_log.Warn("Setting bad Geom"); 1140 d.GeomSetCollideBits(prim_geom, (int)CollisionCategories.Land);
1141 } 1141 }
1142 1142 else
1143 1143 {
1144 /// <summary> 1144 d.GeomSetCollideBits(prim_geom, 0);
1145 /// Create a geometry for the given mesh in the given target space. 1145 d.GeomDisable(prim_geom);
1146 /// </summary> 1146 }
1147 /// <param name="m_targetSpace"></param> 1147 }
1148 /// <param name="mesh">If null, then a mesh is used that is based on the profile shape data.</param> 1148 else
1149 private void CreateGeom() 1149 {
1150 { 1150 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
1151 if (_triMeshData != IntPtr.Zero) 1151 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
1152 { 1152 }
1153 d.GeomTriMeshDataDestroy(_triMeshData); 1153
1154 _triMeshData = IntPtr.Zero; 1154 CalcPrimBodyData();
1155 } 1155
1156 1156 _parent_scene.geom_name_map[prim_geom] = Name;
1157 bool haveMesh = false; 1157 _parent_scene.actor_name_map[prim_geom] = this;
1158 hasOOBoffsetFromMesh = false; 1158
1159 m_NoColide = false; 1159 }
1160 1160 else
1161 if (_parent_scene.needsMeshing(_pbs)) 1161 m_log.Warn("Setting bad Geom");
1162 { 1162 }
1163 haveMesh = setMesh(_parent_scene); // this will give a mesh to non trivial known prims 1163
1164 if (!haveMesh) 1164
1165 m_NoColide = true; 1165 /// <summary>
1166 } 1166 /// Create a geometry for the given mesh in the given target space.
1167 1167 /// </summary>
1168 if (!haveMesh) 1168 /// <param name="m_targetSpace"></param>
1169 { 1169 /// <param name="mesh">If null, then a mesh is used that is based on the profile shape data.</param>
1170 if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1 1170 private void CreateGeom()
1171 && _size.X == _size.Y && _size.Y == _size.Z) 1171 {
1172 { // it's a sphere 1172 if (_triMeshData != IntPtr.Zero)
1173 _parent_scene.waitForSpaceUnlock(m_targetSpace); 1173 {
1174 try 1174 d.GeomTriMeshDataDestroy(_triMeshData);
1175 { 1175 _triMeshData = IntPtr.Zero;
1176 SetGeom(d.CreateSphere(m_targetSpace, _size.X * 0.5f)); 1176 }
1177 } 1177
1178 catch (Exception e) 1178 bool haveMesh = false;
1179 { 1179 hasOOBoffsetFromMesh = false;
1180 m_log.WarnFormat("[PHYSICS]: Create sphere failed: {0}", e); 1180 m_NoColide = false;
1181 return; 1181
1182 } 1182 if (_parent_scene.needsMeshing(_pbs))
1183 } 1183 {
1184 else 1184 haveMesh = setMesh(_parent_scene); // this will give a mesh to non trivial known prims
1185 {// do it as a box 1185 if (!haveMesh)
1186 _parent_scene.waitForSpaceUnlock(m_targetSpace); 1186 m_NoColide = true;
1187 try 1187 }
1188 { 1188
1189 //Console.WriteLine(" CreateGeom 4"); 1189 if (!haveMesh)
1190 SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z)); 1190 {
1191 } 1191 if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1
1192 catch (Exception e) 1192 && _size.X == _size.Y && _size.Y == _size.Z)
1193 { 1193 { // it's a sphere
1194 m_log.Warn("[PHYSICS]: Create box failed: {0}", e); 1194 _parent_scene.waitForSpaceUnlock(m_targetSpace);
1195 return; 1195 try
1196 } 1196 {
1197 } 1197 SetGeom(d.CreateSphere(m_targetSpace, _size.X * 0.5f));
1198 } 1198 }
1199 } 1199 catch (Exception e)
1200 1200 {
1201 /// <summary> 1201 m_log.WarnFormat("[PHYSICS]: Create sphere failed: {0}", e);
1202 /// Set a new geometry for this prim. 1202 return;
1203 /// </summary> 1203 }
1204 /// <param name="geom"></param> 1204 }
1205 private void RemoveGeom() 1205 else
1206 { 1206 {// do it as a box
1207 if (prim_geom != IntPtr.Zero) 1207 _parent_scene.waitForSpaceUnlock(m_targetSpace);
1208 { 1208 try
1209 _parent_scene.geom_name_map.Remove(prim_geom); 1209 {
1210 _parent_scene.actor_name_map.Remove(prim_geom); 1210 //Console.WriteLine(" CreateGeom 4");
1211 try 1211 SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z));
1212 { 1212 }
1213 d.GeomDestroy(prim_geom); 1213 catch (Exception e)
1214 if (_triMeshData != IntPtr.Zero) 1214 {
1215 { 1215 m_log.Warn("[PHYSICS]: Create box failed: {0}", e);
1216 d.GeomTriMeshDataDestroy(_triMeshData); 1216 return;
1217 _triMeshData = IntPtr.Zero; 1217 }
1218 } 1218 }
1219 } 1219 }
1220 // catch (System.AccessViolationException) 1220 }
1221 catch (Exception e) 1221
1222 { 1222 /// <summary>
1223 m_log.ErrorFormat("[PHYSICS]: PrimGeom destruction failed for {0} exception {1}", Name, e); 1223 /// Set a new geometry for this prim.
1224 } 1224 /// </summary>
1225 1225 /// <param name="geom"></param>
1226 prim_geom = IntPtr.Zero; 1226 private void RemoveGeom()
1227 } 1227 {
1228 else 1228 if (prim_geom != IntPtr.Zero)
1229 { 1229 {
1230 m_log.ErrorFormat("[PHYSICS]: PrimGeom destruction BAD {0}", Name); 1230 _parent_scene.geom_name_map.Remove(prim_geom);
1231 } 1231 _parent_scene.actor_name_map.Remove(prim_geom);
1232 Body = IntPtr.Zero; 1232 try
1233 hasOOBoffsetFromMesh = false; 1233 {
1234 CalcPrimBodyData(); 1234 d.GeomDestroy(prim_geom);
1235 } 1235 if (_triMeshData != IntPtr.Zero)
1236 1236 {
1237 private void ChildSetGeom(OdePrim odePrim) 1237 d.GeomTriMeshDataDestroy(_triMeshData);
1238 { 1238 _triMeshData = IntPtr.Zero;
1239 // well.. 1239 }
1240 DestroyBody(); 1240 }
1241 MakeBody(); 1241 // catch (System.AccessViolationException)
1242 } 1242 catch (Exception e)
1243 1243 {
1244 //sets non physical prim m_targetSpace to right space in spaces grid for static prims 1244 m_log.ErrorFormat("[PHYSICS]: PrimGeom destruction failed for {0} exception {1}", Name, e);
1245 // should only be called for non physical prims unless they are becoming non physical 1245 }
1246 private void SetInStaticSpace(OdePrim prim) 1246
1247 { 1247 prim_geom = IntPtr.Zero;
1248 IntPtr targetSpace = _parent_scene.MoveGeomToStaticSpace(prim.prim_geom, prim._position, prim.m_targetSpace); 1248 }
1249 prim.m_targetSpace = targetSpace; 1249 else
1250 d.GeomEnable(prim_geom); 1250 {
1251 } 1251 m_log.ErrorFormat("[PHYSICS]: PrimGeom destruction BAD {0}", Name);
1252 1252 }
1253 public void enableBodySoft() 1253 Body = IntPtr.Zero;
1254 { 1254 hasOOBoffsetFromMesh = false;
1255 if (!childPrim && !m_isSelected) 1255 CalcPrimBodyData();
1256 { 1256 }
1257 if (m_isphysical && Body != IntPtr.Zero) 1257
1258 { 1258 private void ChildSetGeom(OdePrim odePrim)
1259 if (m_isphantom && !m_isVolumeDetect) 1259 {
1260 { 1260 // well..
1261 m_collisionCategories = 0; 1261 DestroyBody();
1262 m_collisionFlags = CollisionCategories.Land; 1262 MakeBody();
1263 } 1263 }
1264 else 1264
1265 { 1265 //sets non physical prim m_targetSpace to right space in spaces grid for static prims
1266 m_collisionCategories |= CollisionCategories.Body; 1266 // should only be called for non physical prims unless they are becoming non physical
1267 m_collisionFlags |= (CollisionCategories.Land | CollisionCategories.Wind); 1267 private void SetInStaticSpace(OdePrim prim)
1268 } 1268 {
1269 1269 IntPtr targetSpace = _parent_scene.MoveGeomToStaticSpace(prim.prim_geom, prim._position, prim.m_targetSpace);
1270 foreach (OdePrim prm in childrenPrim) 1270 prim.m_targetSpace = targetSpace;
1271 { 1271 d.GeomEnable(prim_geom);
1272 prm.m_collisionCategories = m_collisionCategories; 1272 }
1273 prm.m_collisionFlags = m_collisionFlags; 1273
1274 1274 public void enableBodySoft()
1275 if (prm.prim_geom != IntPtr.Zero) 1275 {
1276 { 1276 if (!childPrim && !m_isSelected)
1277 if (prm.m_NoColide) 1277 {
1278 { 1278 if (m_isphysical && Body != IntPtr.Zero)
1279 d.GeomSetCategoryBits(prm.prim_geom, 0); 1279 {
1280 d.GeomSetCollideBits(prm.prim_geom, (int)CollisionCategories.Land); 1280 if (m_isphantom && !m_isVolumeDetect)
1281 } 1281 {
1282 else 1282 m_collisionCategories = 0;
1283 { 1283 m_collisionFlags = CollisionCategories.Land;
1284 d.GeomSetCategoryBits(prm.prim_geom, (int)m_collisionCategories); 1284 }
1285 d.GeomSetCollideBits(prm.prim_geom, (int)m_collisionFlags); 1285 else
1286 } 1286 {
1287 d.GeomEnable(prm.prim_geom); 1287 m_collisionCategories |= CollisionCategories.Body;
1288 } 1288 m_collisionFlags |= (CollisionCategories.Land | CollisionCategories.Wind);
1289 } 1289 }
1290 1290
1291 if (prim_geom != IntPtr.Zero) 1291 foreach (OdePrim prm in childrenPrim)
1292 { 1292 {
1293 if (m_NoColide) 1293 prm.m_collisionCategories = m_collisionCategories;
1294 { 1294 prm.m_collisionFlags = m_collisionFlags;
1295 d.GeomSetCategoryBits(prim_geom, 0); 1295
1296 d.GeomSetCollideBits(prim_geom, (int)CollisionCategories.Land); 1296 if (prm.prim_geom != IntPtr.Zero)
1297 } 1297 {
1298 else 1298 if (prm.m_NoColide)
1299 { 1299 {
1300 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories); 1300 d.GeomSetCategoryBits(prm.prim_geom, 0);
1301 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); 1301 d.GeomSetCollideBits(prm.prim_geom, (int)CollisionCategories.Land);
1302 } 1302 }
1303 d.GeomEnable(prim_geom); 1303 else
1304 } 1304 {
1305 d.BodyEnable(Body); 1305 d.GeomSetCategoryBits(prm.prim_geom, (int)m_collisionCategories);
1306 } 1306 d.GeomSetCollideBits(prm.prim_geom, (int)m_collisionFlags);
1307 } 1307 }
1308 m_disabled = false; 1308 d.GeomEnable(prm.prim_geom);
1309 resetCollisionAccounting(); // this sets m_disable to false 1309 }
1310 } 1310 }
1311 1311
1312 private void disableBodySoft() 1312 if (prim_geom != IntPtr.Zero)
1313 { 1313 {
1314 m_disabled = true; 1314 if (m_NoColide)
1315 if (!childPrim) 1315 {
1316 { 1316 d.GeomSetCategoryBits(prim_geom, 0);
1317 if (m_isphysical && Body != IntPtr.Zero) 1317 d.GeomSetCollideBits(prim_geom, (int)CollisionCategories.Land);
1318 { 1318 }
1319 m_collisionCategories &= ~CollisionCategories.Body; 1319 else
1320 m_collisionFlags &= ~(CollisionCategories.Wind | CollisionCategories.Land); 1320 {
1321 1321 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
1322 foreach (OdePrim prm in childrenPrim) 1322 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
1323 { 1323 }
1324 prm.m_collisionCategories = m_collisionCategories; 1324 d.GeomEnable(prim_geom);
1325 prm.m_collisionFlags = m_collisionFlags; 1325 }
1326 1326 d.BodyEnable(Body);
1327 if (prm.prim_geom != IntPtr.Zero) 1327 }
1328 { 1328 }
1329 if (prm.m_NoColide) 1329 m_disabled = false;
1330 { 1330 resetCollisionAccounting(); // this sets m_disable to false
1331 d.GeomSetCategoryBits(prm.prim_geom, 0); 1331 }
1332 d.GeomSetCollideBits(prm.prim_geom, 0); 1332
1333 } 1333 private void disableBodySoft()
1334 else 1334 {
1335 { 1335 m_disabled = true;
1336 d.GeomSetCategoryBits(prm.prim_geom, (int)m_collisionCategories); 1336 if (!childPrim)
1337 d.GeomSetCollideBits(prm.prim_geom, (int)m_collisionFlags); 1337 {
1338 } 1338 if (m_isphysical && Body != IntPtr.Zero)
1339 d.GeomDisable(prm.prim_geom); 1339 {
1340 } 1340 m_collisionCategories &= ~CollisionCategories.Body;
1341 } 1341 m_collisionFlags &= ~(CollisionCategories.Wind | CollisionCategories.Land);
1342 1342
1343 if (prim_geom != IntPtr.Zero) 1343 foreach (OdePrim prm in childrenPrim)
1344 { 1344 {
1345 if (m_NoColide) 1345 prm.m_collisionCategories = m_collisionCategories;
1346 { 1346 prm.m_collisionFlags = m_collisionFlags;
1347 d.GeomSetCategoryBits(prim_geom, 0); 1347
1348 d.GeomSetCollideBits(prim_geom, 0); 1348 if (prm.prim_geom != IntPtr.Zero)
1349 } 1349 {
1350 else 1350 if (prm.m_NoColide)
1351 { 1351 {
1352 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories); 1352 d.GeomSetCategoryBits(prm.prim_geom, 0);
1353 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); 1353 d.GeomSetCollideBits(prm.prim_geom, 0);
1354 } 1354 }
1355 d.GeomDisable(prim_geom); 1355 else
1356 } 1356 {
1357 1357 d.GeomSetCategoryBits(prm.prim_geom, (int)m_collisionCategories);
1358 d.BodyDisable(Body); 1358 d.GeomSetCollideBits(prm.prim_geom, (int)m_collisionFlags);
1359 } 1359 }
1360 } 1360 d.GeomDisable(prm.prim_geom);
1361 } 1361 }
1362 1362 }
1363 private void MakeBody() 1363
1364 { 1364 if (prim_geom != IntPtr.Zero)
1365 if (!m_isphysical) // only physical get bodies 1365 {
1366 return; 1366 if (m_NoColide)
1367 1367 {
1368 if (childPrim) // child prims don't get bodies; 1368 d.GeomSetCategoryBits(prim_geom, 0);
1369 return; 1369 d.GeomSetCollideBits(prim_geom, 0);
1370 1370 }
1371 if (m_building) 1371 else
1372 return; 1372 {
1373 1373 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
1374 if (prim_geom == IntPtr.Zero) 1374 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
1375 { 1375 }
1376 m_log.Warn("[PHYSICS]: Unable to link the linkset. Root has no geom yet"); 1376 d.GeomDisable(prim_geom);
1377 return; 1377 }
1378 } 1378
1379 1379 d.BodyDisable(Body);
1380 if (Body != IntPtr.Zero) 1380 }
1381 { 1381 }
1382 d.BodyDestroy(Body); 1382 }
1383 Body = IntPtr.Zero; 1383
1384 m_log.Warn("[PHYSICS]: MakeBody called having a body"); 1384 private void MakeBody()
1385 } 1385 {
1386 1386 if (!m_isphysical) // only physical get bodies
1387 1387 return;
1388 if (d.GeomGetBody(prim_geom) != IntPtr.Zero) 1388
1389 { 1389 if (childPrim) // child prims don't get bodies;
1390 d.GeomSetBody(prim_geom, IntPtr.Zero); 1390 return;
1391 m_log.Warn("[PHYSICS]: MakeBody root geom already had a body"); 1391
1392 } 1392 if (m_building)
1393 1393 return;
1394 d.Matrix3 mymat = new d.Matrix3(); 1394
1395 d.Quaternion myrot = new d.Quaternion(); 1395 if (prim_geom == IntPtr.Zero)
1396 d.Mass objdmass = new d.Mass { }; 1396 {
1397 1397 m_log.Warn("[PHYSICS]: Unable to link the linkset. Root has no geom yet");
1398 Body = d.BodyCreate(_parent_scene.world); 1398 return;
1399 1399 }
1400 DMassDup(ref primdMass, out objdmass); 1400
1401 1401 if (Body != IntPtr.Zero)
1402 // rotate inertia 1402 {
1403 myrot.X = _orientation.X; 1403 d.BodyDestroy(Body);
1404 myrot.Y = _orientation.Y; 1404 Body = IntPtr.Zero;
1405 myrot.Z = _orientation.Z; 1405 m_log.Warn("[PHYSICS]: MakeBody called having a body");
1406 myrot.W = _orientation.W; 1406 }
1407 1407
1408 d.RfromQ(out mymat, ref myrot); 1408
1409 d.MassRotate(ref objdmass, ref mymat); 1409 if (d.GeomGetBody(prim_geom) != IntPtr.Zero)
1410 1410 {
1411 // set the body rotation and position 1411 d.GeomSetBody(prim_geom, IntPtr.Zero);
1412 d.BodySetRotation(Body, ref mymat); 1412 m_log.Warn("[PHYSICS]: MakeBody root geom already had a body");
1413 1413 }
1414 // recompute full object inertia if needed 1414
1415 if (childrenPrim.Count > 0) 1415 d.Matrix3 mymat = new d.Matrix3();
1416 { 1416 d.Quaternion myrot = new d.Quaternion();
1417 d.Matrix3 mat = new d.Matrix3(); 1417 d.Mass objdmass = new d.Mass { };
1418 d.Quaternion quat = new d.Quaternion(); 1418
1419 d.Mass tmpdmass = new d.Mass { }; 1419 Body = d.BodyCreate(_parent_scene.world);
1420 Vector3 rcm; 1420
1421 1421 DMassDup(ref primdMass, out objdmass);
1422 rcm.X = _position.X + objdmass.c.X; 1422
1423 rcm.Y = _position.Y + objdmass.c.Y; 1423 // rotate inertia
1424 rcm.Z = _position.Z + objdmass.c.Z; 1424 myrot.X = _orientation.X;
1425 1425 myrot.Y = _orientation.Y;
1426 lock (childrenPrim) 1426 myrot.Z = _orientation.Z;
1427 { 1427 myrot.W = _orientation.W;
1428 foreach (OdePrim prm in childrenPrim) 1428
1429 { 1429 d.RfromQ(out mymat, ref myrot);
1430 if (prm.prim_geom == IntPtr.Zero) 1430 d.MassRotate(ref objdmass, ref mymat);
1431 { 1431
1432 m_log.Warn("[PHYSICS]: Unable to link one of the linkset elements, skipping it. No geom yet"); 1432 // set the body rotation and position
1433 continue; 1433 d.BodySetRotation(Body, ref mymat);
1434 } 1434
1435 1435 // recompute full object inertia if needed
1436 DMassCopy(ref prm.primdMass, ref tmpdmass); 1436 if (childrenPrim.Count > 0)
1437 1437 {
1438 // apply prim current rotation to inertia 1438 d.Matrix3 mat = new d.Matrix3();
1439 quat.X = prm._orientation.X; 1439 d.Quaternion quat = new d.Quaternion();
1440 quat.Y = prm._orientation.Y; 1440 d.Mass tmpdmass = new d.Mass { };
1441 quat.Z = prm._orientation.Z; 1441 Vector3 rcm;
1442 quat.W = prm._orientation.W; 1442
1443 d.RfromQ(out mat, ref quat); 1443 rcm.X = _position.X + objdmass.c.X;
1444 d.MassRotate(ref tmpdmass, ref mat); 1444 rcm.Y = _position.Y + objdmass.c.Y;
1445 1445 rcm.Z = _position.Z + objdmass.c.Z;
1446 Vector3 ppos = prm._position; 1446
1447 ppos.X += tmpdmass.c.X - rcm.X; 1447 lock (childrenPrim)
1448 ppos.Y += tmpdmass.c.Y - rcm.Y; 1448 {
1449 ppos.Z += tmpdmass.c.Z - rcm.Z; 1449 foreach (OdePrim prm in childrenPrim)
1450 1450 {
1451 // refer inertia to root prim center of mass position 1451 if (prm.prim_geom == IntPtr.Zero)
1452 d.MassTranslate(ref tmpdmass, 1452 {
1453 ppos.X, 1453 m_log.Warn("[PHYSICS]: Unable to link one of the linkset elements, skipping it. No geom yet");
1454 ppos.Y, 1454 continue;
1455 ppos.Z); 1455 }
1456 1456
1457 d.MassAdd(ref objdmass, ref tmpdmass); // add to total object inertia 1457 DMassCopy(ref prm.primdMass, ref tmpdmass);
1458 // fix prim colision cats 1458
1459 1459 // apply prim current rotation to inertia
1460 if (d.GeomGetBody(prm.prim_geom) != IntPtr.Zero) 1460 quat.X = prm._orientation.X;
1461 { 1461 quat.Y = prm._orientation.Y;
1462 d.GeomSetBody(prm.prim_geom, IntPtr.Zero); 1462 quat.Z = prm._orientation.Z;
1463 m_log.Warn("[PHYSICS]: MakeBody child geom already had a body"); 1463 quat.W = prm._orientation.W;
1464 } 1464 d.RfromQ(out mat, ref quat);
1465 1465 d.MassRotate(ref tmpdmass, ref mat);
1466 d.GeomClearOffset(prm.prim_geom); 1466
1467 d.GeomSetBody(prm.prim_geom, Body); 1467 Vector3 ppos = prm._position;
1468 prm.Body = Body; 1468 ppos.X += tmpdmass.c.X - rcm.X;
1469 d.GeomSetOffsetWorldRotation(prm.prim_geom, ref mat); // set relative rotation 1469 ppos.Y += tmpdmass.c.Y - rcm.Y;
1470 } 1470 ppos.Z += tmpdmass.c.Z - rcm.Z;
1471 } 1471
1472 } 1472 // refer inertia to root prim center of mass position
1473 1473 d.MassTranslate(ref tmpdmass,
1474 d.GeomClearOffset(prim_geom); // make sure we don't have a hidden offset 1474 ppos.X,
1475 // associate root geom with body 1475 ppos.Y,
1476 d.GeomSetBody(prim_geom, Body); 1476 ppos.Z);
1477 1477
1478 d.BodySetPosition(Body, _position.X + objdmass.c.X, _position.Y + objdmass.c.Y, _position.Z + objdmass.c.Z); 1478 d.MassAdd(ref objdmass, ref tmpdmass); // add to total object inertia
1479 d.GeomSetOffsetWorldPosition(prim_geom, _position.X, _position.Y, _position.Z); 1479 // fix prim colision cats
1480 1480
1481 d.MassTranslate(ref objdmass, -objdmass.c.X, -objdmass.c.Y, -objdmass.c.Z); // ode wants inertia at center of body 1481 if (d.GeomGetBody(prm.prim_geom) != IntPtr.Zero)
1482 myrot.W = -myrot.W; 1482 {
1483 d.RfromQ(out mymat, ref myrot); 1483 d.GeomSetBody(prm.prim_geom, IntPtr.Zero);
1484 d.MassRotate(ref objdmass, ref mymat); 1484 m_log.Warn("[PHYSICS]: MakeBody child geom already had a body");
1485 d.BodySetMass(Body, ref objdmass); 1485 }
1486 _mass = objdmass.mass; 1486
1487 1487 d.GeomClearOffset(prm.prim_geom);
1488 // disconnect from world gravity so we can apply buoyancy 1488 d.GeomSetBody(prm.prim_geom, Body);
1489 d.BodySetGravityMode(Body, false); 1489 prm.Body = Body;
1490 1490 d.GeomSetOffsetWorldRotation(prm.prim_geom, ref mat); // set relative rotation
1491 d.BodySetAutoDisableFlag(Body, true); 1491 }
1492 d.BodySetAutoDisableSteps(Body, body_autodisable_frames); 1492 }
1493 // d.BodySetLinearDampingThreshold(Body, 0.01f); 1493 }
1494 // d.BodySetAngularDampingThreshold(Body, 0.001f); 1494
1495 d.BodySetDamping(Body, .002f, .002f); 1495 d.GeomClearOffset(prim_geom); // make sure we don't have a hidden offset
1496 1496 // associate root geom with body
1497 1497 d.GeomSetBody(prim_geom, Body);
1498 if (m_targetSpace != IntPtr.Zero) 1498
1499 { 1499 d.BodySetPosition(Body, _position.X + objdmass.c.X, _position.Y + objdmass.c.Y, _position.Z + objdmass.c.Z);
1500 _parent_scene.waitForSpaceUnlock(m_targetSpace); 1500 d.GeomSetOffsetWorldPosition(prim_geom, _position.X, _position.Y, _position.Z);
1501 if (d.SpaceQuery(m_targetSpace, prim_geom)) 1501
1502 d.SpaceRemove(m_targetSpace, prim_geom); 1502 d.MassTranslate(ref objdmass, -objdmass.c.X, -objdmass.c.Y, -objdmass.c.Z); // ode wants inertia at center of body
1503 } 1503 myrot.W = -myrot.W;
1504 1504 d.RfromQ(out mymat, ref myrot);
1505 1505 d.MassRotate(ref objdmass, ref mymat);
1506 if (childrenPrim.Count == 0) 1506 d.BodySetMass(Body, ref objdmass);
1507 { 1507 _mass = objdmass.mass;
1508 collide_geom = prim_geom; 1508
1509 m_targetSpace = _parent_scene.ActiveSpace; 1509 // disconnect from world gravity so we can apply buoyancy
1510 d.SpaceAdd(m_targetSpace, prim_geom); 1510 d.BodySetGravityMode(Body, false);
1511 } 1511
1512 else 1512 d.BodySetAutoDisableFlag(Body, true);
1513 { 1513 d.BodySetAutoDisableSteps(Body, body_autodisable_frames);
1514 m_targetSpace = d.HashSpaceCreate(_parent_scene.ActiveSpace); 1514 // d.BodySetLinearDampingThreshold(Body, 0.01f);
1515 d.HashSpaceSetLevels(m_targetSpace, -2, 8); 1515 // d.BodySetAngularDampingThreshold(Body, 0.001f);
1516 d.SpaceSetSublevel(m_targetSpace, 3); 1516 d.BodySetDamping(Body, .002f, .002f);
1517 d.SpaceSetCleanup(m_targetSpace, false); 1517
1518 d.SpaceAdd(m_targetSpace, prim_geom); 1518
1519 collide_geom = m_targetSpace; 1519 if (m_targetSpace != IntPtr.Zero)
1520 } 1520 {
1521 1521 _parent_scene.waitForSpaceUnlock(m_targetSpace);
1522 if (m_delaySelect) 1522 if (d.SpaceQuery(m_targetSpace, prim_geom))
1523 { 1523 d.SpaceRemove(m_targetSpace, prim_geom);
1524 m_isSelected = true; 1524 }
1525 m_delaySelect = false; 1525
1526 } 1526
1527 1527 if (childrenPrim.Count == 0)
1528 lock (childrenPrim) 1528 {
1529 { 1529 collide_geom = prim_geom;
1530 foreach (OdePrim prm in childrenPrim) 1530 m_targetSpace = _parent_scene.ActiveSpace;
1531 { 1531 d.SpaceAdd(m_targetSpace, prim_geom);
1532 if (prm.prim_geom == IntPtr.Zero) 1532 }
1533 continue; 1533 else
1534 1534 {
1535 Vector3 ppos = prm._position; 1535 m_targetSpace = d.HashSpaceCreate(_parent_scene.ActiveSpace);
1536 d.GeomSetOffsetWorldPosition(prm.prim_geom, ppos.X, ppos.Y, ppos.Z); // set relative position 1536 d.HashSpaceSetLevels(m_targetSpace, -2, 8);
1537 1537 d.SpaceSetSublevel(m_targetSpace, 3);
1538 if (prm.m_targetSpace != m_targetSpace) 1538 d.SpaceSetCleanup(m_targetSpace, false);
1539 { 1539 d.SpaceAdd(m_targetSpace, prim_geom);
1540 if (prm.m_targetSpace != IntPtr.Zero) 1540 collide_geom = m_targetSpace;
1541 { 1541 }
1542 _parent_scene.waitForSpaceUnlock(prm.m_targetSpace); 1542
1543 if (d.SpaceQuery(prm.m_targetSpace, prm.prim_geom)) 1543 if (m_delaySelect)
1544 d.SpaceRemove(prm.m_targetSpace, prm.prim_geom); 1544 {
1545 } 1545 m_isSelected = true;
1546 prm.m_targetSpace = m_targetSpace; 1546 m_delaySelect = false;
1547 d.SpaceAdd(m_targetSpace, prm.prim_geom); 1547 }
1548 } 1548
1549 1549 lock (childrenPrim)
1550 if (m_isSelected || m_disabled) 1550 {
1551 { 1551 foreach (OdePrim prm in childrenPrim)
1552 prm.m_collisionCategories &= ~CollisionCategories.Body; 1552 {
1553 prm.m_collisionFlags &= ~(CollisionCategories.Land | CollisionCategories.Wind); 1553 if (prm.prim_geom == IntPtr.Zero)
1554 d.GeomDisable(prm.prim_geom); 1554 continue;
1555 } 1555
1556 else 1556 Vector3 ppos = prm._position;
1557 { 1557 d.GeomSetOffsetWorldPosition(prm.prim_geom, ppos.X, ppos.Y, ppos.Z); // set relative position
1558 if (m_isphantom && !m_isVolumeDetect) 1558
1559 { 1559 if (prm.m_targetSpace != m_targetSpace)
1560 prm.m_collisionCategories = 0; 1560 {
1561 prm.m_collisionFlags = CollisionCategories.Land; 1561 if (prm.m_targetSpace != IntPtr.Zero)
1562 } 1562 {
1563 else 1563 _parent_scene.waitForSpaceUnlock(prm.m_targetSpace);
1564 { 1564 if (d.SpaceQuery(prm.m_targetSpace, prm.prim_geom))
1565 prm.m_collisionCategories |= CollisionCategories.Body; 1565 d.SpaceRemove(prm.m_targetSpace, prm.prim_geom);
1566 prm.m_collisionFlags |= (CollisionCategories.Land | CollisionCategories.Wind); 1566 }
1567 } 1567 prm.m_targetSpace = m_targetSpace;
1568 d.GeomEnable(prm.prim_geom); 1568 d.SpaceAdd(m_targetSpace, prm.prim_geom);
1569 } 1569 }
1570 1570
1571 if (prm.m_NoColide) 1571 if (m_isSelected || m_disabled)
1572 { 1572 {
1573 d.GeomSetCategoryBits(prm.prim_geom, 0); 1573 prm.m_collisionCategories &= ~CollisionCategories.Body;
1574 d.GeomSetCollideBits(prm.prim_geom, (int)CollisionCategories.Land); 1574 prm.m_collisionFlags &= ~(CollisionCategories.Land | CollisionCategories.Wind);
1575 d.GeomEnable(prm.prim_geom); 1575 d.GeomDisable(prm.prim_geom);
1576 } 1576 }
1577 else 1577 else
1578 { 1578 {
1579 d.GeomSetCategoryBits(prm.prim_geom, (int)prm.m_collisionCategories); 1579 if (m_isphantom && !m_isVolumeDetect)
1580 d.GeomSetCollideBits(prm.prim_geom, (int)prm.m_collisionFlags); 1580 {
1581 } 1581 prm.m_collisionCategories = 0;
1582 prm.m_collisionscore = 0; 1582 prm.m_collisionFlags = CollisionCategories.Land;
1583 1583 }
1584 if(!m_disabled) 1584 else
1585 prm.m_disabled = false; 1585 {
1586 1586 prm.m_collisionCategories |= CollisionCategories.Body;
1587 _parent_scene.addActivePrim(prm); 1587 prm.m_collisionFlags |= (CollisionCategories.Land | CollisionCategories.Wind);
1588 } 1588 }
1589 } 1589 d.GeomEnable(prm.prim_geom);
1590 1590 }
1591 // The body doesn't already have a finite rotation mode set here 1591
1592 if ((!m_angularlock.ApproxEquals(Vector3.One, 0.0f)) && _parent == null) 1592 if (prm.m_NoColide)
1593 { 1593 {
1594 createAMotor(m_angularlock); 1594 d.GeomSetCategoryBits(prm.prim_geom, 0);
1595 } 1595 d.GeomSetCollideBits(prm.prim_geom, (int)CollisionCategories.Land);
1596 1596 d.GeomEnable(prm.prim_geom);
1597 if (m_isSelected || m_disabled) 1597 }
1598 { 1598 else
1599 m_collisionCategories &= ~CollisionCategories.Body; 1599 {
1600 m_collisionFlags &= ~(CollisionCategories.Land | CollisionCategories.Wind); 1600 d.GeomSetCategoryBits(prm.prim_geom, (int)prm.m_collisionCategories);
1601 1601 d.GeomSetCollideBits(prm.prim_geom, (int)prm.m_collisionFlags);
1602 d.GeomDisable(prim_geom); 1602 }
1603 d.BodyDisable(Body); 1603 prm.m_collisionscore = 0;
1604 } 1604
1605 else 1605 if(!m_disabled)
1606 { 1606 prm.m_disabled = false;
1607 if (m_isphantom && !m_isVolumeDetect) 1607
1608 { 1608 _parent_scene.addActivePrim(prm);
1609 m_collisionCategories = 0; 1609 }
1610 m_collisionFlags = CollisionCategories.Land; 1610 }
1611 } 1611
1612 else 1612 // The body doesn't already have a finite rotation mode set here
1613 { 1613 if ((!m_angularlock.ApproxEquals(Vector3.One, 0.0f)) && _parent == null)
1614 m_collisionCategories |= CollisionCategories.Body; 1614 {
1615 m_collisionFlags |= (CollisionCategories.Land | CollisionCategories.Wind); 1615 createAMotor(m_angularlock);
1616 } 1616 }
1617 1617
1618 d.BodySetAngularVel(Body, m_rotationalVelocity.X, m_rotationalVelocity.Y, m_rotationalVelocity.Z); 1618 if (m_isSelected || m_disabled)
1619 d.BodySetLinearVel(Body, _velocity.X, _velocity.Y, _velocity.Z); 1619 {
1620 } 1620 m_collisionCategories &= ~CollisionCategories.Body;
1621 1621 m_collisionFlags &= ~(CollisionCategories.Land | CollisionCategories.Wind);
1622 if (m_NoColide) 1622
1623 { 1623 d.GeomDisable(prim_geom);
1624 d.GeomSetCategoryBits(prim_geom, 0); 1624 d.BodyDisable(Body);
1625 d.GeomSetCollideBits(prim_geom, (int)CollisionCategories.Land); 1625 }
1626 } 1626 else
1627 else 1627 {
1628 { 1628 if (m_isphantom && !m_isVolumeDetect)
1629 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories); 1629 {
1630 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); 1630 m_collisionCategories = 0;
1631 } 1631 m_collisionFlags = CollisionCategories.Land;
1632 1632 }
1633 m_collisionscore = 0; 1633 else
1634 1634 {
1635 m_softcolide = true; 1635 m_collisionCategories |= CollisionCategories.Body;
1636 _parent_scene.addActivePrim(this); 1636 m_collisionFlags |= (CollisionCategories.Land | CollisionCategories.Wind);
1637 _parent_scene.addActiveGroups(this); 1637 }
1638 } 1638
1639 1639 d.BodySetAngularVel(Body, m_rotationalVelocity.X, m_rotationalVelocity.Y, m_rotationalVelocity.Z);
1640 private void DestroyBody() 1640 d.BodySetLinearVel(Body, _velocity.X, _velocity.Y, _velocity.Z);
1641 { 1641 }
1642 if (Body != IntPtr.Zero) 1642
1643 { 1643 if (m_NoColide)
1644 _parent_scene.remActivePrim(this); 1644 {
1645 m_collisionCategories &= ~CollisionCategories.Body; 1645 d.GeomSetCategoryBits(prim_geom, 0);
1646 m_collisionFlags &= ~(CollisionCategories.Wind | CollisionCategories.Land); 1646 d.GeomSetCollideBits(prim_geom, (int)CollisionCategories.Land);
1647 if (prim_geom != IntPtr.Zero) 1647 }
1648 { 1648 else
1649 if (m_NoColide) 1649 {
1650 { 1650 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
1651 d.GeomSetCategoryBits(prim_geom, 0); 1651 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
1652 d.GeomSetCollideBits(prim_geom, 0); 1652 }
1653 } 1653
1654 else 1654 m_collisionscore = 0;
1655 { 1655
1656 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories); 1656 m_softcolide = true;
1657 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); 1657 _parent_scene.addActivePrim(this);
1658 } 1658 _parent_scene.addActiveGroups(this);
1659 UpdateDataFromGeom(); 1659 }
1660 d.GeomSetBody(prim_geom, IntPtr.Zero); 1660
1661 SetInStaticSpace(this); 1661 private void DestroyBody()
1662 } 1662 {
1663 1663 if (Body != IntPtr.Zero)
1664 if (!childPrim) 1664 {
1665 { 1665 _parent_scene.remActivePrim(this);
1666 lock (childrenPrim) 1666 m_collisionCategories &= ~CollisionCategories.Body;
1667 { 1667 m_collisionFlags &= ~(CollisionCategories.Wind | CollisionCategories.Land);
1668 foreach (OdePrim prm in childrenPrim) 1668 if (prim_geom != IntPtr.Zero)
1669 { 1669 {
1670 _parent_scene.remActivePrim(prm); 1670 if (m_NoColide)
1671 prm.m_collisionCategories = m_collisionCategories; 1671 {
1672 prm.m_collisionFlags = m_collisionFlags; 1672 d.GeomSetCategoryBits(prim_geom, 0);
1673 if (prm.prim_geom != IntPtr.Zero) 1673 d.GeomSetCollideBits(prim_geom, 0);
1674 { 1674 }
1675 if (prm.m_NoColide) 1675 else
1676 { 1676 {
1677 d.GeomSetCategoryBits(prm.prim_geom, 0); 1677 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
1678 d.GeomSetCollideBits(prm.prim_geom, 0); 1678 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
1679 } 1679 }
1680 else 1680 UpdateDataFromGeom();
1681 { 1681 d.GeomSetBody(prim_geom, IntPtr.Zero);
1682 d.GeomSetCategoryBits(prm.prim_geom, (int)m_collisionCategories); 1682 SetInStaticSpace(this);
1683 d.GeomSetCollideBits(prm.prim_geom, (int)m_collisionFlags); 1683 }
1684 } 1684
1685 prm.UpdateDataFromGeom(); 1685 if (!childPrim)
1686 SetInStaticSpace(prm); 1686 {
1687 } 1687 lock (childrenPrim)
1688 prm.Body = IntPtr.Zero; 1688 {
1689 prm._mass = prm.primMass; 1689 foreach (OdePrim prm in childrenPrim)
1690 prm.m_collisionscore = 0; 1690 {
1691 } 1691 _parent_scene.remActivePrim(prm);
1692 } 1692 prm.m_collisionCategories = m_collisionCategories;
1693 if (Amotor != IntPtr.Zero) 1693 prm.m_collisionFlags = m_collisionFlags;
1694 { 1694 if (prm.prim_geom != IntPtr.Zero)
1695 d.JointDestroy(Amotor); 1695 {
1696 Amotor = IntPtr.Zero; 1696 if (prm.m_NoColide)
1697 } 1697 {
1698 _parent_scene.remActiveGroup(this); 1698 d.GeomSetCategoryBits(prm.prim_geom, 0);
1699 d.BodyDestroy(Body); 1699 d.GeomSetCollideBits(prm.prim_geom, 0);
1700 } 1700 }
1701 Body = IntPtr.Zero; 1701 else
1702 } 1702 {
1703 _mass = primMass; 1703 d.GeomSetCategoryBits(prm.prim_geom, (int)m_collisionCategories);
1704 m_collisionscore = 0; 1704 d.GeomSetCollideBits(prm.prim_geom, (int)m_collisionFlags);
1705 } 1705 }
1706 1706 prm.UpdateDataFromGeom();
1707 #region Mass Calculation 1707 SetInStaticSpace(prm);
1708 1708 }
1709 private float CalculatePrimVolume() 1709 prm.Body = IntPtr.Zero;
1710 { 1710 prm._mass = prm.primMass;
1711 float volume = _size.X * _size.Y * _size.Z; // default 1711 prm.m_collisionscore = 0;
1712 float tmp; 1712 }
1713 1713 }
1714 float hollowAmount = (float)_pbs.ProfileHollow * 2.0e-5f; 1714 if (Amotor != IntPtr.Zero)
1715 float hollowVolume = hollowAmount * hollowAmount; 1715 {
1716 1716 d.JointDestroy(Amotor);
1717 switch (_pbs.ProfileShape) 1717 Amotor = IntPtr.Zero;
1718 { 1718 }
1719 case ProfileShape.Square: 1719 _parent_scene.remActiveGroup(this);
1720 // default box 1720 d.BodyDestroy(Body);
1721 1721 }
1722 if (_pbs.PathCurve == (byte)Extrusion.Straight) 1722 Body = IntPtr.Zero;
1723 { 1723 }
1724 if (hollowAmount > 0.0) 1724 _mass = primMass;
1725 { 1725 m_collisionscore = 0;
1726 switch (_pbs.HollowShape) 1726 }
1727 { 1727
1728 case HollowShape.Square: 1728 #region Mass Calculation
1729 case HollowShape.Same: 1729
1730 break; 1730 private float CalculatePrimVolume()
1731 1731 {
1732 case HollowShape.Circle: 1732 float volume = _size.X * _size.Y * _size.Z; // default
1733 1733 float tmp;
1734 hollowVolume *= 0.78539816339f; 1734
1735 break; 1735 float hollowAmount = (float)_pbs.ProfileHollow * 2.0e-5f;
1736 1736 float hollowVolume = hollowAmount * hollowAmount;
1737 case HollowShape.Triangle: 1737
1738 1738 switch (_pbs.ProfileShape)
1739 hollowVolume *= (0.5f * .5f); 1739 {
1740 break; 1740 case ProfileShape.Square:
1741 1741 // default box
1742 default: 1742
1743 hollowVolume = 0; 1743 if (_pbs.PathCurve == (byte)Extrusion.Straight)
1744 break; 1744 {
1745 } 1745 if (hollowAmount > 0.0)
1746 volume *= (1.0f - hollowVolume); 1746 {
1747 } 1747 switch (_pbs.HollowShape)
1748 } 1748 {
1749 1749 case HollowShape.Square:
1750 else if (_pbs.PathCurve == (byte)Extrusion.Curve1) 1750 case HollowShape.Same:
1751 { 1751 break;
1752 //a tube 1752
1753 1753 case HollowShape.Circle:
1754 volume *= 0.78539816339e-2f * (float)(200 - _pbs.PathScaleX); 1754
1755 tmp = 1.0f - 2.0e-2f * (float)(200 - _pbs.PathScaleY); 1755 hollowVolume *= 0.78539816339f;
1756 volume -= volume * tmp * tmp; 1756 break;
1757 1757
1758 if (hollowAmount > 0.0) 1758 case HollowShape.Triangle:
1759 { 1759
1760 hollowVolume *= hollowAmount; 1760 hollowVolume *= (0.5f * .5f);
1761 1761 break;
1762 switch (_pbs.HollowShape) 1762
1763 { 1763 default:
1764 case HollowShape.Square: 1764 hollowVolume = 0;
1765 case HollowShape.Same: 1765 break;
1766 break; 1766 }
1767 1767 volume *= (1.0f - hollowVolume);
1768 case HollowShape.Circle: 1768 }
1769 hollowVolume *= 0.78539816339f; 1769 }
1770 break; 1770
1771 1771 else if (_pbs.PathCurve == (byte)Extrusion.Curve1)
1772 case HollowShape.Triangle: 1772 {
1773 hollowVolume *= 0.5f * 0.5f; 1773 //a tube
1774 break; 1774
1775 default: 1775 volume *= 0.78539816339e-2f * (float)(200 - _pbs.PathScaleX);
1776 hollowVolume = 0; 1776 tmp = 1.0f - 2.0e-2f * (float)(200 - _pbs.PathScaleY);
1777 break; 1777 volume -= volume * tmp * tmp;
1778 } 1778
1779 volume *= (1.0f - hollowVolume); 1779 if (hollowAmount > 0.0)
1780 } 1780 {
1781 } 1781 hollowVolume *= hollowAmount;
1782 1782
1783 break; 1783 switch (_pbs.HollowShape)
1784 1784 {
1785 case ProfileShape.Circle: 1785 case HollowShape.Square:
1786 1786 case HollowShape.Same:
1787 if (_pbs.PathCurve == (byte)Extrusion.Straight) 1787 break;
1788 { 1788
1789 volume *= 0.78539816339f; // elipse base 1789 case HollowShape.Circle:
1790 1790 hollowVolume *= 0.78539816339f;
1791 if (hollowAmount > 0.0) 1791 break;
1792 { 1792
1793 switch (_pbs.HollowShape) 1793 case HollowShape.Triangle:
1794 { 1794 hollowVolume *= 0.5f * 0.5f;
1795 case HollowShape.Same: 1795 break;
1796 case HollowShape.Circle: 1796 default:
1797 break; 1797 hollowVolume = 0;
1798 1798 break;
1799 case HollowShape.Square: 1799 }
1800 hollowVolume *= 0.5f * 2.5984480504799f; 1800 volume *= (1.0f - hollowVolume);
1801 break; 1801 }
1802 1802 }
1803 case HollowShape.Triangle: 1803
1804 hollowVolume *= .5f * 1.27323954473516f; 1804 break;
1805 break; 1805
1806 1806 case ProfileShape.Circle:
1807 default: 1807
1808 hollowVolume = 0; 1808 if (_pbs.PathCurve == (byte)Extrusion.Straight)
1809 break; 1809 {
1810 } 1810 volume *= 0.78539816339f; // elipse base
1811 volume *= (1.0f - hollowVolume); 1811
1812 } 1812 if (hollowAmount > 0.0)
1813 } 1813 {
1814 1814 switch (_pbs.HollowShape)
1815 else if (_pbs.PathCurve == (byte)Extrusion.Curve1) 1815 {
1816 { 1816 case HollowShape.Same:
1817 volume *= 0.61685027506808491367715568749226e-2f * (float)(200 - _pbs.PathScaleX); 1817 case HollowShape.Circle:
1818 tmp = 1.0f - .02f * (float)(200 - _pbs.PathScaleY); 1818 break;
1819 volume *= (1.0f - tmp * tmp); 1819
1820 1820 case HollowShape.Square:
1821 if (hollowAmount > 0.0) 1821 hollowVolume *= 0.5f * 2.5984480504799f;
1822 { 1822 break;
1823 1823
1824 // calculate the hollow volume by it's shape compared to the prim shape 1824 case HollowShape.Triangle:
1825 hollowVolume *= hollowAmount; 1825 hollowVolume *= .5f * 1.27323954473516f;
1826 1826 break;
1827 switch (_pbs.HollowShape) 1827
1828 { 1828 default:
1829 case HollowShape.Same: 1829 hollowVolume = 0;
1830 case HollowShape.Circle: 1830 break;
1831 break; 1831 }
1832 1832 volume *= (1.0f - hollowVolume);
1833 case HollowShape.Square: 1833 }
1834 hollowVolume *= 0.5f * 2.5984480504799f; 1834 }
1835 break; 1835
1836 1836 else if (_pbs.PathCurve == (byte)Extrusion.Curve1)
1837 case HollowShape.Triangle: 1837 {
1838 hollowVolume *= .5f * 1.27323954473516f; 1838 volume *= 0.61685027506808491367715568749226e-2f * (float)(200 - _pbs.PathScaleX);
1839 break; 1839 tmp = 1.0f - .02f * (float)(200 - _pbs.PathScaleY);
1840 1840 volume *= (1.0f - tmp * tmp);
1841 default: 1841
1842 hollowVolume = 0; 1842 if (hollowAmount > 0.0)
1843 break; 1843 {
1844 } 1844
1845 volume *= (1.0f - hollowVolume); 1845 // calculate the hollow volume by it's shape compared to the prim shape
1846 } 1846 hollowVolume *= hollowAmount;
1847 } 1847
1848 break; 1848 switch (_pbs.HollowShape)
1849 1849 {
1850 case ProfileShape.HalfCircle: 1850 case HollowShape.Same:
1851 if (_pbs.PathCurve == (byte)Extrusion.Curve1) 1851 case HollowShape.Circle:
1852 { 1852 break;
1853 volume *= 0.52359877559829887307710723054658f; 1853
1854 } 1854 case HollowShape.Square:
1855 break; 1855 hollowVolume *= 0.5f * 2.5984480504799f;
1856 1856 break;
1857 case ProfileShape.EquilateralTriangle: 1857
1858 1858 case HollowShape.Triangle:
1859 if (_pbs.PathCurve == (byte)Extrusion.Straight) 1859 hollowVolume *= .5f * 1.27323954473516f;
1860 { 1860 break;
1861 volume *= 0.32475953f; 1861
1862 1862 default:
1863 if (hollowAmount > 0.0) 1863 hollowVolume = 0;
1864 { 1864 break;
1865 1865 }
1866 // calculate the hollow volume by it's shape compared to the prim shape 1866 volume *= (1.0f - hollowVolume);
1867 switch (_pbs.HollowShape) 1867 }
1868 { 1868 }
1869 case HollowShape.Same: 1869 break;
1870 case HollowShape.Triangle: 1870
1871 hollowVolume *= .25f; 1871 case ProfileShape.HalfCircle:
1872 break; 1872 if (_pbs.PathCurve == (byte)Extrusion.Curve1)
1873 1873 {
1874 case HollowShape.Square: 1874 volume *= 0.52359877559829887307710723054658f;
1875 hollowVolume *= 0.499849f * 3.07920140172638f; 1875 }
1876 break; 1876 break;
1877 1877
1878 case HollowShape.Circle: 1878 case ProfileShape.EquilateralTriangle:
1879 // Hollow shape is a perfect cyllinder in respect to the cube's scale 1879
1880 // Cyllinder hollow volume calculation 1880 if (_pbs.PathCurve == (byte)Extrusion.Straight)
1881 1881 {
1882 hollowVolume *= 0.1963495f * 3.07920140172638f; 1882 volume *= 0.32475953f;
1883 break; 1883
1884 1884 if (hollowAmount > 0.0)
1885 default: 1885 {
1886 hollowVolume = 0; 1886
1887 break; 1887 // calculate the hollow volume by it's shape compared to the prim shape
1888 } 1888 switch (_pbs.HollowShape)
1889 volume *= (1.0f - hollowVolume); 1889 {
1890 } 1890 case HollowShape.Same:
1891 } 1891 case HollowShape.Triangle:
1892 else if (_pbs.PathCurve == (byte)Extrusion.Curve1) 1892 hollowVolume *= .25f;
1893 { 1893 break;
1894 volume *= 0.32475953f; 1894
1895 volume *= 0.01f * (float)(200 - _pbs.PathScaleX); 1895 case HollowShape.Square:
1896 tmp = 1.0f - .02f * (float)(200 - _pbs.PathScaleY); 1896 hollowVolume *= 0.499849f * 3.07920140172638f;
1897 volume *= (1.0f - tmp * tmp); 1897 break;
1898 1898
1899 if (hollowAmount > 0.0) 1899 case HollowShape.Circle:
1900 { 1900 // Hollow shape is a perfect cyllinder in respect to the cube's scale
1901 1901 // Cyllinder hollow volume calculation
1902 hollowVolume *= hollowAmount; 1902
1903 1903 hollowVolume *= 0.1963495f * 3.07920140172638f;
1904 switch (_pbs.HollowShape) 1904 break;
1905 { 1905
1906 case HollowShape.Same: 1906 default:
1907 case HollowShape.Triangle: 1907 hollowVolume = 0;
1908 hollowVolume *= .25f; 1908 break;
1909 break; 1909 }
1910 1910 volume *= (1.0f - hollowVolume);
1911 case HollowShape.Square: 1911 }
1912 hollowVolume *= 0.499849f * 3.07920140172638f; 1912 }
1913 break; 1913 else if (_pbs.PathCurve == (byte)Extrusion.Curve1)
1914 1914 {
1915 case HollowShape.Circle: 1915 volume *= 0.32475953f;
1916 1916 volume *= 0.01f * (float)(200 - _pbs.PathScaleX);
1917 hollowVolume *= 0.1963495f * 3.07920140172638f; 1917 tmp = 1.0f - .02f * (float)(200 - _pbs.PathScaleY);
1918 break; 1918 volume *= (1.0f - tmp * tmp);
1919 1919
1920 default: 1920 if (hollowAmount > 0.0)
1921 hollowVolume = 0; 1921 {
1922 break; 1922
1923 } 1923 hollowVolume *= hollowAmount;
1924 volume *= (1.0f - hollowVolume); 1924
1925 } 1925 switch (_pbs.HollowShape)
1926 } 1926 {
1927 break; 1927 case HollowShape.Same:
1928 1928 case HollowShape.Triangle:
1929 default: 1929 hollowVolume *= .25f;
1930 break; 1930 break;
1931 } 1931
1932 1932 case HollowShape.Square:
1933 float taperX1; 1933 hollowVolume *= 0.499849f * 3.07920140172638f;
1934 float taperY1; 1934 break;
1935 float taperX; 1935
1936 float taperY; 1936 case HollowShape.Circle:
1937 float pathBegin; 1937
1938 float pathEnd; 1938 hollowVolume *= 0.1963495f * 3.07920140172638f;
1939 float profileBegin; 1939 break;
1940 float profileEnd; 1940
1941 1941 default:
1942 if (_pbs.PathCurve == (byte)Extrusion.Straight || _pbs.PathCurve == (byte)Extrusion.Flexible) 1942 hollowVolume = 0;
1943 { 1943 break;
1944 taperX1 = _pbs.PathScaleX * 0.01f; 1944 }
1945 if (taperX1 > 1.0f) 1945 volume *= (1.0f - hollowVolume);
1946 taperX1 = 2.0f - taperX1; 1946 }
1947 taperX = 1.0f - taperX1; 1947 }
1948 1948 break;
1949 taperY1 = _pbs.PathScaleY * 0.01f; 1949
1950 if (taperY1 > 1.0f) 1950 default:
1951 taperY1 = 2.0f - taperY1; 1951 break;
1952 taperY = 1.0f - taperY1; 1952 }
1953 } 1953
1954 else 1954 float taperX1;
1955 { 1955 float taperY1;
1956 taperX = _pbs.PathTaperX * 0.01f; 1956 float taperX;
1957 if (taperX < 0.0f) 1957 float taperY;
1958 taperX = -taperX; 1958 float pathBegin;
1959 taperX1 = 1.0f - taperX; 1959 float pathEnd;
1960 1960 float profileBegin;
1961 taperY = _pbs.PathTaperY * 0.01f; 1961 float profileEnd;
1962 if (taperY < 0.0f) 1962
1963 taperY = -taperY; 1963 if (_pbs.PathCurve == (byte)Extrusion.Straight || _pbs.PathCurve == (byte)Extrusion.Flexible)
1964 taperY1 = 1.0f - taperY; 1964 {
1965 } 1965 taperX1 = _pbs.PathScaleX * 0.01f;
1966 1966 if (taperX1 > 1.0f)
1967 volume *= (taperX1 * taperY1 + 0.5f * (taperX1 * taperY + taperX * taperY1) + 0.3333333333f * taperX * taperY); 1967 taperX1 = 2.0f - taperX1;
1968 1968 taperX = 1.0f - taperX1;
1969 pathBegin = (float)_pbs.PathBegin * 2.0e-5f; 1969
1970 pathEnd = 1.0f - (float)_pbs.PathEnd * 2.0e-5f; 1970 taperY1 = _pbs.PathScaleY * 0.01f;
1971 volume *= (pathEnd - pathBegin); 1971 if (taperY1 > 1.0f)
1972 1972 taperY1 = 2.0f - taperY1;
1973 // this is crude aproximation 1973 taperY = 1.0f - taperY1;
1974 profileBegin = (float)_pbs.ProfileBegin * 2.0e-5f; 1974 }
1975 profileEnd = 1.0f - (float)_pbs.ProfileEnd * 2.0e-5f; 1975 else
1976 volume *= (profileEnd - profileBegin); 1976 {
1977 1977 taperX = _pbs.PathTaperX * 0.01f;
1978 return volume; 1978 if (taperX < 0.0f)
1979 } 1979 taperX = -taperX;
1980 1980 taperX1 = 1.0f - taperX;
1981 1981
1982 private void CalcPrimBodyData() 1982 taperY = _pbs.PathTaperY * 0.01f;
1983 { 1983 if (taperY < 0.0f)
1984 float volume; 1984 taperY = -taperY;
1985 1985 taperY1 = 1.0f - taperY;
1986 if (prim_geom == IntPtr.Zero) 1986 }
1987 { 1987
1988 // Ubit let's have a initial basic OOB 1988 volume *= (taperX1 * taperY1 + 0.5f * (taperX1 * taperY + taperX * taperY1) + 0.3333333333f * taperX * taperY);
1989 primOOBsize.X = _size.X; 1989
1990 primOOBsize.Y = _size.Y; 1990 pathBegin = (float)_pbs.PathBegin * 2.0e-5f;
1991 primOOBsize.Z = _size.Z; 1991 pathEnd = 1.0f - (float)_pbs.PathEnd * 2.0e-5f;
1992 primOOBoffset = Vector3.Zero; 1992 volume *= (pathEnd - pathBegin);
1993 } 1993
1994 else 1994 // this is crude aproximation
1995 { 1995 profileBegin = (float)_pbs.ProfileBegin * 2.0e-5f;
1996 d.AABB AABB; 1996 profileEnd = 1.0f - (float)_pbs.ProfileEnd * 2.0e-5f;
1997 d.GeomGetAABB(prim_geom, out AABB); // get the AABB from engine geom 1997 volume *= (profileEnd - profileBegin);
1998 1998
1999 primOOBsize.X = (AABB.MaxX - AABB.MinX); 1999 return volume;
2000 primOOBsize.Y = (AABB.MaxY - AABB.MinY); 2000 }
2001 primOOBsize.Z = (AABB.MaxZ - AABB.MinZ); 2001
2002 if (!hasOOBoffsetFromMesh) 2002
2003 { 2003 private void CalcPrimBodyData()
2004 primOOBoffset.X = (AABB.MaxX + AABB.MinX) * 0.5f; 2004 {
2005 primOOBoffset.Y = (AABB.MaxY + AABB.MinY) * 0.5f; 2005 float volume;
2006 primOOBoffset.Z = (AABB.MaxZ + AABB.MinZ) * 0.5f; 2006
2007 } 2007 if (prim_geom == IntPtr.Zero)
2008 } 2008 {
2009 2009 // Ubit let's have a initial basic OOB
2010 // also its own inertia and mass 2010 primOOBsize.X = _size.X;
2011 // keep using basic shape mass for now 2011 primOOBsize.Y = _size.Y;
2012 volume = CalculatePrimVolume(); 2012 primOOBsize.Z = _size.Z;
2013 2013 primOOBoffset = Vector3.Zero;
2014 primMass = m_density * volume; 2014 }
2015 2015 else
2016 if (primMass <= 0) 2016 {
2017 primMass = 0.0001f;//ckrinke: Mass must be greater then zero. 2017 d.AABB AABB;
2018 if (primMass > _parent_scene.maximumMassObject) 2018 d.GeomGetAABB(prim_geom, out AABB); // get the AABB from engine geom
2019 primMass = _parent_scene.maximumMassObject; 2019
2020 2020 primOOBsize.X = (AABB.MaxX - AABB.MinX);
2021 _mass = primMass; // just in case 2021 primOOBsize.Y = (AABB.MaxY - AABB.MinY);
2022 2022 primOOBsize.Z = (AABB.MaxZ - AABB.MinZ);
2023 d.MassSetBoxTotal(out primdMass, primMass, primOOBsize.X, primOOBsize.Y, primOOBsize.Z); 2023 if (!hasOOBoffsetFromMesh)
2024 2024 {
2025 d.MassTranslate(ref primdMass, 2025 primOOBoffset.X = (AABB.MaxX + AABB.MinX) * 0.5f;
2026 primOOBoffset.X, 2026 primOOBoffset.Y = (AABB.MaxY + AABB.MinY) * 0.5f;
2027 primOOBoffset.Y, 2027 primOOBoffset.Z = (AABB.MaxZ + AABB.MinZ) * 0.5f;
2028 primOOBoffset.Z); 2028 }
2029 2029 }
2030 primOOBsize *= 0.5f; // let obb size be a corner coords 2030
2031 primOOBradiusSQ = primOOBsize.LengthSquared(); 2031 // also its own inertia and mass
2032 } 2032 // keep using basic shape mass for now
2033 2033 volume = CalculatePrimVolume();
2034 2034
2035 #endregion 2035 primMass = m_density * volume;
2036 2036
2037 2037 if (primMass <= 0)
2038 /// <summary> 2038 primMass = 0.0001f;//ckrinke: Mass must be greater then zero.
2039 /// Add a child prim to this parent prim. 2039 if (primMass > _parent_scene.maximumMassObject)
2040 /// </summary> 2040 primMass = _parent_scene.maximumMassObject;
2041 /// <param name="prim">Child prim</param> 2041
2042 // I'm the parent 2042 _mass = primMass; // just in case
2043 // prim is the child 2043
2044 public void ParentPrim(OdePrim prim) 2044 d.MassSetBoxTotal(out primdMass, primMass, primOOBsize.X, primOOBsize.Y, primOOBsize.Z);
2045 { 2045
2046 //Console.WriteLine("ParentPrim " + m_primName); 2046 d.MassTranslate(ref primdMass,
2047 if (this.m_localID != prim.m_localID) 2047 primOOBoffset.X,
2048 { 2048 primOOBoffset.Y,
2049 DestroyBody(); // for now we need to rebuil entire object on link change 2049 primOOBoffset.Z);
2050 2050
2051 lock (childrenPrim) 2051 primOOBsize *= 0.5f; // let obb size be a corner coords
2052 { 2052 primOOBradiusSQ = primOOBsize.LengthSquared();
2053 // adopt the prim 2053 }
2054 if (!childrenPrim.Contains(prim)) 2054
2055 childrenPrim.Add(prim); 2055
2056 2056 #endregion
2057 // see if this prim has kids and adopt them also 2057
2058 // should not happen for now 2058
2059 foreach (OdePrim prm in prim.childrenPrim) 2059 /// <summary>
2060 { 2060 /// Add a child prim to this parent prim.
2061 if (!childrenPrim.Contains(prm)) 2061 /// </summary>
2062 { 2062 /// <param name="prim">Child prim</param>
2063 if (prm.Body != IntPtr.Zero) 2063 // I'm the parent
2064 { 2064 // prim is the child
2065 if (prm.prim_geom != IntPtr.Zero) 2065 public void ParentPrim(OdePrim prim)
2066 d.GeomSetBody(prm.prim_geom, IntPtr.Zero); 2066 {
2067 if (prm.Body != prim.Body) 2067 //Console.WriteLine("ParentPrim " + m_primName);
2068 prm.DestroyBody(); // don't loose bodies around 2068 if (this.m_localID != prim.m_localID)
2069 prm.Body = IntPtr.Zero; 2069 {
2070 } 2070 DestroyBody(); // for now we need to rebuil entire object on link change
2071 2071
2072 childrenPrim.Add(prm); 2072 lock (childrenPrim)
2073 prm._parent = this; 2073 {
2074 } 2074 // adopt the prim
2075 } 2075 if (!childrenPrim.Contains(prim))
2076 } 2076 childrenPrim.Add(prim);
2077 //Remove old children from the prim 2077
2078 prim.childrenPrim.Clear(); 2078 // see if this prim has kids and adopt them also
2079 2079 // should not happen for now
2080 if (prim.Body != IntPtr.Zero) 2080 foreach (OdePrim prm in prim.childrenPrim)
2081 { 2081 {
2082 if (prim.prim_geom != IntPtr.Zero) 2082 if (!childrenPrim.Contains(prm))
2083 d.GeomSetBody(prim.prim_geom, IntPtr.Zero); 2083 {
2084 prim.DestroyBody(); // don't loose bodies around 2084 if (prm.Body != IntPtr.Zero)
2085 prim.Body = IntPtr.Zero; 2085 {
2086 } 2086 if (prm.prim_geom != IntPtr.Zero)
2087 2087 d.GeomSetBody(prm.prim_geom, IntPtr.Zero);
2088 prim.childPrim = true; 2088 if (prm.Body != prim.Body)
2089 prim._parent = this; 2089 prm.DestroyBody(); // don't loose bodies around
2090 2090 prm.Body = IntPtr.Zero;
2091 MakeBody(); // full nasty reconstruction 2091 }
2092 } 2092
2093 } 2093 childrenPrim.Add(prm);
2094 2094 prm._parent = this;
2095 private void UpdateChildsfromgeom() 2095 }
2096 { 2096 }
2097 if (childrenPrim.Count > 0) 2097 }
2098 { 2098 //Remove old children from the prim
2099 foreach (OdePrim prm in childrenPrim) 2099 prim.childrenPrim.Clear();
2100 prm.UpdateDataFromGeom(); 2100
2101 } 2101 if (prim.Body != IntPtr.Zero)
2102 } 2102 {
2103 2103 if (prim.prim_geom != IntPtr.Zero)
2104 private void UpdateDataFromGeom() 2104 d.GeomSetBody(prim.prim_geom, IntPtr.Zero);
2105 { 2105 prim.DestroyBody(); // don't loose bodies around
2106 if (prim_geom != IntPtr.Zero) 2106 prim.Body = IntPtr.Zero;
2107 { 2107 }
2108 d.Vector3 lpos; 2108
2109 d.GeomCopyPosition(prim_geom, out lpos); 2109 prim.childPrim = true;
2110 _position.X = lpos.X; 2110 prim._parent = this;
2111 _position.Y = lpos.Y; 2111
2112 _position.Z = lpos.Z; 2112 MakeBody(); // full nasty reconstruction
2113 d.Quaternion qtmp = new d.Quaternion { }; 2113 }
2114 d.GeomCopyQuaternion(prim_geom, out qtmp); 2114 }
2115 _orientation.W = qtmp.W; 2115
2116 _orientation.X = qtmp.X; 2116 private void UpdateChildsfromgeom()
2117 _orientation.Y = qtmp.Y; 2117 {
2118 _orientation.Z = qtmp.Z; 2118 if (childrenPrim.Count > 0)
2119 } 2119 {
2120 } 2120 foreach (OdePrim prm in childrenPrim)
2121 2121 prm.UpdateDataFromGeom();
2122 private void ChildDelink(OdePrim odePrim, bool remakebodies) 2122 }
2123 { 2123 }
2124 // Okay, we have a delinked child.. destroy all body and remake 2124
2125 if (odePrim != this && !childrenPrim.Contains(odePrim)) 2125 private void UpdateDataFromGeom()
2126 return; 2126 {
2127 2127 if (prim_geom != IntPtr.Zero)
2128 DestroyBody(); 2128 {
2129 2129 d.Vector3 lpos;
2130 if (odePrim == this) // delinking the root prim 2130 d.GeomCopyPosition(prim_geom, out lpos);
2131 { 2131 _position.X = lpos.X;
2132 OdePrim newroot = null; 2132 _position.Y = lpos.Y;
2133 lock (childrenPrim) 2133 _position.Z = lpos.Z;
2134 { 2134 d.Quaternion qtmp = new d.Quaternion { };
2135 if (childrenPrim.Count > 0) 2135 d.GeomCopyQuaternion(prim_geom, out qtmp);
2136 { 2136 _orientation.W = qtmp.W;
2137 newroot = childrenPrim[0]; 2137 _orientation.X = qtmp.X;
2138 childrenPrim.RemoveAt(0); 2138 _orientation.Y = qtmp.Y;
2139 foreach (OdePrim prm in childrenPrim) 2139 _orientation.Z = qtmp.Z;
2140 { 2140 }
2141 newroot.childrenPrim.Add(prm); 2141 }
2142 } 2142
2143 childrenPrim.Clear(); 2143 private void ChildDelink(OdePrim odePrim, bool remakebodies)
2144 } 2144 {
2145 if (newroot != null) 2145 // Okay, we have a delinked child.. destroy all body and remake
2146 { 2146 if (odePrim != this && !childrenPrim.Contains(odePrim))
2147 newroot.childPrim = false; 2147 return;
2148 newroot._parent = null; 2148
2149 if (remakebodies) 2149 DestroyBody();
2150 newroot.MakeBody(); 2150
2151 } 2151 if (odePrim == this) // delinking the root prim
2152 } 2152 {
2153 } 2153 OdePrim newroot = null;
2154 2154 lock (childrenPrim)
2155 else 2155 {
2156 { 2156 if (childrenPrim.Count > 0)
2157 lock (childrenPrim) 2157 {
2158 { 2158 newroot = childrenPrim[0];
2159 childrenPrim.Remove(odePrim); 2159 childrenPrim.RemoveAt(0);
2160 odePrim.childPrim = false; 2160 foreach (OdePrim prm in childrenPrim)
2161 odePrim._parent = null; 2161 {
2162 // odePrim.UpdateDataFromGeom(); 2162 newroot.childrenPrim.Add(prm);
2163 if (remakebodies) 2163 }
2164 odePrim.MakeBody(); 2164 childrenPrim.Clear();
2165 } 2165 }
2166 } 2166 if (newroot != null)
2167 if (remakebodies) 2167 {
2168 MakeBody(); 2168 newroot.childPrim = false;
2169 } 2169 newroot._parent = null;
2170 2170 if (remakebodies)
2171 protected void ChildRemove(OdePrim odePrim, bool reMakeBody) 2171 newroot.MakeBody();
2172 { 2172 }
2173 // Okay, we have a delinked child.. destroy all body and remake 2173 }
2174 if (odePrim != this && !childrenPrim.Contains(odePrim)) 2174 }
2175 return; 2175
2176 2176 else
2177 DestroyBody(); 2177 {
2178 2178 lock (childrenPrim)
2179 if (odePrim == this) 2179 {
2180 { 2180 childrenPrim.Remove(odePrim);
2181 OdePrim newroot = null; 2181 odePrim.childPrim = false;
2182 lock (childrenPrim) 2182 odePrim._parent = null;
2183 { 2183 // odePrim.UpdateDataFromGeom();
2184 if (childrenPrim.Count > 0) 2184 if (remakebodies)
2185 { 2185 odePrim.MakeBody();
2186 newroot = childrenPrim[0]; 2186 }
2187 childrenPrim.RemoveAt(0); 2187 }
2188 foreach (OdePrim prm in childrenPrim) 2188 if (remakebodies)
2189 { 2189 MakeBody();
2190 newroot.childrenPrim.Add(prm); 2190 }
2191 } 2191
2192 childrenPrim.Clear(); 2192 protected void ChildRemove(OdePrim odePrim, bool reMakeBody)
2193 } 2193 {
2194 if (newroot != null) 2194 // Okay, we have a delinked child.. destroy all body and remake
2195 { 2195 if (odePrim != this && !childrenPrim.Contains(odePrim))
2196 newroot.childPrim = false; 2196 return;
2197 newroot._parent = null; 2197
2198 newroot.MakeBody(); 2198 DestroyBody();
2199 } 2199
2200 } 2200 if (odePrim == this)
2201 if (reMakeBody) 2201 {
2202 MakeBody(); 2202 OdePrim newroot = null;
2203 return; 2203 lock (childrenPrim)
2204 } 2204 {
2205 else 2205 if (childrenPrim.Count > 0)
2206 { 2206 {
2207 lock (childrenPrim) 2207 newroot = childrenPrim[0];
2208 { 2208 childrenPrim.RemoveAt(0);
2209 childrenPrim.Remove(odePrim); 2209 foreach (OdePrim prm in childrenPrim)
2210 odePrim.childPrim = false; 2210 {
2211 odePrim._parent = null; 2211 newroot.childrenPrim.Add(prm);
2212 if (reMakeBody) 2212 }
2213 odePrim.MakeBody(); 2213 childrenPrim.Clear();
2214 } 2214 }
2215 } 2215 if (newroot != null)
2216 MakeBody(); 2216 {
2217 } 2217 newroot.childPrim = false;
2218 2218 newroot._parent = null;
2219 #region changes 2219 newroot.MakeBody();
2220 2220 }
2221 private void changeadd() 2221 }
2222 { 2222 if (reMakeBody)
2223 CreateGeom(); 2223 MakeBody();
2224 2224 return;
2225 if (prim_geom != IntPtr.Zero) 2225 }
2226 { 2226 else
2227 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z); 2227 {
2228 d.Quaternion myrot = new d.Quaternion(); 2228 lock (childrenPrim)
2229 myrot.X = _orientation.X; 2229 {
2230 myrot.Y = _orientation.Y; 2230 childrenPrim.Remove(odePrim);
2231 myrot.Z = _orientation.Z; 2231 odePrim.childPrim = false;
2232 myrot.W = _orientation.W; 2232 odePrim._parent = null;
2233 d.GeomSetQuaternion(prim_geom, ref myrot); 2233 if (reMakeBody)
2234 2234 odePrim.MakeBody();
2235 if (!m_isphysical) 2235 }
2236 SetInStaticSpace(this); 2236 }
2237 } 2237 MakeBody();
2238 2238 }
2239 if (m_isphysical && Body == IntPtr.Zero) 2239
2240 { 2240 #region changes
2241 MakeBody(); 2241
2242 } 2242 private void changeadd()
2243 } 2243 {
2244 2244 CreateGeom();
2245 private void changeAngularLock(Vector3 newLock) 2245
2246 { 2246 if (prim_geom != IntPtr.Zero)
2247 // do we have a Physical object? 2247 {
2248 if (Body != IntPtr.Zero) 2248 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
2249 { 2249 d.Quaternion myrot = new d.Quaternion();
2250 //Check that we have a Parent 2250 myrot.X = _orientation.X;
2251 //If we have a parent then we're not authorative here 2251 myrot.Y = _orientation.Y;
2252 if (_parent == null) 2252 myrot.Z = _orientation.Z;
2253 { 2253 myrot.W = _orientation.W;
2254 if (!newLock.ApproxEquals(Vector3.One, 0f)) 2254 d.GeomSetQuaternion(prim_geom, ref myrot);
2255 { 2255
2256 createAMotor(newLock); 2256 if (!m_isphysical)
2257 } 2257 SetInStaticSpace(this);
2258 else 2258 }
2259 { 2259
2260 if (Amotor != IntPtr.Zero) 2260 if (m_isphysical && Body == IntPtr.Zero)
2261 { 2261 {
2262 d.JointDestroy(Amotor); 2262 MakeBody();
2263 Amotor = IntPtr.Zero; 2263 }
2264 } 2264 }
2265 } 2265
2266 } 2266 private void changeAngularLock(Vector3 newLock)
2267 } 2267 {
2268 // Store this for later in case we get turned into a separate body 2268 // do we have a Physical object?
2269 m_angularlock = newLock; 2269 if (Body != IntPtr.Zero)
2270 } 2270 {
2271 2271 //Check that we have a Parent
2272 private void changeLink(OdePrim NewParent) 2272 //If we have a parent then we're not authorative here
2273 { 2273 if (_parent == null)
2274 if (_parent == null && NewParent != null) 2274 {
2275 { 2275 if (!newLock.ApproxEquals(Vector3.One, 0f))
2276 NewParent.ParentPrim(this); 2276 {
2277 } 2277 createAMotor(newLock);
2278 else if (_parent != null) 2278 }
2279 { 2279 else
2280 if (_parent is OdePrim) 2280 {
2281 { 2281 if (Amotor != IntPtr.Zero)
2282 if (NewParent != _parent) 2282 {
2283 { 2283 d.JointDestroy(Amotor);
2284 (_parent as OdePrim).ChildDelink(this, false); // for now... 2284 Amotor = IntPtr.Zero;
2285 childPrim = false; 2285 }
2286 2286 }
2287 if (NewParent != null) 2287 }
2288 { 2288 }
2289 NewParent.ParentPrim(this); 2289 // Store this for later in case we get turned into a separate body
2290 } 2290 m_angularlock = newLock;
2291 } 2291 }
2292 } 2292
2293 } 2293 private void changeLink(OdePrim NewParent)
2294 _parent = NewParent; 2294 {
2295 } 2295 if (_parent == null && NewParent != null)
2296 2296 {
2297 2297 NewParent.ParentPrim(this);
2298 private void Stop() 2298 }
2299 { 2299 else if (_parent != null)
2300 if (!childPrim) 2300 {
2301 { 2301 if (_parent is OdePrim)
2302 m_force = Vector3.Zero; 2302 {
2303 m_forceacc = Vector3.Zero; 2303 if (NewParent != _parent)
2304 m_angularForceacc = Vector3.Zero; 2304 {
2305 _torque = Vector3.Zero; 2305 (_parent as OdePrim).ChildDelink(this, false); // for now...
2306 _velocity = Vector3.Zero; 2306 childPrim = false;
2307 _acceleration = Vector3.Zero; 2307
2308 m_rotationalVelocity = Vector3.Zero; 2308 if (NewParent != null)
2309 _target_velocity = Vector3.Zero; 2309 {
2310 if (m_vehicle != null && m_vehicle.Type != Vehicle.TYPE_NONE) 2310 NewParent.ParentPrim(this);
2311 m_vehicle.Stop(); 2311 }
2312 } 2312 }
2313 2313 }
2314 if (Body != IntPtr.Zero) 2314 }
2315 { 2315 _parent = NewParent;
2316 d.BodySetForce(Body, 0f, 0f, 0f); 2316 }
2317 d.BodySetTorque(Body, 0f, 0f, 0f); 2317
2318 d.BodySetLinearVel(Body, 0f, 0f, 0f); 2318
2319 d.BodySetAngularVel(Body, 0f, 0f, 0f); 2319 private void Stop()
2320 } 2320 {
2321 } 2321 if (!childPrim)
2322 2322 {
2323 2323 m_force = Vector3.Zero;
2324 private void changePhantomStatus(bool newval) 2324 m_forceacc = Vector3.Zero;
2325 { 2325 m_angularForceacc = Vector3.Zero;
2326 m_isphantom = newval; 2326 _torque = Vector3.Zero;
2327 2327 _velocity = Vector3.Zero;
2328 if (m_isSelected) 2328 _acceleration = Vector3.Zero;
2329 { 2329 m_rotationalVelocity = Vector3.Zero;
2330 m_collisionCategories = CollisionCategories.Selected; 2330 _target_velocity = Vector3.Zero;
2331 m_collisionFlags = (CollisionCategories.Sensor | CollisionCategories.Space); 2331 if (m_vehicle != null && m_vehicle.Type != Vehicle.TYPE_NONE)
2332 } 2332 m_vehicle.Stop();
2333 else 2333 }
2334 { 2334
2335 if (m_isphantom && !m_isVolumeDetect) 2335 if (Body != IntPtr.Zero)
2336 { 2336 {
2337 m_collisionCategories = 0; 2337 d.BodySetForce(Body, 0f, 0f, 0f);
2338 if (m_isphysical) 2338 d.BodySetTorque(Body, 0f, 0f, 0f);
2339 m_collisionFlags = CollisionCategories.Land; 2339 d.BodySetLinearVel(Body, 0f, 0f, 0f);
2340 else 2340 d.BodySetAngularVel(Body, 0f, 0f, 0f);
2341 m_collisionFlags = 0; // should never happen 2341 }
2342 } 2342 }
2343 2343
2344 else 2344
2345 { 2345 private void changePhantomStatus(bool newval)
2346 m_collisionCategories = CollisionCategories.Geom; 2346 {
2347 if (m_isphysical) 2347 m_isphantom = newval;
2348 m_collisionCategories |= CollisionCategories.Body; 2348
2349 2349 if (m_isSelected)
2350 m_collisionFlags = m_default_collisionFlags | CollisionCategories.Land; 2350 {
2351 2351 m_collisionCategories = CollisionCategories.Selected;
2352 if (m_collidesWater) 2352 m_collisionFlags = (CollisionCategories.Sensor | CollisionCategories.Space);
2353 m_collisionFlags |= CollisionCategories.Water; 2353 }
2354 } 2354 else
2355 } 2355 {
2356 2356 if (m_isphantom && !m_isVolumeDetect)
2357 if (!childPrim) 2357 {
2358 { 2358 m_collisionCategories = 0;
2359 foreach (OdePrim prm in childrenPrim) 2359 if (m_isphysical)
2360 { 2360 m_collisionFlags = CollisionCategories.Land;
2361 prm.m_collisionCategories = m_collisionCategories; 2361 else
2362 prm.m_collisionFlags = m_collisionFlags; 2362 m_collisionFlags = 0; // should never happen
2363 2363 }
2364 if (!prm.m_disabled && prm.prim_geom != IntPtr.Zero) 2364
2365 { 2365 else
2366 if (prm.m_NoColide) 2366 {
2367 { 2367 m_collisionCategories = CollisionCategories.Geom;
2368 d.GeomSetCategoryBits(prm.prim_geom, 0); 2368 if (m_isphysical)
2369 if (m_isphysical) 2369 m_collisionCategories |= CollisionCategories.Body;
2370 d.GeomSetCollideBits(prm.prim_geom, (int)CollisionCategories.Land); 2370
2371 else 2371 m_collisionFlags = m_default_collisionFlags | CollisionCategories.Land;
2372 d.GeomSetCollideBits(prm.prim_geom, 0); 2372
2373 } 2373 if (m_collidesWater)
2374 else 2374 m_collisionFlags |= CollisionCategories.Water;
2375 { 2375 }
2376 d.GeomSetCategoryBits(prm.prim_geom, (int)m_collisionCategories); 2376 }
2377 d.GeomSetCollideBits(prm.prim_geom, (int)m_collisionFlags); 2377
2378 } 2378 if (!childPrim)
2379 if(!m_isSelected) 2379 {
2380 d.GeomEnable(prm.prim_geom); 2380 foreach (OdePrim prm in childrenPrim)
2381 } 2381 {
2382 } 2382 prm.m_collisionCategories = m_collisionCategories;
2383 } 2383 prm.m_collisionFlags = m_collisionFlags;
2384 2384
2385 if (!m_disabled && prim_geom != IntPtr.Zero) 2385 if (!prm.m_disabled && prm.prim_geom != IntPtr.Zero)
2386 { 2386 {
2387 if (m_NoColide) 2387 if (prm.m_NoColide)
2388 { 2388 {
2389 d.GeomSetCategoryBits(prim_geom, 0); 2389 d.GeomSetCategoryBits(prm.prim_geom, 0);
2390 if (m_isphysical) 2390 if (m_isphysical)
2391 d.GeomSetCollideBits(prim_geom, (int)CollisionCategories.Land); 2391 d.GeomSetCollideBits(prm.prim_geom, (int)CollisionCategories.Land);
2392 else 2392 else
2393 d.GeomSetCollideBits(prim_geom, 0); 2393 d.GeomSetCollideBits(prm.prim_geom, 0);
2394 } 2394 }
2395 else 2395 else
2396 { 2396 {
2397 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories); 2397 d.GeomSetCategoryBits(prm.prim_geom, (int)m_collisionCategories);
2398 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); 2398 d.GeomSetCollideBits(prm.prim_geom, (int)m_collisionFlags);
2399 } 2399 }
2400 if(!m_isSelected) 2400 if(!m_isSelected)
2401 d.GeomEnable(prim_geom); 2401 d.GeomEnable(prm.prim_geom);
2402 } 2402 }
2403 } 2403 }
2404 2404 }
2405 private void changeSelectedStatus(bool newval) 2405
2406 { 2406 if (!m_disabled && prim_geom != IntPtr.Zero)
2407 if (m_lastdoneSelected == newval) 2407 {
2408 return; 2408 if (m_NoColide)
2409 2409 {
2410 m_lastdoneSelected = newval; 2410 d.GeomSetCategoryBits(prim_geom, 0);
2411 DoSelectedStatus(newval); 2411 if (m_isphysical)
2412 } 2412 d.GeomSetCollideBits(prim_geom, (int)CollisionCategories.Land);
2413 2413 else
2414 private void CheckDelaySelect() 2414 d.GeomSetCollideBits(prim_geom, 0);
2415 { 2415 }
2416 if (m_delaySelect) 2416 else
2417 { 2417 {
2418 DoSelectedStatus(m_isSelected); 2418 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
2419 } 2419 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
2420 } 2420 }
2421 2421 if(!m_isSelected)
2422 private void DoSelectedStatus(bool newval) 2422 d.GeomEnable(prim_geom);
2423 { 2423 }
2424 m_isSelected = newval; 2424 }
2425 Stop(); 2425
2426 2426 private void changeSelectedStatus(bool newval)
2427 if (newval) 2427 {
2428 { 2428 if (m_lastdoneSelected == newval)
2429 if (!childPrim && Body != IntPtr.Zero) 2429 return;
2430 d.BodyDisable(Body); 2430
2431 2431 m_lastdoneSelected = newval;
2432 if (m_delaySelect || m_isphysical) 2432 DoSelectedStatus(newval);
2433 { 2433 }
2434 m_collisionCategories = CollisionCategories.Selected; 2434
2435 m_collisionFlags = (CollisionCategories.Sensor | CollisionCategories.Space); 2435 private void CheckDelaySelect()
2436 2436 {
2437 if (!childPrim) 2437 if (m_delaySelect)
2438 { 2438 {
2439 foreach (OdePrim prm in childrenPrim) 2439 DoSelectedStatus(m_isSelected);
2440 { 2440 }
2441 prm.m_collisionCategories = m_collisionCategories; 2441 }
2442 prm.m_collisionFlags = m_collisionFlags; 2442
2443 2443 private void DoSelectedStatus(bool newval)
2444 if (prm.prim_geom != null) 2444 {
2445 { 2445 m_isSelected = newval;
2446 2446 Stop();
2447 if (prm.m_NoColide) 2447
2448 { 2448 if (newval)
2449 d.GeomSetCategoryBits(prm.prim_geom, 0); 2449 {
2450 d.GeomSetCollideBits(prm.prim_geom, 0); 2450 if (!childPrim && Body != IntPtr.Zero)
2451 } 2451 d.BodyDisable(Body);
2452 else 2452
2453 { 2453 if (m_delaySelect || m_isphysical)
2454 d.GeomSetCategoryBits(prm.prim_geom, (int)m_collisionCategories); 2454 {
2455 d.GeomSetCollideBits(prm.prim_geom, (int)m_collisionFlags); 2455 m_collisionCategories = CollisionCategories.Selected;
2456 } 2456 m_collisionFlags = (CollisionCategories.Sensor | CollisionCategories.Space);
2457 d.GeomDisable(prm.prim_geom); 2457
2458 } 2458 if (!childPrim)
2459 prm.m_delaySelect = false; 2459 {
2460 } 2460 foreach (OdePrim prm in childrenPrim)
2461 } 2461 {
2462 2462 prm.m_collisionCategories = m_collisionCategories;
2463 if (prim_geom != null) 2463 prm.m_collisionFlags = m_collisionFlags;
2464 { 2464
2465 if (m_NoColide) 2465 if (prm.prim_geom != null)
2466 { 2466 {
2467 d.GeomSetCategoryBits(prim_geom, 0); 2467
2468 d.GeomSetCollideBits(prim_geom, 0); 2468 if (prm.m_NoColide)
2469 } 2469 {
2470 else 2470 d.GeomSetCategoryBits(prm.prim_geom, 0);
2471 { 2471 d.GeomSetCollideBits(prm.prim_geom, 0);
2472 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories); 2472 }
2473 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); 2473 else
2474 } 2474 {
2475 d.GeomDisable(prim_geom); 2475 d.GeomSetCategoryBits(prm.prim_geom, (int)m_collisionCategories);
2476 } 2476 d.GeomSetCollideBits(prm.prim_geom, (int)m_collisionFlags);
2477 2477 }
2478 m_delaySelect = false; 2478 d.GeomDisable(prm.prim_geom);
2479 } 2479 }
2480 else if(!m_isphysical) 2480 prm.m_delaySelect = false;
2481 { 2481 }
2482 m_delaySelect = true; 2482 }
2483 } 2483
2484 } 2484 if (prim_geom != null)
2485 else 2485 {
2486 { 2486 if (m_NoColide)
2487 if (!childPrim && Body != IntPtr.Zero && !m_disabled) 2487 {
2488 d.BodyEnable(Body); 2488 d.GeomSetCategoryBits(prim_geom, 0);
2489 2489 d.GeomSetCollideBits(prim_geom, 0);
2490 if (m_isphantom && !m_isVolumeDetect) 2490 }
2491 { 2491 else
2492 m_collisionCategories = 0; 2492 {
2493 if(m_isphysical) 2493 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
2494 m_collisionFlags = CollisionCategories.Land; 2494 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
2495 else 2495 }
2496 m_collisionFlags = 0; 2496 d.GeomDisable(prim_geom);
2497 } 2497 }
2498 else 2498
2499 { 2499 m_delaySelect = false;
2500 m_collisionCategories = CollisionCategories.Geom; 2500 }
2501 if (m_isphysical) 2501 else if(!m_isphysical)
2502 m_collisionCategories |= CollisionCategories.Body; 2502 {
2503 2503 m_delaySelect = true;
2504 m_collisionFlags = m_default_collisionFlags | CollisionCategories.Land; 2504 }
2505 2505 }
2506 if (m_collidesWater) 2506 else
2507 m_collisionFlags |= CollisionCategories.Water; 2507 {
2508 } 2508 if (!childPrim && Body != IntPtr.Zero && !m_disabled)
2509 2509 d.BodyEnable(Body);
2510 if (!childPrim) 2510
2511 { 2511 if (m_isphantom && !m_isVolumeDetect)
2512 foreach (OdePrim prm in childrenPrim) 2512 {
2513 { 2513 m_collisionCategories = 0;
2514 prm.m_collisionCategories = m_collisionCategories; 2514 if(m_isphysical)
2515 prm.m_collisionFlags = m_collisionFlags; 2515 m_collisionFlags = CollisionCategories.Land;
2516 2516 else
2517 if (!prm.m_disabled && prm.prim_geom != IntPtr.Zero) 2517 m_collisionFlags = 0;
2518 { 2518 }
2519 if (prm.m_NoColide) 2519 else
2520 { 2520 {
2521 d.GeomSetCategoryBits(prm.prim_geom, 0); 2521 m_collisionCategories = CollisionCategories.Geom;
2522 if (m_isphysical) 2522 if (m_isphysical)
2523 d.GeomSetCollideBits(prm.prim_geom, (int)CollisionCategories.Land); 2523 m_collisionCategories |= CollisionCategories.Body;
2524 else 2524
2525 d.GeomSetCollideBits(prm.prim_geom, 0); 2525 m_collisionFlags = m_default_collisionFlags | CollisionCategories.Land;
2526 } 2526
2527 else 2527 if (m_collidesWater)
2528 { 2528 m_collisionFlags |= CollisionCategories.Water;
2529 d.GeomSetCategoryBits(prm.prim_geom, (int)m_collisionCategories); 2529 }
2530 d.GeomSetCollideBits(prm.prim_geom, (int)m_collisionFlags); 2530
2531 } 2531 if (!childPrim)
2532 d.GeomEnable(prm.prim_geom); 2532 {
2533 } 2533 foreach (OdePrim prm in childrenPrim)
2534 prm.m_delaySelect = false; 2534 {
2535 prm.m_softcolide = true; 2535 prm.m_collisionCategories = m_collisionCategories;
2536 } 2536 prm.m_collisionFlags = m_collisionFlags;
2537 } 2537
2538 2538 if (!prm.m_disabled && prm.prim_geom != IntPtr.Zero)
2539 if (!m_disabled && prim_geom != IntPtr.Zero) 2539 {
2540 { 2540 if (prm.m_NoColide)
2541 if (m_NoColide) 2541 {
2542 { 2542 d.GeomSetCategoryBits(prm.prim_geom, 0);
2543 d.GeomSetCategoryBits(prim_geom, 0); 2543 if (m_isphysical)
2544 if (m_isphysical) 2544 d.GeomSetCollideBits(prm.prim_geom, (int)CollisionCategories.Land);
2545 d.GeomSetCollideBits(prim_geom, (int)CollisionCategories.Land); 2545 else
2546 else 2546 d.GeomSetCollideBits(prm.prim_geom, 0);
2547 d.GeomSetCollideBits(prim_geom, 0); 2547 }
2548 } 2548 else
2549 else 2549 {
2550 { 2550 d.GeomSetCategoryBits(prm.prim_geom, (int)m_collisionCategories);
2551 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories); 2551 d.GeomSetCollideBits(prm.prim_geom, (int)m_collisionFlags);
2552 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); 2552 }
2553 } 2553 d.GeomEnable(prm.prim_geom);
2554 d.GeomEnable(prim_geom); 2554 }
2555 } 2555 prm.m_delaySelect = false;
2556 2556 prm.m_softcolide = true;
2557 m_delaySelect = false; 2557 }
2558 m_softcolide = true; 2558 }
2559 } 2559
2560 2560 if (!m_disabled && prim_geom != IntPtr.Zero)
2561 resetCollisionAccounting(); 2561 {
2562 } 2562 if (m_NoColide)
2563 2563 {
2564 private void changePosition(Vector3 newPos) 2564 d.GeomSetCategoryBits(prim_geom, 0);
2565 { 2565 if (m_isphysical)
2566 CheckDelaySelect(); 2566 d.GeomSetCollideBits(prim_geom, (int)CollisionCategories.Land);
2567 if (m_isphysical) 2567 else
2568 { 2568 d.GeomSetCollideBits(prim_geom, 0);
2569 if (childPrim) // inertia is messed, must rebuild 2569 }
2570 { 2570 else
2571 if (m_building) 2571 {
2572 { 2572 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
2573 _position = newPos; 2573 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
2574 } 2574 }
2575 } 2575 d.GeomEnable(prim_geom);
2576 else 2576 }
2577 { 2577
2578 if (_position != newPos) 2578 m_delaySelect = false;
2579 { 2579 m_softcolide = true;
2580 d.GeomSetPosition(prim_geom, newPos.X, newPos.Y, newPos.Z); 2580 }
2581 _position = newPos; 2581
2582 } 2582 resetCollisionAccounting();
2583 if (Body != IntPtr.Zero && !d.BodyIsEnabled(Body)) 2583 }
2584 d.BodyEnable(Body); 2584
2585 } 2585 private void changePosition(Vector3 newPos)
2586 } 2586 {
2587 else 2587 CheckDelaySelect();
2588 { 2588 if (m_isphysical)
2589 if (prim_geom != IntPtr.Zero) 2589 {
2590 { 2590 if (childPrim) // inertia is messed, must rebuild
2591 if (newPos != _position) 2591 {
2592 { 2592 if (m_building)
2593 d.GeomSetPosition(prim_geom, newPos.X, newPos.Y, newPos.Z); 2593 {
2594 _position = newPos; 2594 _position = newPos;
2595 2595 }
2596 m_targetSpace = _parent_scene.MoveGeomToStaticSpace(prim_geom, _position, m_targetSpace); 2596 }
2597 } 2597 else
2598 } 2598 {
2599 } 2599 if (_position != newPos)
2600 givefakepos--; 2600 {
2601 if (givefakepos < 0) 2601 d.GeomSetPosition(prim_geom, newPos.X, newPos.Y, newPos.Z);
2602 givefakepos = 0; 2602 _position = newPos;
2603 // changeSelectedStatus(); 2603 }
2604 m_softcolide = true; 2604 if (Body != IntPtr.Zero && !d.BodyIsEnabled(Body))
2605 resetCollisionAccounting(); 2605 d.BodyEnable(Body);
2606 } 2606 }
2607 2607 }
2608 private void changeOrientation(Quaternion newOri) 2608 else
2609 { 2609 {
2610 CheckDelaySelect(); 2610 if (prim_geom != IntPtr.Zero)
2611 if (m_isphysical) 2611 {
2612 { 2612 if (newPos != _position)
2613 if (childPrim) // inertia is messed, must rebuild 2613 {
2614 { 2614 d.GeomSetPosition(prim_geom, newPos.X, newPos.Y, newPos.Z);
2615 if (m_building) 2615 _position = newPos;
2616 { 2616
2617 _orientation = newOri; 2617 m_targetSpace = _parent_scene.MoveGeomToStaticSpace(prim_geom, _position, m_targetSpace);
2618 } 2618 }
2619 } 2619 }
2620 else 2620 }
2621 { 2621 givefakepos--;
2622 if (newOri != _orientation) 2622 if (givefakepos < 0)
2623 { 2623 givefakepos = 0;
2624 d.Quaternion myrot = new d.Quaternion(); 2624 // changeSelectedStatus();
2625 myrot.X = newOri.X; 2625 m_softcolide = true;
2626 myrot.Y = newOri.Y; 2626 resetCollisionAccounting();
2627 myrot.Z = newOri.Z; 2627 }
2628 myrot.W = newOri.W; 2628
2629 d.GeomSetQuaternion(prim_geom, ref myrot); 2629 private void changeOrientation(Quaternion newOri)
2630 _orientation = newOri; 2630 {
2631 if (Body != IntPtr.Zero && !m_angularlock.ApproxEquals(Vector3.One, 0f)) 2631 CheckDelaySelect();
2632 createAMotor(m_angularlock); 2632 if (m_isphysical)
2633 } 2633 {
2634 if (Body != IntPtr.Zero && !d.BodyIsEnabled(Body)) 2634 if (childPrim) // inertia is messed, must rebuild
2635 d.BodyEnable(Body); 2635 {
2636 } 2636 if (m_building)
2637 } 2637 {
2638 else 2638 _orientation = newOri;
2639 { 2639 }
2640 if (prim_geom != IntPtr.Zero) 2640 }
2641 { 2641 else
2642 if (newOri != _orientation) 2642 {
2643 { 2643 if (newOri != _orientation)
2644 d.Quaternion myrot = new d.Quaternion(); 2644 {
2645 myrot.X = newOri.X; 2645 d.Quaternion myrot = new d.Quaternion();
2646 myrot.Y = newOri.Y; 2646 myrot.X = newOri.X;
2647 myrot.Z = newOri.Z; 2647 myrot.Y = newOri.Y;
2648 myrot.W = newOri.W; 2648 myrot.Z = newOri.Z;
2649 d.GeomSetQuaternion(prim_geom, ref myrot); 2649 myrot.W = newOri.W;
2650 _orientation = newOri; 2650 d.GeomSetQuaternion(prim_geom, ref myrot);
2651 } 2651 _orientation = newOri;
2652 } 2652 if (Body != IntPtr.Zero && !m_angularlock.ApproxEquals(Vector3.One, 0f))
2653 } 2653 createAMotor(m_angularlock);
2654 givefakeori--; 2654 }
2655 if (givefakeori < 0) 2655 if (Body != IntPtr.Zero && !d.BodyIsEnabled(Body))
2656 givefakeori = 0; 2656 d.BodyEnable(Body);
2657 m_softcolide = true; 2657 }
2658 resetCollisionAccounting(); 2658 }
2659 } 2659 else
2660 2660 {
2661 private void changePositionAndOrientation(Vector3 newPos, Quaternion newOri) 2661 if (prim_geom != IntPtr.Zero)
2662 { 2662 {
2663 CheckDelaySelect(); 2663 if (newOri != _orientation)
2664 if (m_isphysical) 2664 {
2665 { 2665 d.Quaternion myrot = new d.Quaternion();
2666 if (childPrim && m_building) // inertia is messed, must rebuild 2666 myrot.X = newOri.X;
2667 { 2667 myrot.Y = newOri.Y;
2668 _position = newPos; 2668 myrot.Z = newOri.Z;
2669 _orientation = newOri; 2669 myrot.W = newOri.W;
2670 } 2670 d.GeomSetQuaternion(prim_geom, ref myrot);
2671 else 2671 _orientation = newOri;
2672 { 2672 }
2673 if (newOri != _orientation) 2673 }
2674 { 2674 }
2675 d.Quaternion myrot = new d.Quaternion(); 2675 givefakeori--;
2676 myrot.X = newOri.X; 2676 if (givefakeori < 0)
2677 myrot.Y = newOri.Y; 2677 givefakeori = 0;
2678 myrot.Z = newOri.Z; 2678 m_softcolide = true;
2679 myrot.W = newOri.W; 2679 resetCollisionAccounting();
2680 d.GeomSetQuaternion(prim_geom, ref myrot); 2680 }
2681 _orientation = newOri; 2681
2682 if (Body != IntPtr.Zero && !m_angularlock.ApproxEquals(Vector3.One, 0f)) 2682 private void changePositionAndOrientation(Vector3 newPos, Quaternion newOri)
2683 createAMotor(m_angularlock); 2683 {
2684 } 2684 CheckDelaySelect();
2685 if (_position != newPos) 2685 if (m_isphysical)
2686 { 2686 {
2687 d.GeomSetPosition(prim_geom, newPos.X, newPos.Y, newPos.Z); 2687 if (childPrim && m_building) // inertia is messed, must rebuild
2688 _position = newPos; 2688 {
2689 } 2689 _position = newPos;
2690 if (Body != IntPtr.Zero && !d.BodyIsEnabled(Body)) 2690 _orientation = newOri;
2691 d.BodyEnable(Body); 2691 }
2692 } 2692 else
2693 } 2693 {
2694 else 2694 if (newOri != _orientation)
2695 { 2695 {
2696 // string primScenAvatarIn = _parent_scene.whichspaceamIin(_position); 2696 d.Quaternion myrot = new d.Quaternion();
2697 // int[] arrayitem = _parent_scene.calculateSpaceArrayItemFromPos(_position); 2697 myrot.X = newOri.X;
2698 2698 myrot.Y = newOri.Y;
2699 if (prim_geom != IntPtr.Zero) 2699 myrot.Z = newOri.Z;
2700 { 2700 myrot.W = newOri.W;
2701 if (newOri != _orientation) 2701 d.GeomSetQuaternion(prim_geom, ref myrot);
2702 { 2702 _orientation = newOri;
2703 d.Quaternion myrot = new d.Quaternion(); 2703 if (Body != IntPtr.Zero && !m_angularlock.ApproxEquals(Vector3.One, 0f))
2704 myrot.X = newOri.X; 2704 createAMotor(m_angularlock);
2705 myrot.Y = newOri.Y; 2705 }
2706 myrot.Z = newOri.Z; 2706 if (_position != newPos)
2707 myrot.W = newOri.W; 2707 {
2708 d.GeomSetQuaternion(prim_geom, ref myrot); 2708 d.GeomSetPosition(prim_geom, newPos.X, newPos.Y, newPos.Z);
2709 _orientation = newOri; 2709 _position = newPos;
2710 } 2710 }
2711 2711 if (Body != IntPtr.Zero && !d.BodyIsEnabled(Body))
2712 if (newPos != _position) 2712 d.BodyEnable(Body);
2713 { 2713 }
2714 d.GeomSetPosition(prim_geom, newPos.X, newPos.Y, newPos.Z); 2714 }
2715 _position = newPos; 2715 else
2716 2716 {
2717 m_targetSpace = _parent_scene.MoveGeomToStaticSpace(prim_geom, _position, m_targetSpace); 2717 // string primScenAvatarIn = _parent_scene.whichspaceamIin(_position);
2718 } 2718 // int[] arrayitem = _parent_scene.calculateSpaceArrayItemFromPos(_position);
2719 } 2719
2720 } 2720 if (prim_geom != IntPtr.Zero)
2721 givefakepos--; 2721 {
2722 if (givefakepos < 0) 2722 if (newOri != _orientation)
2723 givefakepos = 0; 2723 {
2724 givefakeori--; 2724 d.Quaternion myrot = new d.Quaternion();
2725 if (givefakeori < 0) 2725 myrot.X = newOri.X;
2726 givefakeori = 0; 2726 myrot.Y = newOri.Y;
2727 2727 myrot.Z = newOri.Z;
2728 m_softcolide = true; 2728 myrot.W = newOri.W;
2729 resetCollisionAccounting(); 2729 d.GeomSetQuaternion(prim_geom, ref myrot);
2730 } 2730 _orientation = newOri;
2731 2731 }
2732 2732
2733 private void changeDisable(bool disable) 2733 if (newPos != _position)
2734 { 2734 {
2735 if (disable) 2735 d.GeomSetPosition(prim_geom, newPos.X, newPos.Y, newPos.Z);
2736 { 2736 _position = newPos;
2737 if (!m_disabled) 2737
2738 disableBodySoft(); 2738 m_targetSpace = _parent_scene.MoveGeomToStaticSpace(prim_geom, _position, m_targetSpace);
2739 } 2739 }
2740 else 2740 }
2741 { 2741 }
2742 if (m_disabled) 2742 givefakepos--;
2743 enableBodySoft(); 2743 if (givefakepos < 0)
2744 } 2744 givefakepos = 0;
2745 } 2745 givefakeori--;
2746 2746 if (givefakeori < 0)
2747 private void changePhysicsStatus(bool NewStatus) 2747 givefakeori = 0;
2748 { 2748
2749 CheckDelaySelect(); 2749 m_softcolide = true;
2750 2750 resetCollisionAccounting();
2751 m_isphysical = NewStatus; 2751 }
2752 2752
2753 if (!childPrim) 2753
2754 { 2754 private void changeDisable(bool disable)
2755 if (NewStatus) 2755 {
2756 { 2756 if (disable)
2757 if (Body == IntPtr.Zero) 2757 {
2758 MakeBody(); 2758 if (!m_disabled)
2759 } 2759 disableBodySoft();
2760 else 2760 }
2761 { 2761 else
2762 if (Body != IntPtr.Zero) 2762 {
2763 { 2763 if (m_disabled)
2764 DestroyBody(); 2764 enableBodySoft();
2765 } 2765 }
2766 Stop(); 2766 }
2767 } 2767
2768 } 2768 private void changePhysicsStatus(bool NewStatus)
2769 2769 {
2770 resetCollisionAccounting(); 2770 CheckDelaySelect();
2771 } 2771
2772 2772 m_isphysical = NewStatus;
2773 private void changeprimsizeshape() 2773
2774 { 2774 if (!childPrim)
2775 CheckDelaySelect(); 2775 {
2776 2776 if (NewStatus)
2777 OdePrim parent = (OdePrim)_parent; 2777 {
2778 2778 if (Body == IntPtr.Zero)
2779 bool chp = childPrim; 2779 MakeBody();
2780 2780 }
2781 if (chp) 2781 else
2782 { 2782 {
2783 if (parent != null) 2783 if (Body != IntPtr.Zero)
2784 { 2784 {
2785 parent.DestroyBody(); 2785 DestroyBody();
2786 } 2786 }
2787 } 2787 Stop();
2788 else 2788 }
2789 { 2789 }
2790 DestroyBody(); 2790
2791 } 2791 resetCollisionAccounting();
2792 2792 }
2793 RemoveGeom(); 2793
2794 2794 private void changeprimsizeshape()
2795 // we don't need to do space calculation because the client sends a position update also. 2795 {
2796 if (_size.X <= 0) 2796 CheckDelaySelect();
2797 _size.X = 0.01f; 2797
2798 if (_size.Y <= 0) 2798 OdePrim parent = (OdePrim)_parent;
2799 _size.Y = 0.01f; 2799
2800 if (_size.Z <= 0) 2800 bool chp = childPrim;
2801 _size.Z = 0.01f; 2801
2802 // Construction of new prim 2802 if (chp)
2803 2803 {
2804 CreateGeom(); 2804 if (parent != null)
2805 2805 {
2806 if (prim_geom != IntPtr.Zero) 2806 parent.DestroyBody();
2807 { 2807 }
2808 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z); 2808 }
2809 d.Quaternion myrot = new d.Quaternion(); 2809 else
2810 myrot.X = _orientation.X; 2810 {
2811 myrot.Y = _orientation.Y; 2811 DestroyBody();
2812 myrot.Z = _orientation.Z; 2812 }
2813 myrot.W = _orientation.W; 2813
2814 d.GeomSetQuaternion(prim_geom, ref myrot); 2814 RemoveGeom();
2815 } 2815
2816 2816 // we don't need to do space calculation because the client sends a position update also.
2817 if (chp) 2817 if (_size.X <= 0)
2818 { 2818 _size.X = 0.01f;
2819 if (parent != null) 2819 if (_size.Y <= 0)
2820 { 2820 _size.Y = 0.01f;
2821 parent.MakeBody(); 2821 if (_size.Z <= 0)
2822 } 2822 _size.Z = 0.01f;
2823 } 2823 // Construction of new prim
2824 else 2824
2825 MakeBody(); 2825 CreateGeom();
2826 2826
2827 m_softcolide = true; 2827 if (prim_geom != IntPtr.Zero)
2828 resetCollisionAccounting(); 2828 {
2829 } 2829 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
2830 2830 d.Quaternion myrot = new d.Quaternion();
2831 private void changeSize(Vector3 newSize) 2831 myrot.X = _orientation.X;
2832 { 2832 myrot.Y = _orientation.Y;
2833 _size = newSize; 2833 myrot.Z = _orientation.Z;
2834 changeprimsizeshape(); 2834 myrot.W = _orientation.W;
2835 } 2835 d.GeomSetQuaternion(prim_geom, ref myrot);
2836 2836 }
2837 private void changeShape(PrimitiveBaseShape newShape) 2837
2838 { 2838 if (chp)
2839 _pbs = newShape; 2839 {
2840 changeprimsizeshape(); 2840 if (parent != null)
2841 } 2841 {
2842 2842 parent.MakeBody();
2843 private void changeFloatOnWater(bool newval) 2843 }
2844 { 2844 }
2845 m_collidesWater = newval; 2845 else
2846 2846 MakeBody();
2847 if (prim_geom != IntPtr.Zero && !m_isphantom) 2847
2848 { 2848 m_softcolide = true;
2849 if (m_collidesWater) 2849 resetCollisionAccounting();
2850 { 2850 }
2851 m_collisionFlags |= CollisionCategories.Water; 2851
2852 } 2852 private void changeSize(Vector3 newSize)
2853 else 2853 {
2854 { 2854 _size = newSize;
2855 m_collisionFlags &= ~CollisionCategories.Water; 2855 changeprimsizeshape();
2856 } 2856 }
2857 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); 2857
2858 } 2858 private void changeShape(PrimitiveBaseShape newShape)
2859 } 2859 {
2860 2860 if(newShape != null)
2861 private void changeSetTorque(Vector3 newtorque) 2861 _pbs = newShape;
2862 { 2862 changeprimsizeshape();
2863 if (!m_isSelected) 2863 }
2864 { 2864
2865 if (m_isphysical && Body != IntPtr.Zero) 2865 private void changeFloatOnWater(bool newval)
2866 { 2866 {
2867 if (m_disabled) 2867 m_collidesWater = newval;
2868 enableBodySoft(); 2868
2869 else if (!d.BodyIsEnabled(Body)) 2869 if (prim_geom != IntPtr.Zero && !m_isphantom)
2870 d.BodyEnable(Body); 2870 {
2871 2871 if (m_collidesWater)
2872 } 2872 {
2873 _torque = newtorque; 2873 m_collisionFlags |= CollisionCategories.Water;
2874 } 2874 }
2875 } 2875 else
2876 2876 {
2877 private void changeForce(Vector3 force) 2877 m_collisionFlags &= ~CollisionCategories.Water;
2878 { 2878 }
2879 m_force = force; 2879 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
2880 if (Body != IntPtr.Zero && !d.BodyIsEnabled(Body)) 2880 }
2881 d.BodyEnable(Body); 2881 }
2882 } 2882
2883 2883 private void changeSetTorque(Vector3 newtorque)
2884 private void changeAddForce(Vector3 force) 2884 {
2885 { 2885 if (!m_isSelected)
2886 m_forceacc += force; 2886 {
2887 if (!m_isSelected) 2887 if (m_isphysical && Body != IntPtr.Zero)
2888 { 2888 {
2889 lock (this) 2889 if (m_disabled)
2890 { 2890 enableBodySoft();
2891 //m_log.Info("[PHYSICS]: dequeing forcelist"); 2891 else if (!d.BodyIsEnabled(Body))
2892 if (m_isphysical && Body != IntPtr.Zero) 2892 d.BodyEnable(Body);
2893 { 2893
2894 if (m_disabled) 2894 }
2895 enableBodySoft(); 2895 _torque = newtorque;
2896 else if (!d.BodyIsEnabled(Body)) 2896 }
2897 d.BodyEnable(Body); 2897 }
2898 } 2898
2899 } 2899 private void changeForce(Vector3 force)
2900 2900 {
2901 m_collisionscore = 0; 2901 m_force = force;
2902 } 2902 if (Body != IntPtr.Zero && !d.BodyIsEnabled(Body))
2903 } 2903 d.BodyEnable(Body);
2904 2904 }
2905 private void changeAddAngularForce(Vector3 aforce) 2905
2906 { 2906 private void changeAddForce(Vector3 force)
2907 m_angularForceacc += aforce; 2907 {
2908 if (!m_isSelected) 2908 m_forceacc += force;
2909 { 2909 if (!m_isSelected)
2910 lock (this) 2910 {
2911 { 2911 lock (this)
2912 if (m_isphysical && Body != IntPtr.Zero) 2912 {
2913 { 2913 //m_log.Info("[PHYSICS]: dequeing forcelist");
2914 if (m_disabled) 2914 if (m_isphysical && Body != IntPtr.Zero)
2915 enableBodySoft(); 2915 {
2916 else if (!d.BodyIsEnabled(Body)) 2916 if (m_disabled)
2917 d.BodyEnable(Body); 2917 enableBodySoft();
2918 } 2918 else if (!d.BodyIsEnabled(Body))
2919 } 2919 d.BodyEnable(Body);
2920 m_collisionscore = 0; 2920 }
2921 } 2921 }
2922 } 2922
2923 2923 m_collisionscore = 0;
2924 private void changevelocity(Vector3 newVel) 2924 }
2925 { 2925 }
2926 if (!m_isSelected) 2926
2927 { 2927 private void changeAddAngularForce(Vector3 aforce)
2928 if (Body != IntPtr.Zero) 2928 {
2929 { 2929 m_angularForceacc += aforce;
2930 if (m_disabled) 2930 if (!m_isSelected)
2931 enableBodySoft(); 2931 {
2932 else if (!d.BodyIsEnabled(Body)) 2932 lock (this)
2933 d.BodyEnable(Body); 2933 {
2934 2934 if (m_isphysical && Body != IntPtr.Zero)
2935 d.BodySetLinearVel(Body, newVel.X, newVel.Y, newVel.Z); 2935 {
2936 } 2936 if (m_disabled)
2937 //resetCollisionAccounting(); 2937 enableBodySoft();
2938 } 2938 else if (!d.BodyIsEnabled(Body))
2939 _velocity = newVel; 2939 d.BodyEnable(Body);
2940 } 2940 }
2941 2941 }
2942 private void changeVolumedetetion(bool newVolDtc) 2942 m_collisionscore = 0;
2943 { 2943 }
2944 m_isVolumeDetect = newVolDtc; 2944 }
2945 } 2945
2946 2946 private void changevelocity(Vector3 newVel)
2947 protected void changeBuilding(bool newbuilding) 2947 {
2948 { 2948 if (!m_isSelected)
2949 if ((bool)newbuilding) 2949 {
2950 { 2950 if (Body != IntPtr.Zero)
2951 m_building = true; 2951 {
2952 if (!childPrim) 2952 if (m_disabled)
2953 DestroyBody(); 2953 enableBodySoft();
2954 } 2954 else if (!d.BodyIsEnabled(Body))
2955 else 2955 d.BodyEnable(Body);
2956 { 2956
2957 m_building = false; 2957 d.BodySetLinearVel(Body, newVel.X, newVel.Y, newVel.Z);
2958 CheckDelaySelect(); 2958 }
2959 if (!childPrim) 2959 //resetCollisionAccounting();
2960 MakeBody(); 2960 }
2961 } 2961 _velocity = newVel;
2962 if (!childPrim && childrenPrim.Count > 0) 2962 }
2963 { 2963
2964 foreach (OdePrim prm in childrenPrim) 2964 private void changeVolumedetetion(bool newVolDtc)
2965 prm.changeBuilding(m_building); // call directly 2965 {
2966 } 2966 m_isVolumeDetect = newVolDtc;
2967 } 2967 }
2968 2968
2969 public void changeSetVehicle(VehicleData vdata) 2969 protected void changeBuilding(bool newbuilding)
2970 { 2970 {
2971 if (m_vehicle == null) 2971 if ((bool)newbuilding)
2972 m_vehicle = new ODEDynamics(this); 2972 {
2973 m_vehicle.DoSetVehicle(vdata); 2973 m_building = true;
2974 } 2974 if (!childPrim)
2975 private void changeVehicleType(int value) 2975 DestroyBody();
2976 { 2976 }
2977 if (value == (int)Vehicle.TYPE_NONE) 2977 else
2978 { 2978 {
2979 if (m_vehicle != null) 2979 m_building = false;
2980 m_vehicle = null; 2980 CheckDelaySelect();
2981 } 2981 if (!childPrim)
2982 else 2982 MakeBody();
2983 { 2983 }
2984 if (m_vehicle == null) 2984 if (!childPrim && childrenPrim.Count > 0)
2985 m_vehicle = new ODEDynamics(this); 2985 {
2986 2986 foreach (OdePrim prm in childrenPrim)
2987 m_vehicle.ProcessTypeChange((Vehicle)value); 2987 prm.changeBuilding(m_building); // call directly
2988 } 2988 }
2989 } 2989 }
2990 2990
2991 private void changeVehicleFloatParam(strVehicleFloatParam fp) 2991 public void changeSetVehicle(VehicleData vdata)
2992 { 2992 {
2993 if (m_vehicle == null) 2993 if (m_vehicle == null)
2994 return; 2994 m_vehicle = new ODEDynamics(this);
2995 2995 m_vehicle.DoSetVehicle(vdata);
2996 m_vehicle.ProcessFloatVehicleParam((Vehicle)fp.param, fp.value); 2996 }
2997 } 2997 private void changeVehicleType(int value)
2998 2998 {
2999 private void changeVehicleVectorParam(strVehicleVectorParam vp) 2999 if (value == (int)Vehicle.TYPE_NONE)
3000 { 3000 {
3001 if (m_vehicle == null) 3001 if (m_vehicle != null)
3002 return; 3002 m_vehicle = null;
3003 m_vehicle.ProcessVectorVehicleParam((Vehicle)vp.param, vp.value); 3003 }
3004 } 3004 else
3005 3005 {
3006 private void changeVehicleRotationParam(strVehicleQuatParam qp) 3006 if (m_vehicle == null)
3007 { 3007 m_vehicle = new ODEDynamics(this);
3008 if (m_vehicle == null) 3008
3009 return; 3009 m_vehicle.ProcessTypeChange((Vehicle)value);
3010 m_vehicle.ProcessRotationVehicleParam((Vehicle)qp.param, qp.value); 3010 }
3011 } 3011 }
3012 3012
3013 private void changeVehicleFlags(strVehicleBoolParam bp) 3013 private void changeVehicleFloatParam(strVehicleFloatParam fp)
3014 { 3014 {
3015 if (m_vehicle == null) 3015 if (m_vehicle == null)
3016 return; 3016 return;
3017 m_vehicle.ProcessVehicleFlags(bp.param, bp.value); 3017
3018 } 3018 m_vehicle.ProcessFloatVehicleParam((Vehicle)fp.param, fp.value);
3019 3019 }
3020 #endregion 3020
3021 3021 private void changeVehicleVectorParam(strVehicleVectorParam vp)
3022 public void Move() 3022 {
3023 { 3023 if (m_vehicle == null)
3024 if (!childPrim && m_isphysical && Body != IntPtr.Zero && 3024 return;
3025 !m_disabled && !m_isSelected && d.BodyIsEnabled(Body) && !m_building && !m_outbounds) 3025 m_vehicle.ProcessVectorVehicleParam((Vehicle)vp.param, vp.value);
3026 // !m_disabled && !m_isSelected && !m_building && !m_outbounds) 3026 }
3027 { 3027
3028// if (!d.BodyIsEnabled(Body)) d.BodyEnable(Body); // KF add 161009 3028 private void changeVehicleRotationParam(strVehicleQuatParam qp)
3029 3029 {
3030 float timestep = _parent_scene.ODE_STEPSIZE; 3030 if (m_vehicle == null)
3031 3031 return;
3032 // check outside region 3032 m_vehicle.ProcessRotationVehicleParam((Vehicle)qp.param, qp.value);
3033 d.Vector3 lpos; 3033 }
3034 d.GeomCopyPosition(prim_geom, out lpos); // root position that is seem by rest of simulator 3034
3035 3035 private void changeVehicleFlags(strVehicleBoolParam bp)
3036 if (lpos.Z < -100 || lpos.Z > 100000f) 3036 {
3037 { 3037 if (m_vehicle == null)
3038 m_outbounds = true; 3038 return;
3039 3039 m_vehicle.ProcessVehicleFlags(bp.param, bp.value);
3040 lpos.Z = Util.Clip(lpos.Z, -100f, 100000f); 3040 }
3041 _acceleration.X = 0; 3041
3042 _acceleration.Y = 0; 3042 #endregion
3043 _acceleration.Z = 0; 3043
3044 3044 public void Move()
3045 _velocity.X = 0; 3045 {
3046 _velocity.Y = 0; 3046 if (!childPrim && m_isphysical && Body != IntPtr.Zero &&
3047 _velocity.Z = 0; 3047 !m_disabled && !m_isSelected && d.BodyIsEnabled(Body) && !m_building && !m_outbounds)
3048 m_rotationalVelocity.X = 0; 3048 // !m_disabled && !m_isSelected && !m_building && !m_outbounds)
3049 m_rotationalVelocity.Y = 0; 3049 {
3050 m_rotationalVelocity.Z = 0; 3050// if (!d.BodyIsEnabled(Body)) d.BodyEnable(Body); // KF add 161009
3051 3051
3052 d.BodySetLinearVel(Body, 0, 0, 0); // stop it 3052 float timestep = _parent_scene.ODE_STEPSIZE;
3053 d.BodySetAngularVel(Body, 0, 0, 0); // stop it 3053
3054 d.BodySetPosition(Body, lpos.X, lpos.Y, lpos.Z); // put it somewhere 3054 // check outside region
3055 m_lastposition = _position; 3055 d.Vector3 lpos;
3056 m_lastorientation = _orientation; 3056 d.GeomCopyPosition(prim_geom, out lpos); // root position that is seem by rest of simulator
3057 3057
3058 base.RequestPhysicsterseUpdate(); 3058 if (lpos.Z < -100 || lpos.Z > 100000f)
3059 3059 {
3060 m_throttleUpdates = false; 3060 m_outbounds = true;
3061 throttleCounter = 0; 3061
3062 _zeroFlag = true; 3062 lpos.Z = Util.Clip(lpos.Z, -100f, 100000f);
3063 3063 _acceleration.X = 0;
3064 disableBodySoft(); // disable it and colisions 3064 _acceleration.Y = 0;
3065 base.RaiseOutOfBounds(_position); 3065 _acceleration.Z = 0;
3066 return; 3066
3067 } 3067 _velocity.X = 0;
3068 3068 _velocity.Y = 0;
3069 if (lpos.X < 0f) 3069 _velocity.Z = 0;
3070 { 3070 m_rotationalVelocity.X = 0;
3071 _position.X = Util.Clip(lpos.X, -2f, -0.1f); 3071 m_rotationalVelocity.Y = 0;
3072 m_outbounds = true; 3072 m_rotationalVelocity.Z = 0;
3073 } 3073
3074 else if(lpos.X > _parent_scene.WorldExtents.X) 3074 d.BodySetLinearVel(Body, 0, 0, 0); // stop it
3075 { 3075 d.BodySetAngularVel(Body, 0, 0, 0); // stop it
3076 _position.X = Util.Clip(lpos.X, _parent_scene.WorldExtents.X + 0.1f, _parent_scene.WorldExtents.X + 2f); 3076 d.BodySetPosition(Body, lpos.X, lpos.Y, lpos.Z); // put it somewhere
3077 m_outbounds = true; 3077 m_lastposition = _position;
3078 } 3078 m_lastorientation = _orientation;
3079 if (lpos.Y < 0f) 3079
3080 { 3080 base.RequestPhysicsterseUpdate();
3081 _position.Y = Util.Clip(lpos.Y, -2f, -0.1f); 3081
3082 m_outbounds = true; 3082 m_throttleUpdates = false;
3083 } 3083 throttleCounter = 0;
3084 else if(lpos.Y > _parent_scene.WorldExtents.Y) 3084 _zeroFlag = true;
3085 { 3085
3086 _position.Y = Util.Clip(lpos.Y, _parent_scene.WorldExtents.Y + 0.1f, _parent_scene.WorldExtents.Y + 2f); 3086 disableBodySoft(); // disable it and colisions
3087 m_outbounds = true; 3087 base.RaiseOutOfBounds(_position);
3088 } 3088 return;
3089 3089 }
3090 if(m_outbounds) 3090
3091 { 3091 if (lpos.X < 0f)
3092 m_lastposition = _position; 3092 {
3093 m_lastorientation = _orientation; 3093 _position.X = Util.Clip(lpos.X, -2f, -0.1f);
3094 3094 m_outbounds = true;
3095 d.Vector3 dtmp = d.BodyGetAngularVel(Body); 3095 }
3096 m_rotationalVelocity.X = dtmp.X; 3096 else if(lpos.X > _parent_scene.WorldExtents.X)
3097 m_rotationalVelocity.Y = dtmp.Y; 3097 {
3098 m_rotationalVelocity.Z = dtmp.Z; 3098 _position.X = Util.Clip(lpos.X, _parent_scene.WorldExtents.X + 0.1f, _parent_scene.WorldExtents.X + 2f);
3099 3099 m_outbounds = true;
3100 dtmp = d.BodyGetLinearVel(Body); 3100 }
3101 _velocity.X = dtmp.X; 3101 if (lpos.Y < 0f)
3102 _velocity.Y = dtmp.Y; 3102 {
3103 _velocity.Z = dtmp.Z; 3103 _position.Y = Util.Clip(lpos.Y, -2f, -0.1f);
3104 3104 m_outbounds = true;
3105 d.BodySetLinearVel(Body, 0, 0, 0); // stop it 3105 }
3106 d.BodySetAngularVel(Body, 0, 0, 0); 3106 else if(lpos.Y > _parent_scene.WorldExtents.Y)
3107 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z); 3107 {
3108 disableBodySoft(); // stop collisions 3108 _position.Y = Util.Clip(lpos.Y, _parent_scene.WorldExtents.Y + 0.1f, _parent_scene.WorldExtents.Y + 2f);
3109 base.RequestPhysicsterseUpdate(); 3109 m_outbounds = true;
3110 return; 3110 }
3111 } 3111
3112 3112 if(m_outbounds)
3113 3113 {
3114 float fx = 0; 3114 m_lastposition = _position;
3115 float fy = 0; 3115 m_lastorientation = _orientation;
3116 float fz = 0; 3116
3117 3117 d.Vector3 dtmp = d.BodyGetAngularVel(Body);
3118 if (m_vehicle != null && m_vehicle.Type != Vehicle.TYPE_NONE) 3118 m_rotationalVelocity.X = dtmp.X;
3119 { 3119 m_rotationalVelocity.Y = dtmp.Y;
3120 // 'VEHICLES' are dealt with in ODEDynamics.cs 3120 m_rotationalVelocity.Z = dtmp.Z;
3121 m_vehicle.Step(); 3121
3122 } 3122 dtmp = d.BodyGetLinearVel(Body);
3123 else 3123 _velocity.X = dtmp.X;
3124 { 3124 _velocity.Y = dtmp.Y;
3125 float m_mass = _mass; 3125 _velocity.Z = dtmp.Z;
3126 3126
3127 // fz = 0f; 3127 d.BodySetLinearVel(Body, 0, 0, 0); // stop it
3128 //m_log.Info(m_collisionFlags.ToString()); 3128 d.BodySetAngularVel(Body, 0, 0, 0);
3129 if (m_usePID) 3129 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
3130 { 3130 disableBodySoft(); // stop collisions
3131 3131 base.RequestPhysicsterseUpdate();
3132 // If the PID Controller isn't active then we set our force 3132 return;
3133 // calculating base velocity to the current position 3133 }
3134 3134
3135 if ((m_PIDTau < 1) && (m_PIDTau != 0)) 3135
3136 { 3136 float fx = 0;
3137 //PID_G = PID_G / m_PIDTau; 3137 float fy = 0;
3138 m_PIDTau = 1; 3138 float fz = 0;
3139 } 3139
3140 3140 if (m_vehicle != null && m_vehicle.Type != Vehicle.TYPE_NONE)
3141 if ((PID_G - m_PIDTau) <= 0) 3141 {
3142 { 3142 // 'VEHICLES' are dealt with in ODEDynamics.cs
3143 PID_G = m_PIDTau + 1; 3143 m_vehicle.Step();
3144 } 3144 }
3145 3145 else
3146 d.Vector3 vel = d.BodyGetLinearVel(Body); 3146 {
3147 d.Vector3 pos = d.BodyGetPosition(Body); 3147 float m_mass = _mass;
3148 _target_velocity = 3148
3149 new Vector3( 3149 // fz = 0f;
3150 (m_PIDTarget.X - pos.X) * ((PID_G - m_PIDTau) * timestep), 3150 //m_log.Info(m_collisionFlags.ToString());
3151 (m_PIDTarget.Y - pos.Y) * ((PID_G - m_PIDTau) * timestep), 3151 if (m_usePID)
3152 (m_PIDTarget.Z - pos.Z) * ((PID_G - m_PIDTau) * timestep) 3152 {
3153 ); 3153
3154 3154 // If the PID Controller isn't active then we set our force
3155 // if velocity is zero, use position control; otherwise, velocity control 3155 // calculating base velocity to the current position
3156 3156
3157 if (_target_velocity.ApproxEquals(Vector3.Zero, 0.1f)) 3157 if ((m_PIDTau < 1) && (m_PIDTau != 0))
3158 { 3158 {
3159 // keep track of where we stopped. No more slippin' & slidin' 3159 //PID_G = PID_G / m_PIDTau;
3160 3160 m_PIDTau = 1;
3161 // We only want to deactivate the PID Controller if we think we want to have our surrogate 3161 }
3162 // react to the physics scene by moving it's position. 3162
3163 // Avatar to Avatar collisions 3163 if ((PID_G - m_PIDTau) <= 0)
3164 // Prim to avatar collisions 3164 {
3165 3165 PID_G = m_PIDTau + 1;
3166 //fx = (_target_velocity.X - vel.X) * (PID_D) + (_zeroPosition.X - pos.X) * (PID_P * 2); 3166 }
3167 //fy = (_target_velocity.Y - vel.Y) * (PID_D) + (_zeroPosition.Y - pos.Y) * (PID_P * 2); 3167
3168 //fz = fz + (_target_velocity.Z - vel.Z) * (PID_D) + (_zeroPosition.Z - pos.Z) * PID_P; 3168 d.Vector3 vel = d.BodyGetLinearVel(Body);
3169 d.BodySetPosition(Body, m_PIDTarget.X, m_PIDTarget.Y, m_PIDTarget.Z); 3169 d.Vector3 pos = d.BodyGetPosition(Body);
3170 d.BodySetLinearVel(Body, 0, 0, 0); 3170 _target_velocity =
3171 d.BodyAddForce(Body, 0, 0, fz); 3171 new Vector3(
3172 return; 3172 (m_PIDTarget.X - pos.X) * ((PID_G - m_PIDTau) * timestep),
3173 } 3173 (m_PIDTarget.Y - pos.Y) * ((PID_G - m_PIDTau) * timestep),
3174 else 3174 (m_PIDTarget.Z - pos.Z) * ((PID_G - m_PIDTau) * timestep)
3175 { 3175 );
3176 _zeroFlag = false; 3176
3177 3177 // if velocity is zero, use position control; otherwise, velocity control
3178 // We're flying and colliding with something 3178
3179 fx = ((_target_velocity.X) - vel.X) * (PID_D); 3179 if (_target_velocity.ApproxEquals(Vector3.Zero, 0.1f))
3180 fy = ((_target_velocity.Y) - vel.Y) * (PID_D); 3180 {
3181 3181 // keep track of where we stopped. No more slippin' & slidin'
3182 // vec.Z = (_target_velocity.Z - vel.Z) * PID_D + (_zeroPosition.Z - pos.Z) * PID_P; 3182
3183 3183 // We only want to deactivate the PID Controller if we think we want to have our surrogate
3184 fz = ((_target_velocity.Z - vel.Z) * (PID_D)); 3184 // react to the physics scene by moving it's position.
3185 } 3185 // Avatar to Avatar collisions
3186 } // end if (m_usePID) 3186 // Prim to avatar collisions
3187 3187
3188 // Hover PID Controller needs to be mutually exlusive to MoveTo PID controller 3188 //fx = (_target_velocity.X - vel.X) * (PID_D) + (_zeroPosition.X - pos.X) * (PID_P * 2);
3189 else if (m_useHoverPID) 3189 //fy = (_target_velocity.Y - vel.Y) * (PID_D) + (_zeroPosition.Y - pos.Y) * (PID_P * 2);
3190 { 3190 //fz = fz + (_target_velocity.Z - vel.Z) * (PID_D) + (_zeroPosition.Z - pos.Z) * PID_P;
3191 //Console.WriteLine("Hover " + Name); 3191 d.BodySetPosition(Body, m_PIDTarget.X, m_PIDTarget.Y, m_PIDTarget.Z);
3192 3192 d.BodySetLinearVel(Body, 0, 0, 0);
3193 // If we're using the PID controller, then we have no gravity 3193 d.BodyAddForce(Body, 0, 0, fz);
3194 3194 return;
3195 // no lock; for now it's only called from within Simulate() 3195 }
3196 3196 else
3197 // If the PID Controller isn't active then we set our force 3197 {
3198 // calculating base velocity to the current position 3198 _zeroFlag = false;
3199 3199
3200 if ((m_PIDTau < 1)) 3200 // We're flying and colliding with something
3201 { 3201 fx = ((_target_velocity.X) - vel.X) * (PID_D);
3202 PID_G = PID_G / m_PIDTau; 3202 fy = ((_target_velocity.Y) - vel.Y) * (PID_D);
3203 } 3203
3204 3204 // vec.Z = (_target_velocity.Z - vel.Z) * PID_D + (_zeroPosition.Z - pos.Z) * PID_P;
3205 if ((PID_G - m_PIDTau) <= 0) 3205
3206 { 3206 fz = ((_target_velocity.Z - vel.Z) * (PID_D));
3207 PID_G = m_PIDTau + 1; 3207 }
3208 } 3208 } // end if (m_usePID)
3209 3209
3210 // Where are we, and where are we headed? 3210 // Hover PID Controller needs to be mutually exlusive to MoveTo PID controller
3211 d.Vector3 pos = d.BodyGetPosition(Body); 3211 else if (m_useHoverPID)
3212 d.Vector3 vel = d.BodyGetLinearVel(Body); 3212 {
3213 3213 //Console.WriteLine("Hover " + Name);
3214 // Non-Vehicles have a limited set of Hover options. 3214
3215 // determine what our target height really is based on HoverType 3215 // If we're using the PID controller, then we have no gravity
3216 switch (m_PIDHoverType) 3216
3217 { 3217 // no lock; for now it's only called from within Simulate()
3218 case PIDHoverType.Ground: 3218
3219 m_groundHeight = _parent_scene.GetTerrainHeightAtXY(pos.X, pos.Y); 3219 // If the PID Controller isn't active then we set our force
3220 m_targetHoverHeight = m_groundHeight + m_PIDHoverHeight; 3220 // calculating base velocity to the current position
3221 break; 3221
3222 case PIDHoverType.GroundAndWater: 3222 if ((m_PIDTau < 1))
3223 m_groundHeight = _parent_scene.GetTerrainHeightAtXY(pos.X, pos.Y); 3223 {
3224 m_waterHeight = _parent_scene.GetWaterLevel(); 3224 PID_G = PID_G / m_PIDTau;
3225 if (m_groundHeight > m_waterHeight) 3225 }
3226 { 3226
3227 m_targetHoverHeight = m_groundHeight + m_PIDHoverHeight; 3227 if ((PID_G - m_PIDTau) <= 0)
3228 } 3228 {
3229 else 3229 PID_G = m_PIDTau + 1;
3230 { 3230 }
3231 m_targetHoverHeight = m_waterHeight + m_PIDHoverHeight; 3231
3232 } 3232 // Where are we, and where are we headed?
3233 break; 3233 d.Vector3 pos = d.BodyGetPosition(Body);
3234 3234 d.Vector3 vel = d.BodyGetLinearVel(Body);
3235 } // end switch (m_PIDHoverType) 3235
3236 3236 // Non-Vehicles have a limited set of Hover options.
3237 3237 // determine what our target height really is based on HoverType
3238 _target_velocity = 3238 switch (m_PIDHoverType)
3239 new Vector3(0.0f, 0.0f, 3239 {
3240 (m_targetHoverHeight - pos.Z) * ((PID_G - m_PIDHoverTau) * timestep) 3240 case PIDHoverType.Ground:
3241 ); 3241 m_groundHeight = _parent_scene.GetTerrainHeightAtXY(pos.X, pos.Y);
3242 3242 m_targetHoverHeight = m_groundHeight + m_PIDHoverHeight;
3243 // if velocity is zero, use position control; otherwise, velocity control 3243 break;
3244 3244 case PIDHoverType.GroundAndWater:
3245 if (_target_velocity.ApproxEquals(Vector3.Zero, 0.1f)) 3245 m_groundHeight = _parent_scene.GetTerrainHeightAtXY(pos.X, pos.Y);
3246 { 3246 m_waterHeight = _parent_scene.GetWaterLevel();
3247 // keep track of where we stopped. No more slippin' & slidin' 3247 if (m_groundHeight > m_waterHeight)
3248 3248 {
3249 // We only want to deactivate the PID Controller if we think we want to have our surrogate 3249 m_targetHoverHeight = m_groundHeight + m_PIDHoverHeight;
3250 // react to the physics scene by moving it's position. 3250 }
3251 // Avatar to Avatar collisions 3251 else
3252 // Prim to avatar collisions 3252 {
3253 3253 m_targetHoverHeight = m_waterHeight + m_PIDHoverHeight;
3254 d.BodySetPosition(Body, pos.X, pos.Y, m_targetHoverHeight); 3254 }
3255 d.BodySetLinearVel(Body, vel.X, vel.Y, 0); 3255 break;
3256 // ? d.BodyAddForce(Body, 0, 0, fz); 3256
3257 return; 3257 } // end switch (m_PIDHoverType)
3258 } 3258
3259 else 3259
3260 { 3260 _target_velocity =
3261 _zeroFlag = false; 3261 new Vector3(0.0f, 0.0f,
3262 3262 (m_targetHoverHeight - pos.Z) * ((PID_G - m_PIDHoverTau) * timestep)
3263 // We're flying and colliding with something 3263 );
3264 fz = ((_target_velocity.Z - vel.Z) * (PID_D)); 3264
3265 } 3265 // if velocity is zero, use position control; otherwise, velocity control
3266 } 3266
3267 else 3267 if (_target_velocity.ApproxEquals(Vector3.Zero, 0.1f))
3268 { 3268 {
3269 float b = (1.0f - m_buoyancy); 3269 // keep track of where we stopped. No more slippin' & slidin'
3270 fx = _parent_scene.gravityx * b; 3270
3271 fy = _parent_scene.gravityy * b; 3271 // We only want to deactivate the PID Controller if we think we want to have our surrogate
3272 fz = _parent_scene.gravityz * b; 3272 // react to the physics scene by moving it's position.
3273 } 3273 // Avatar to Avatar collisions
3274 3274 // Prim to avatar collisions
3275 fx *= m_mass; 3275
3276 fy *= m_mass; 3276 d.BodySetPosition(Body, pos.X, pos.Y, m_targetHoverHeight);
3277 fz *= m_mass; 3277 d.BodySetLinearVel(Body, vel.X, vel.Y, 0);
3278 3278 // ? d.BodyAddForce(Body, 0, 0, fz);
3279 // constant force 3279 return;
3280 fx += m_force.X; 3280 }
3281 fy += m_force.Y; 3281 else
3282 fz += m_force.Z; 3282 {
3283 3283 _zeroFlag = false;
3284 fx += m_forceacc.X; 3284
3285 fy += m_forceacc.Y; 3285 // We're flying and colliding with something
3286 fz += m_forceacc.Z; 3286 fz = ((_target_velocity.Z - vel.Z) * (PID_D));
3287 3287 }
3288 m_forceacc = Vector3.Zero; 3288 }
3289 3289 else
3290 //m_log.Info("[OBJPID]: X:" + fx.ToString() + " Y:" + fy.ToString() + " Z:" + fz.ToString()); 3290 {
3291 if (fx != 0 || fy != 0 || fz != 0) 3291 float b = (1.0f - m_buoyancy);
3292 { 3292 fx = _parent_scene.gravityx * b;
3293 d.BodyAddForce(Body, fx, fy, fz); 3293 fy = _parent_scene.gravityy * b;
3294 //Console.WriteLine("AddForce " + fx + "," + fy + "," + fz); 3294 fz = _parent_scene.gravityz * b;
3295 } 3295 }
3296 3296
3297 Vector3 trq; 3297 fx *= m_mass;
3298 3298 fy *= m_mass;
3299 trq = _torque; 3299 fz *= m_mass;
3300 trq += m_angularForceacc; 3300
3301 m_angularForceacc = Vector3.Zero; 3301 // constant force
3302 if (trq.X != 0 || trq.Y != 0 || trq.Z != 0) 3302 fx += m_force.X;
3303 { 3303 fy += m_force.Y;
3304 d.BodyAddTorque(Body, trq.X, trq.Y, trq.Z); 3304 fz += m_force.Z;
3305 } 3305
3306 3306 fx += m_forceacc.X;
3307 } 3307 fy += m_forceacc.Y;
3308 } 3308 fz += m_forceacc.Z;
3309 else 3309
3310 { // is not physical, or is not a body or is selected 3310 m_forceacc = Vector3.Zero;
3311 // _zeroPosition = d.BodyGetPosition(Body); 3311
3312 return; 3312 //m_log.Info("[OBJPID]: X:" + fx.ToString() + " Y:" + fy.ToString() + " Z:" + fz.ToString());
3313 //Console.WriteLine("Nothing " + Name); 3313 if (fx != 0 || fy != 0 || fz != 0)
3314 3314 {
3315 } 3315 d.BodyAddForce(Body, fx, fy, fz);
3316 } 3316 //Console.WriteLine("AddForce " + fx + "," + fy + "," + fz);
3317 3317 }
3318 3318
3319 public void UpdatePositionAndVelocity(float simulatedtime) 3319 Vector3 trq;
3320 { 3320
3321 // no lock; called from Simulate() -- if you call this from elsewhere, gotta lock or do Monitor.Enter/Exit! 3321 trq = _torque;
3322 if (_parent == null && !m_disabled && !m_building && !m_outbounds) 3322 trq += m_angularForceacc;
3323 { 3323 m_angularForceacc = Vector3.Zero;
3324 if (Body != IntPtr.Zero) 3324 if (trq.X != 0 || trq.Y != 0 || trq.Z != 0)
3325 { 3325 {
3326 Vector3 pv = Vector3.Zero; 3326 d.BodyAddTorque(Body, trq.X, trq.Y, trq.Z);
3327 bool lastZeroFlag = _zeroFlag; 3327 }
3328 3328
3329 d.Vector3 lpos; 3329 }
3330 d.GeomCopyPosition(prim_geom, out lpos); // root position that is seem by rest of simulator 3330 }
3331 3331 else
3332 3332 { // is not physical, or is not a body or is selected
3333 d.Quaternion ori; 3333 // _zeroPosition = d.BodyGetPosition(Body);
3334 d.GeomCopyQuaternion(prim_geom, out ori); 3334 return;
3335 d.Vector3 vel = d.BodyGetLinearVel(Body); 3335 //Console.WriteLine("Nothing " + Name);
3336 d.Vector3 rotvel = d.BodyGetAngularVel(Body); 3336
3337 3337 }
3338 if ((Math.Abs(m_lastposition.X - lpos.X) < 0.01) 3338 }
3339 && (Math.Abs(m_lastposition.Y - lpos.Y) < 0.01) 3339
3340 && (Math.Abs(m_lastposition.Z - lpos.Z) < 0.01) 3340
3341 && (Math.Abs(m_lastorientation.X - ori.X) < 0.0001) 3341 public void UpdatePositionAndVelocity(float simulatedtime)
3342 && (Math.Abs(m_lastorientation.Y - ori.Y) < 0.0001) 3342 {
3343 && (Math.Abs(m_lastorientation.Z - ori.Z) < 0.0001) 3343 // no lock; called from Simulate() -- if you call this from elsewhere, gotta lock or do Monitor.Enter/Exit!
3344 ) 3344 if (_parent == null && !m_disabled && !m_building && !m_outbounds)
3345 { 3345 {
3346 _zeroFlag = true; 3346 if (Body != IntPtr.Zero)
3347 //Console.WriteLine("ZFT 2"); 3347 {
3348 m_throttleUpdates = false; 3348 Vector3 pv = Vector3.Zero;
3349 } 3349 bool lastZeroFlag = _zeroFlag;
3350 else 3350
3351 { 3351 d.Vector3 lpos;
3352 //m_log.Debug(Math.Abs(m_lastposition.X - l_position.X).ToString()); 3352 d.GeomCopyPosition(prim_geom, out lpos); // root position that is seem by rest of simulator
3353 _zeroFlag = false; 3353
3354 m_lastUpdateSent = false; 3354
3355 //m_throttleUpdates = false; 3355 d.Quaternion ori;
3356 } 3356 d.GeomCopyQuaternion(prim_geom, out ori);
3357 3357 d.Vector3 vel = d.BodyGetLinearVel(Body);
3358 if (_zeroFlag) 3358 d.Vector3 rotvel = d.BodyGetAngularVel(Body);
3359 { 3359
3360 m_lastposition = _position; 3360 if ((Math.Abs(m_lastposition.X - lpos.X) < 0.01)
3361 m_lastorientation = _orientation; 3361 && (Math.Abs(m_lastposition.Y - lpos.Y) < 0.01)
3362 3362 && (Math.Abs(m_lastposition.Z - lpos.Z) < 0.01)
3363 _velocity.X = 0.0f; 3363 && (Math.Abs(m_lastorientation.X - ori.X) < 0.0001)
3364 _velocity.Y = 0.0f; 3364 && (Math.Abs(m_lastorientation.Y - ori.Y) < 0.0001)
3365 _velocity.Z = 0.0f; 3365 && (Math.Abs(m_lastorientation.Z - ori.Z) < 0.0001)
3366 3366 )
3367 _acceleration.X = 0; 3367 {
3368 _acceleration.Y = 0; 3368 _zeroFlag = true;
3369 _acceleration.Z = 0; 3369 //Console.WriteLine("ZFT 2");
3370 3370 m_throttleUpdates = false;
3371 m_rotationalVelocity.X = 0; 3371 }
3372 m_rotationalVelocity.Y = 0; 3372 else
3373 m_rotationalVelocity.Z = 0; 3373 {
3374 if (!m_lastUpdateSent) 3374 //m_log.Debug(Math.Abs(m_lastposition.X - l_position.X).ToString());
3375 { 3375 _zeroFlag = false;
3376 m_throttleUpdates = false; 3376 m_lastUpdateSent = false;
3377 throttleCounter = 0; 3377 //m_throttleUpdates = false;
3378 m_rotationalVelocity = pv; 3378 }
3379 3379
3380 base.RequestPhysicsterseUpdate(); 3380 if (_zeroFlag)
3381 3381 {
3382 m_lastUpdateSent = true; 3382 m_lastposition = _position;
3383 } 3383 m_lastorientation = _orientation;
3384 } 3384
3385 else 3385 _velocity.X = 0.0f;
3386 { 3386 _velocity.Y = 0.0f;
3387 if (lastZeroFlag != _zeroFlag) 3387 _velocity.Z = 0.0f;
3388 { 3388
3389 base.RequestPhysicsterseUpdate(); 3389 _acceleration.X = 0;
3390 } 3390 _acceleration.Y = 0;
3391 3391 _acceleration.Z = 0;
3392 m_lastVelocity = _velocity; 3392
3393 3393 m_rotationalVelocity.X = 0;
3394 _position.X = lpos.X; 3394 m_rotationalVelocity.Y = 0;
3395 _position.Y = lpos.Y; 3395 m_rotationalVelocity.Z = 0;
3396 _position.Z = lpos.Z; 3396 if (!m_lastUpdateSent)
3397 3397 {
3398 _velocity.X = vel.X; 3398 m_throttleUpdates = false;
3399 _velocity.Y = vel.Y; 3399 throttleCounter = 0;
3400 _velocity.Z = vel.Z; 3400 m_rotationalVelocity = pv;
3401 3401
3402 _orientation.X = ori.X; 3402 base.RequestPhysicsterseUpdate();
3403 _orientation.Y = ori.Y; 3403
3404 _orientation.Z = ori.Z; 3404 m_lastUpdateSent = true;
3405 _orientation.W = ori.W; 3405 }
3406 3406 }
3407 _acceleration = ((_velocity - m_lastVelocity) / simulatedtime); 3407 else
3408 3408 {
3409 if (m_rotationalVelocity.ApproxEquals(pv, 0.0001f)) 3409 if (lastZeroFlag != _zeroFlag)
3410 { 3410 {
3411 m_rotationalVelocity = pv; 3411 base.RequestPhysicsterseUpdate();
3412 } 3412 }
3413 else 3413
3414 { 3414 m_lastVelocity = _velocity;
3415 m_rotationalVelocity.X = rotvel.X; 3415
3416 m_rotationalVelocity.Y = rotvel.Y; 3416 _position.X = lpos.X;
3417 m_rotationalVelocity.Z = rotvel.Z; 3417 _position.Y = lpos.Y;
3418 } 3418 _position.Z = lpos.Z;
3419 3419
3420 m_lastUpdateSent = false; 3420 _velocity.X = vel.X;
3421 if (!m_throttleUpdates || throttleCounter > _parent_scene.geomUpdatesPerThrottledUpdate) 3421 _velocity.Y = vel.Y;
3422 { 3422 _velocity.Z = vel.Z;
3423 m_lastposition = _position; 3423
3424 m_lastorientation = _orientation; 3424 _orientation.X = ori.X;
3425 base.RequestPhysicsterseUpdate(); 3425 _orientation.Y = ori.Y;
3426 } 3426 _orientation.Z = ori.Z;
3427 else 3427 _orientation.W = ori.W;
3428 { 3428
3429 throttleCounter++; 3429 _acceleration = ((_velocity - m_lastVelocity) / simulatedtime);
3430 } 3430
3431 } 3431 if (m_rotationalVelocity.ApproxEquals(pv, 0.0001f))
3432 } 3432 {
3433 else if (!m_lastUpdateSent || !_zeroFlag) 3433 m_rotationalVelocity = pv;
3434 { 3434 }
3435 // Not a body.. so Make sure the client isn't interpolating 3435 else
3436 _velocity.X = 0; 3436 {
3437 _velocity.Y = 0; 3437 m_rotationalVelocity.X = rotvel.X;
3438 _velocity.Z = 0; 3438 m_rotationalVelocity.Y = rotvel.Y;
3439 3439 m_rotationalVelocity.Z = rotvel.Z;
3440 _acceleration.X = 0; 3440 }
3441 _acceleration.Y = 0; 3441
3442 _acceleration.Z = 0; 3442 m_lastUpdateSent = false;
3443 3443 if (!m_throttleUpdates || throttleCounter > _parent_scene.geomUpdatesPerThrottledUpdate)
3444 m_rotationalVelocity.X = 0; 3444 {
3445 m_rotationalVelocity.Y = 0; 3445 m_lastposition = _position;
3446 m_rotationalVelocity.Z = 0; 3446 m_lastorientation = _orientation;
3447 _zeroFlag = true; 3447 base.RequestPhysicsterseUpdate();
3448 3448 }
3449 if (!m_lastUpdateSent) 3449 else
3450 { 3450 {
3451 m_throttleUpdates = false; 3451 throttleCounter++;
3452 throttleCounter = 0; 3452 }
3453 3453 }
3454 base.RequestPhysicsterseUpdate(); 3454 }
3455 3455 else if (!m_lastUpdateSent || !_zeroFlag)
3456 m_lastUpdateSent = true; 3456 {
3457 } 3457 // Not a body.. so Make sure the client isn't interpolating
3458 } 3458 _velocity.X = 0;
3459 } 3459 _velocity.Y = 0;
3460 } 3460 _velocity.Z = 0;
3461 3461
3462 internal static bool QuaternionIsFinite(Quaternion q) 3462 _acceleration.X = 0;
3463 { 3463 _acceleration.Y = 0;
3464 if (Single.IsNaN(q.X) || Single.IsInfinity(q.X)) 3464 _acceleration.Z = 0;
3465 return false; 3465
3466 if (Single.IsNaN(q.Y) || Single.IsInfinity(q.Y)) 3466 m_rotationalVelocity.X = 0;
3467 return false; 3467 m_rotationalVelocity.Y = 0;
3468 if (Single.IsNaN(q.Z) || Single.IsInfinity(q.Z)) 3468 m_rotationalVelocity.Z = 0;
3469 return false; 3469 _zeroFlag = true;
3470 if (Single.IsNaN(q.W) || Single.IsInfinity(q.W)) 3470
3471 return false; 3471 if (!m_lastUpdateSent)
3472 return true; 3472 {
3473 } 3473 m_throttleUpdates = false;
3474 3474 throttleCounter = 0;
3475 internal static void DMassCopy(ref d.Mass src, ref d.Mass dst) 3475
3476 { 3476 base.RequestPhysicsterseUpdate();
3477 dst.c.W = src.c.W; 3477
3478 dst.c.X = src.c.X; 3478 m_lastUpdateSent = true;
3479 dst.c.Y = src.c.Y; 3479 }
3480 dst.c.Z = src.c.Z; 3480 }
3481 dst.mass = src.mass; 3481 }
3482 dst.I.M00 = src.I.M00; 3482 }
3483 dst.I.M01 = src.I.M01; 3483
3484 dst.I.M02 = src.I.M02; 3484 internal static bool QuaternionIsFinite(Quaternion q)
3485 dst.I.M10 = src.I.M10; 3485 {
3486 dst.I.M11 = src.I.M11; 3486 if (Single.IsNaN(q.X) || Single.IsInfinity(q.X))
3487 dst.I.M12 = src.I.M12; 3487 return false;
3488 dst.I.M20 = src.I.M20; 3488 if (Single.IsNaN(q.Y) || Single.IsInfinity(q.Y))
3489 dst.I.M21 = src.I.M21; 3489 return false;
3490 dst.I.M22 = src.I.M22; 3490 if (Single.IsNaN(q.Z) || Single.IsInfinity(q.Z))
3491 } 3491 return false;
3492 3492 if (Single.IsNaN(q.W) || Single.IsInfinity(q.W))
3493 private static void DMassDup(ref d.Mass src, out d.Mass dst) 3493 return false;
3494 { 3494 return true;
3495 dst = new d.Mass { }; 3495 }
3496 3496
3497 dst.c.W = src.c.W; 3497 internal static void DMassCopy(ref d.Mass src, ref d.Mass dst)
3498 dst.c.X = src.c.X; 3498 {
3499 dst.c.Y = src.c.Y; 3499 dst.c.W = src.c.W;
3500 dst.c.Z = src.c.Z; 3500 dst.c.X = src.c.X;
3501 dst.mass = src.mass; 3501 dst.c.Y = src.c.Y;
3502 dst.I.M00 = src.I.M00; 3502 dst.c.Z = src.c.Z;
3503 dst.I.M01 = src.I.M01; 3503 dst.mass = src.mass;
3504 dst.I.M02 = src.I.M02; 3504 dst.I.M00 = src.I.M00;
3505 dst.I.M10 = src.I.M10; 3505 dst.I.M01 = src.I.M01;
3506 dst.I.M11 = src.I.M11; 3506 dst.I.M02 = src.I.M02;
3507 dst.I.M12 = src.I.M12; 3507 dst.I.M10 = src.I.M10;
3508 dst.I.M20 = src.I.M20; 3508 dst.I.M11 = src.I.M11;
3509 dst.I.M21 = src.I.M21; 3509 dst.I.M12 = src.I.M12;
3510 dst.I.M22 = src.I.M22; 3510 dst.I.M20 = src.I.M20;
3511 } 3511 dst.I.M21 = src.I.M21;
3512 private void donullchange() 3512 dst.I.M22 = src.I.M22;
3513 { 3513 }
3514 } 3514
3515 3515 private static void DMassDup(ref d.Mass src, out d.Mass dst)
3516 public bool DoAChange(changes what, object arg) 3516 {
3517 { 3517 dst = new d.Mass { };
3518 if (prim_geom == IntPtr.Zero && what != changes.Add && what != changes.Remove) 3518
3519 { 3519 dst.c.W = src.c.W;
3520 return false; 3520 dst.c.X = src.c.X;
3521 } 3521 dst.c.Y = src.c.Y;
3522 3522 dst.c.Z = src.c.Z;
3523 // nasty switch 3523 dst.mass = src.mass;
3524 switch (what) 3524 dst.I.M00 = src.I.M00;
3525 { 3525 dst.I.M01 = src.I.M01;
3526 case changes.Add: 3526 dst.I.M02 = src.I.M02;
3527 changeadd(); 3527 dst.I.M10 = src.I.M10;
3528 break; 3528 dst.I.M11 = src.I.M11;
3529 case changes.Remove: 3529 dst.I.M12 = src.I.M12;
3530 //If its being removed, we don't want to rebuild the physical rep at all, so ignore this stuff... 3530 dst.I.M20 = src.I.M20;
3531 //When we return true, it destroys all of the prims in the linkset anyway 3531 dst.I.M21 = src.I.M21;
3532 if (_parent != null) 3532 dst.I.M22 = src.I.M22;
3533 { 3533 }
3534 OdePrim parent = (OdePrim)_parent; 3534 private void donullchange()
3535 parent.ChildRemove(this, false); 3535 {
3536 } 3536 }
3537 else 3537
3538 ChildRemove(this, false); 3538 public bool DoAChange(changes what, object arg)
3539 3539 {
3540 m_vehicle = null; 3540 if (prim_geom == IntPtr.Zero && what != changes.Add && what != changes.Remove)
3541 RemoveGeom(); 3541 {
3542 m_targetSpace = IntPtr.Zero; 3542 return false;
3543 if (m_eventsubscription > 0) 3543 }
3544 UnSubscribeEvents(); 3544
3545 return true; 3545 // nasty switch
3546 3546 switch (what)
3547 case changes.Link: 3547 {
3548 OdePrim tmp = (OdePrim)arg; 3548 case changes.Add:
3549 changeLink(tmp); 3549 changeadd();
3550 break; 3550 break;
3551 3551 case changes.Remove:
3552 case changes.DeLink: 3552 //If its being removed, we don't want to rebuild the physical rep at all, so ignore this stuff...
3553 changeLink(null); 3553 //When we return true, it destroys all of the prims in the linkset anyway
3554 break; 3554 if (_parent != null)
3555 3555 {
3556 case changes.Position: 3556 OdePrim parent = (OdePrim)_parent;
3557 changePosition((Vector3)arg); 3557 parent.ChildRemove(this, false);
3558 break; 3558 }
3559 3559 else
3560 case changes.Orientation: 3560 ChildRemove(this, false);
3561 changeOrientation((Quaternion)arg); 3561
3562 break; 3562 m_vehicle = null;
3563 3563 RemoveGeom();
3564 case changes.PosOffset: 3564 m_targetSpace = IntPtr.Zero;
3565 donullchange(); 3565 if (m_eventsubscription > 0)
3566 break; 3566 UnSubscribeEvents();
3567 3567 return true;
3568 case changes.OriOffset: 3568
3569 donullchange(); 3569 case changes.Link:
3570 break; 3570 OdePrim tmp = (OdePrim)arg;
3571 3571 changeLink(tmp);
3572 case changes.Velocity: 3572 break;
3573 changevelocity((Vector3)arg); 3573
3574 break; 3574 case changes.DeLink:
3575 3575 changeLink(null);
3576 // case changes.Acceleration: 3576 break;
3577 // changeacceleration((Vector3)arg); 3577
3578 // break; 3578 case changes.Position:
3579 // case changes.AngVelocity: 3579 changePosition((Vector3)arg);
3580 // changeangvelocity((Vector3)arg); 3580 break;
3581 // break; 3581
3582 3582 case changes.Orientation:
3583 case changes.Force: 3583 changeOrientation((Quaternion)arg);
3584 changeForce((Vector3)arg); 3584 break;
3585 break; 3585
3586 3586 case changes.PosOffset:
3587 case changes.Torque: 3587 donullchange();
3588 changeSetTorque((Vector3)arg); 3588 break;
3589 break; 3589
3590 3590 case changes.OriOffset:
3591 case changes.AddForce: 3591 donullchange();
3592 changeAddForce((Vector3)arg); 3592 break;
3593 break; 3593
3594 3594 case changes.Velocity:
3595 case changes.AddAngForce: 3595 changevelocity((Vector3)arg);
3596 changeAddAngularForce((Vector3)arg); 3596 break;
3597 break; 3597
3598 3598 // case changes.Acceleration:
3599 case changes.AngLock: 3599 // changeacceleration((Vector3)arg);
3600 changeAngularLock((Vector3)arg); 3600 // break;
3601 break; 3601 // case changes.AngVelocity:
3602 3602 // changeangvelocity((Vector3)arg);
3603 case changes.Size: 3603 // break;
3604 changeSize((Vector3)arg); 3604
3605 break; 3605 case changes.Force:
3606 3606 changeForce((Vector3)arg);
3607 case changes.Shape: 3607 break;
3608 changeShape((PrimitiveBaseShape)arg); 3608
3609 break; 3609 case changes.Torque:
3610 3610 changeSetTorque((Vector3)arg);
3611 case changes.CollidesWater: 3611 break;
3612 changeFloatOnWater((bool)arg); 3612
3613 break; 3613 case changes.AddForce:
3614 3614 changeAddForce((Vector3)arg);
3615 case changes.VolumeDtc: 3615 break;
3616 changeVolumedetetion((bool)arg); 3616
3617 break; 3617 case changes.AddAngForce:
3618 3618 changeAddAngularForce((Vector3)arg);
3619 case changes.Phantom: 3619 break;
3620 changePhantomStatus((bool)arg); 3620
3621 break; 3621 case changes.AngLock:
3622 3622 changeAngularLock((Vector3)arg);
3623 case changes.Physical: 3623 break;
3624 changePhysicsStatus((bool)arg); 3624
3625 break; 3625 case changes.Size:
3626 3626 changeSize((Vector3)arg);
3627 case changes.Selected: 3627 break;
3628 changeSelectedStatus((bool)arg); 3628
3629 break; 3629 case changes.Shape:
3630 3630 changeShape((PrimitiveBaseShape)arg);
3631 case changes.disabled: 3631 break;
3632 changeDisable((bool)arg); 3632
3633 break; 3633 case changes.CollidesWater:
3634 3634 changeFloatOnWater((bool)arg);
3635 case changes.building: 3635 break;
3636 changeBuilding((bool)arg); 3636
3637 break; 3637 case changes.VolumeDtc:
3638 3638 changeVolumedetetion((bool)arg);
3639 case changes.VehicleType: 3639 break;
3640 changeVehicleType((int)arg); 3640
3641 break; 3641 case changes.Phantom:
3642 3642 changePhantomStatus((bool)arg);
3643 case changes.VehicleFlags: 3643 break;
3644 changeVehicleFlags((strVehicleBoolParam) arg); 3644
3645 break; 3645 case changes.Physical:
3646 3646 changePhysicsStatus((bool)arg);
3647 case changes.VehicleFloatParam: 3647 break;
3648 changeVehicleFloatParam((strVehicleFloatParam) arg); 3648
3649 break; 3649 case changes.Selected:
3650 3650 changeSelectedStatus((bool)arg);
3651 case changes.VehicleVectorParam: 3651 break;
3652 changeVehicleVectorParam((strVehicleVectorParam) arg); 3652
3653 break; 3653 case changes.disabled:
3654 3654 changeDisable((bool)arg);
3655 case changes.VehicleRotationParam: 3655 break;
3656 changeVehicleRotationParam((strVehicleQuatParam) arg); 3656
3657 break; 3657 case changes.building:
3658 3658 changeBuilding((bool)arg);
3659 case changes.SetVehicle: 3659 break;
3660 changeSetVehicle((VehicleData) arg); 3660
3661 break; 3661 case changes.VehicleType:
3662 case changes.Null: 3662 changeVehicleType((int)arg);
3663 donullchange(); 3663 break;
3664 break; 3664
3665 3665 case changes.VehicleFlags:
3666 default: 3666 changeVehicleFlags((strVehicleBoolParam) arg);
3667 donullchange(); 3667 break;
3668 break; 3668
3669 } 3669 case changes.VehicleFloatParam:
3670 return false; 3670 changeVehicleFloatParam((strVehicleFloatParam) arg);
3671 } 3671 break;
3672 3672
3673 public void AddChange(changes what, object arg) 3673 case changes.VehicleVectorParam:
3674 { 3674 changeVehicleVectorParam((strVehicleVectorParam) arg);
3675 _parent_scene.AddChange((PhysicsActor) this, what, arg); 3675 break;
3676 } 3676
3677 3677 case changes.VehicleRotationParam:
3678 3678 changeVehicleRotationParam((strVehicleQuatParam) arg);
3679 private struct strVehicleBoolParam 3679 break;
3680 { 3680
3681 public int param; 3681 case changes.SetVehicle:
3682 public bool value; 3682 changeSetVehicle((VehicleData) arg);
3683 } 3683 break;
3684 3684 case changes.Null:
3685 private struct strVehicleFloatParam 3685 donullchange();
3686 { 3686 break;
3687 public int param; 3687
3688 public float value; 3688 default:
3689 } 3689 donullchange();
3690 3690 break;
3691 private struct strVehicleQuatParam 3691 }
3692 { 3692 return false;
3693 public int param; 3693 }
3694 public Quaternion value; 3694
3695 } 3695 public void AddChange(changes what, object arg)
3696 3696 {
3697 private struct strVehicleVectorParam 3697 _parent_scene.AddChange((PhysicsActor) this, what, arg);
3698 { 3698 }
3699 public int param; 3699
3700 public Vector3 value; 3700
3701 } 3701 private struct strVehicleBoolParam
3702 } 3702 {
3703 public int param;
3704 public bool value;
3705 }
3706
3707 private struct strVehicleFloatParam
3708 {
3709 public int param;
3710 public float value;
3711 }
3712
3713 private struct strVehicleQuatParam
3714 {
3715 public int param;
3716 public Quaternion value;
3717 }
3718
3719 private struct strVehicleVectorParam
3720 {
3721 public int param;
3722 public Vector3 value;
3723 }
3724 }
3703} \ No newline at end of file 3725} \ No newline at end of file
diff --git a/OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs b/OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs
index 612eafd..76d7746 100644
--- a/OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs
+++ b/OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs
@@ -1141,7 +1141,7 @@ namespace OpenSim.Region.Physics.OdePlugin
1141 OdePrim newPrim; 1141 OdePrim newPrim;
1142 lock (OdeLock) 1142 lock (OdeLock)
1143 { 1143 {
1144 newPrim = new OdePrim(name, this, pos, siz, rot, pbs, isphysical,false,localID); 1144 newPrim = new OdePrim(name, this, pos, siz, rot, pbs, isphysical,false,0,localID);
1145 1145
1146 lock (_prims) 1146 lock (_prims)
1147 _prims.Add(newPrim); 1147 _prims.Add(newPrim);
@@ -1159,7 +1159,25 @@ namespace OpenSim.Region.Physics.OdePlugin
1159 OdePrim newPrim; 1159 OdePrim newPrim;
1160 lock (OdeLock) 1160 lock (OdeLock)
1161 { 1161 {
1162 newPrim = new OdePrim(name, this, pos, siz, rot, pbs, isphysical,isPhantom,localID); 1162 newPrim = new OdePrim(name, this, pos, siz, rot, pbs, isphysical, isPhantom, 0, localID);
1163
1164 lock (_prims)
1165 _prims.Add(newPrim);
1166 }
1167 return newPrim;
1168 }
1169
1170 private PhysicsActor AddPrim(String name, Vector3 position, Vector3 size, Quaternion rotation,
1171 PrimitiveBaseShape pbs, bool isphysical, bool isPhantom, byte shapeType, uint localID)
1172 {
1173 Vector3 pos = position;
1174 Vector3 siz = size;
1175 Quaternion rot = rotation;
1176
1177 OdePrim newPrim;
1178 lock (OdeLock)
1179 {
1180 newPrim = new OdePrim(name, this, pos, siz, rot, pbs, isphysical, isPhantom, shapeType, localID);
1163 1181
1164 lock (_prims) 1182 lock (_prims)
1165 _prims.Add(newPrim); 1183 _prims.Add(newPrim);
@@ -1203,6 +1221,16 @@ namespace OpenSim.Region.Physics.OdePlugin
1203 return AddPrim(primName, position, size, rotation, pbs, isPhysical, localid); 1221 return AddPrim(primName, position, size, rotation, pbs, isPhysical, localid);
1204 } 1222 }
1205 1223
1224 public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position,
1225 Vector3 size, Quaternion rotation, bool isPhysical, bool isPhantom, byte shapeType, uint localid)
1226 {
1227#if SPAM
1228 m_log.DebugFormat("[PHYSICS]: Adding physics actor to {0}", primName);
1229#endif
1230
1231 return AddPrim(primName, position, size, rotation, pbs, isPhysical,isPhantom, shapeType, localid);
1232 }
1233
1206 public override float TimeDilation 1234 public override float TimeDilation
1207 { 1235 {
1208 get { return m_timeDilation; } 1236 get { return m_timeDilation; }