aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPart.cs43
-rw-r--r--OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs7434
2 files changed, 3750 insertions, 3727 deletions
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index a494864..51a3c18 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
@@ -1497,6 +1497,7 @@ namespace OpenSim.Region.Framework.Scenes
1497 get { return m_physicsShapeType; } 1497 get { return m_physicsShapeType; }
1498 set 1498 set
1499 { 1499 {
1500 byte oldv = m_physicsShapeType;
1500 if (value >= 0 && value <= (byte)PhysShapeType.convex) 1501 if (value >= 0 && value <= (byte)PhysShapeType.convex)
1501 { 1502 {
1502 if (value == (byte)PhysShapeType.none && ParentGroup != null && ParentGroup.RootPart == this) 1503 if (value == (byte)PhysShapeType.none && ParentGroup != null && ParentGroup.RootPart == this)
@@ -1507,11 +1508,33 @@ namespace OpenSim.Region.Framework.Scenes
1507 else 1508 else
1508 m_physicsShapeType = DefaultPhysicsShapeType(); 1509 m_physicsShapeType = DefaultPhysicsShapeType();
1509 1510
1510 if (ParentGroup != null)
1511 ParentGroup.HasGroupChanged = true;
1512 1511
1513 if(m_physicsShapeType != value) 1512 if (m_physicsShapeType != oldv && ParentGroup != null)
1513 {
1514 if (m_physicsShapeType == (byte)PhysShapeType.none)
1515 {
1516 if (PhysActor != null)
1517 {
1518 Velocity = new Vector3(0, 0, 0);
1519 Acceleration = new Vector3(0, 0, 0);
1520 if (ParentGroup.RootPart == this)
1521 AngularVelocity = new Vector3(0, 0, 0);
1522 ParentGroup.Scene.RemovePhysicalPrim(1);
1523 RemoveFromPhysics();
1524 }
1525 }
1526 else if (PhysActor == null)
1527 ApplyPhysics((uint)Flags, VolumeDetectActive, false);
1528 else
1529 PhysActor.PhysicsShapeType = m_physicsShapeType;
1530 }
1531 if (m_physicsShapeType != value)
1532 {
1533 if (ParentGroup != null)
1534 ParentGroup.HasGroupChanged = true;
1535
1514 UpdatePhysRequired = true; 1536 UpdatePhysRequired = true;
1537 }
1515 } 1538 }
1516 } 1539 }
1517 1540
@@ -4575,20 +4598,6 @@ namespace OpenSim.Region.Framework.Scenes
4575 { 4598 {
4576 PhysicsShapeType = (byte)physdata.PhysShapeType; 4599 PhysicsShapeType = (byte)physdata.PhysShapeType;
4577 4600
4578 if (PhysicsShapeType == (byte)PhysShapeType.none)
4579 {
4580 if (PhysActor != null)
4581 {
4582 Velocity = new Vector3(0, 0, 0);
4583 Acceleration = new Vector3(0, 0, 0);
4584 if (ParentGroup.RootPart == this)
4585 AngularVelocity = new Vector3(0, 0, 0);
4586 ParentGroup.Scene.RemovePhysicalPrim(1);
4587 RemoveFromPhysics();
4588 }
4589 }
4590 else if (PhysActor == null)
4591 ApplyPhysics((uint)Flags, VolumeDetectActive, false);
4592 } 4601 }
4593 4602
4594 if(Density != physdata.Density) 4603 if(Density != physdata.Density)
diff --git a/OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs
index fd2f88f..71aec4c 100644
--- a/OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs
+++ b/OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs
@@ -1,3711 +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 private byte m_shapetype; 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,byte _shapeType,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_shapetype = _shapeType; 923
924 924 m_isVolumeDetect = false;
925 m_lastdoneSelected = false; 925
926 m_isSelected = false; 926 m_force = Vector3.Zero;
927 m_delaySelect = false; 927
928 928 m_iscolliding = false;
929 m_isphantom = pisPhantom; 929 m_colliderfilter = 0;
930 m_fakeisphantom = pisPhantom; 930 m_softcolide = true;
931 931 m_NoColide = false;
932 mu = parent_scene.m_materialContactsData[(int)Material.Wood].mu; 932
933 bounce = parent_scene.m_materialContactsData[(int)Material.Wood].bounce; 933 hasOOBoffsetFromMesh = false;
934 934 _triMeshData = IntPtr.Zero;
935 CalcPrimBodyData(); 935
936 936 m_shapetype = _shapeType;
937 m_building = true; // control must set this to false when done 937
938 938 m_lastdoneSelected = false;
939 AddChange(changes.Add, null); 939 m_isSelected = false;
940 } 940 m_delaySelect = false;
941 941
942 private void resetCollisionAccounting() 942 m_isphantom = pisPhantom;
943 { 943 m_fakeisphantom = pisPhantom;
944 m_collisionscore = 0; 944
945 } 945 mu = parent_scene.m_materialContactsData[(int)Material.Wood].mu;
946 946 bounce = parent_scene.m_materialContactsData[(int)Material.Wood].bounce;
947 private void createAMotor(Vector3 axis) 947
948 { 948 CalcPrimBodyData();
949 if (Body == IntPtr.Zero) 949
950 return; 950 m_building = true; // control must set this to false when done
951 951
952 if (Amotor != IntPtr.Zero) 952 AddChange(changes.Add, null);
953 { 953 }
954 d.JointDestroy(Amotor); 954
955 Amotor = IntPtr.Zero; 955 private void resetCollisionAccounting()
956 } 956 {
957 957 m_collisionscore = 0;
958 int axisnum = 3 - (int)(axis.X + axis.Y + axis.Z); 958 }
959 959
960 if (axisnum <= 0) 960 private void createAMotor(Vector3 axis)
961 return; 961 {
962 962 if (Body == IntPtr.Zero)
963 // stop it 963 return;
964 d.BodySetTorque(Body, 0, 0, 0); 964
965 d.BodySetAngularVel(Body, 0, 0, 0); 965 if (Amotor != IntPtr.Zero)
966 966 {
967 Amotor = d.JointCreateAMotor(_parent_scene.world, IntPtr.Zero); 967 d.JointDestroy(Amotor);
968 d.JointAttach(Amotor, Body, IntPtr.Zero); 968 Amotor = IntPtr.Zero;
969 969 }
970 d.JointSetAMotorMode(Amotor, 0); 970
971 971 int axisnum = 3 - (int)(axis.X + axis.Y + axis.Z);
972 d.JointSetAMotorNumAxes(Amotor, axisnum); 972
973 973 if (axisnum <= 0)
974 // get current orientation to lock 974 return;
975 975
976 d.Quaternion dcur = d.BodyGetQuaternion(Body); 976 // stop it
977 Quaternion curr; // crap convertion between identical things 977 d.BodySetTorque(Body, 0, 0, 0);
978 curr.X = dcur.X; 978 d.BodySetAngularVel(Body, 0, 0, 0);
979 curr.Y = dcur.Y; 979
980 curr.Z = dcur.Z; 980 Amotor = d.JointCreateAMotor(_parent_scene.world, IntPtr.Zero);
981 curr.W = dcur.W; 981 d.JointAttach(Amotor, Body, IntPtr.Zero);
982 Vector3 ax; 982
983 983 d.JointSetAMotorMode(Amotor, 0);
984 int i = 0; 984
985 int j = 0; 985 d.JointSetAMotorNumAxes(Amotor, axisnum);
986 if (axis.X == 0) 986
987 { 987 // get current orientation to lock
988 ax = (new Vector3(1, 0, 0)) * curr; // rotate world X to current local X 988
989 // ODE should do this with axis relative to body 1 but seems to fail 989 d.Quaternion dcur = d.BodyGetQuaternion(Body);
990 d.JointSetAMotorAxis(Amotor, 0, 0, ax.X, ax.Y, ax.Z); 990 Quaternion curr; // crap convertion between identical things
991 d.JointSetAMotorAngle(Amotor, 0, 0); 991 curr.X = dcur.X;
992 d.JointSetAMotorParam(Amotor, (int)d.JointParam.LoStop, -0.000001f); 992 curr.Y = dcur.Y;
993 d.JointSetAMotorParam(Amotor, (int)d.JointParam.HiStop, 0.000001f); 993 curr.Z = dcur.Z;
994 d.JointSetAMotorParam(Amotor, (int)d.JointParam.Vel, 0); 994 curr.W = dcur.W;
995 d.JointSetAMotorParam(Amotor, (int)d.JointParam.FudgeFactor, 0.0001f); 995 Vector3 ax;
996 d.JointSetAMotorParam(Amotor, (int)d.JointParam.Bounce, 0f); 996
997 d.JointSetAMotorParam(Amotor, (int)d.JointParam.FMax, 5e8f); 997 int i = 0;
998 d.JointSetAMotorParam(Amotor, (int)d.JointParam.StopCFM, 0f); 998 int j = 0;
999 d.JointSetAMotorParam(Amotor, (int)d.JointParam.StopERP, 0.8f); 999 if (axis.X == 0)
1000 i++; 1000 {
1001 j = 256; // move to next axis set 1001 ax = (new Vector3(1, 0, 0)) * curr; // rotate world X to current local X
1002 } 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 if (axis.Y == 0) 1004 d.JointSetAMotorAngle(Amotor, 0, 0);
1005 { 1005 d.JointSetAMotorParam(Amotor, (int)d.JointParam.LoStop, -0.000001f);
1006 ax = (new Vector3(0, 1, 0)) * curr; 1006 d.JointSetAMotorParam(Amotor, (int)d.JointParam.HiStop, 0.000001f);
1007 d.JointSetAMotorAxis(Amotor, i, 0, ax.X, ax.Y, ax.Z); 1007 d.JointSetAMotorParam(Amotor, (int)d.JointParam.Vel, 0);
1008 d.JointSetAMotorAngle(Amotor, i, 0); 1008 d.JointSetAMotorParam(Amotor, (int)d.JointParam.FudgeFactor, 0.0001f);
1009 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.LoStop, -0.000001f); 1009 d.JointSetAMotorParam(Amotor, (int)d.JointParam.Bounce, 0f);
1010 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.HiStop, 0.000001f); 1010 d.JointSetAMotorParam(Amotor, (int)d.JointParam.FMax, 5e8f);
1011 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.Vel, 0); 1011 d.JointSetAMotorParam(Amotor, (int)d.JointParam.StopCFM, 0f);
1012 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.FudgeFactor, 0.0001f); 1012 d.JointSetAMotorParam(Amotor, (int)d.JointParam.StopERP, 0.8f);
1013 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.Bounce, 0f); 1013 i++;
1014 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.FMax, 5e8f); 1014 j = 256; // move to next axis set
1015 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.StopCFM, 0f); 1015 }
1016 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.StopERP, 0.8f); 1016
1017 i++; 1017 if (axis.Y == 0)
1018 j += 256; 1018 {
1019 } 1019 ax = (new Vector3(0, 1, 0)) * curr;
1020 1020 d.JointSetAMotorAxis(Amotor, i, 0, ax.X, ax.Y, ax.Z);
1021 if (axis.Z == 0) 1021 d.JointSetAMotorAngle(Amotor, i, 0);
1022 { 1022 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.LoStop, -0.000001f);
1023 ax = (new Vector3(0, 0, 1)) * curr; 1023 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.HiStop, 0.000001f);
1024 d.JointSetAMotorAxis(Amotor, i, 0, ax.X, ax.Y, ax.Z); 1024 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.Vel, 0);
1025 d.JointSetAMotorAngle(Amotor, i, 0); 1025 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.FudgeFactor, 0.0001f);
1026 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.LoStop, -0.000001f); 1026 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.Bounce, 0f);
1027 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.HiStop, 0.000001f); 1027 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.FMax, 5e8f);
1028 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.Vel, 0); 1028 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.StopCFM, 0f);
1029 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.FudgeFactor, 0.0001f); 1029 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.StopERP, 0.8f);
1030 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.Bounce, 0f); 1030 i++;
1031 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.FMax, 5e8f); 1031 j += 256;
1032 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.StopCFM, 0f); 1032 }
1033 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.StopERP, 0.8f); 1033
1034 } 1034 if (axis.Z == 0)
1035 } 1035 {
1036 1036 ax = (new Vector3(0, 0, 1)) * curr;
1037 private bool setMesh(OdeScene parent_scene) 1037 d.JointSetAMotorAxis(Amotor, i, 0, ax.X, ax.Y, ax.Z);
1038 { 1038 d.JointSetAMotorAngle(Amotor, i, 0);
1039 if (Body != IntPtr.Zero) 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 (childPrim) 1041 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.Vel, 0);
1042 { 1042 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.FudgeFactor, 0.0001f);
1043 if (_parent != null) 1043 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.Bounce, 0f);
1044 { 1044 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.FMax, 5e8f);
1045 OdePrim parent = (OdePrim)_parent; 1045 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.StopCFM, 0f);
1046 parent.ChildDelink(this, false); 1046 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.StopERP, 0.8f);
1047 } 1047 }
1048 } 1048 }
1049 else 1049
1050 { 1050 private bool setMesh(OdeScene parent_scene)
1051 DestroyBody(); 1051 {
1052 } 1052 if (Body != IntPtr.Zero)
1053 } 1053 {
1054 1054 if (childPrim)
1055 bool convex; 1055 {
1056 if (m_shapetype == 0) 1056 if (_parent != null)
1057 convex = false; 1057 {
1058 else 1058 OdePrim parent = (OdePrim)_parent;
1059 convex = true; 1059 parent.ChildDelink(this, false);
1060 1060 }
1061 IMesh mesh = _parent_scene.mesher.CreateMesh(Name, _pbs, _size, (int)LevelOfDetail.High, true,convex); 1061 }
1062 if (mesh == null) 1062 else
1063 { 1063 {
1064 m_log.WarnFormat("[PHYSICS]: CreateMesh Failed on prim {0} at <{1},{2},{3}>.", Name, _position.X, _position.Y, _position.Z); 1064 DestroyBody();
1065 return false; 1065 }
1066 } 1066 }
1067 1067
1068 IntPtr vertices, indices; 1068 bool convex;
1069 int vertexCount, indexCount; 1069 if (m_shapetype == 0)
1070 int vertexStride, triStride; 1070 convex = false;
1071 1071 else
1072 mesh.getVertexListAsPtrToFloatArray(out vertices, out vertexStride, out vertexCount); // Note, that vertices are fixed in unmanaged heap 1072 convex = true;
1073 mesh.getIndexListAsPtrToIntArray(out indices, out triStride, out indexCount); // Also fixed, needs release after usage 1073
1074 1074 IMesh mesh = _parent_scene.mesher.CreateMesh(Name, _pbs, _size, (int)LevelOfDetail.High, true,convex);
1075 if (vertexCount == 0 || indexCount == 0) 1075 if (mesh == null)
1076 { 1076 {
1077 m_log.WarnFormat("[PHYSICS]: Got invalid mesh on prim {0} at <{1},{2},{3}>. mesh UUID {4}", 1077 m_log.WarnFormat("[PHYSICS]: CreateMesh Failed on prim {0} at <{1},{2},{3}>.", Name, _position.X, _position.Y, _position.Z);
1078 Name, _position.X, _position.Y, _position.Z, _pbs.SculptTexture.ToString()); 1078 return false;
1079 mesh.releaseSourceMeshData(); 1079 }
1080 return false; 1080
1081 } 1081 IntPtr vertices, indices;
1082 1082 int vertexCount, indexCount;
1083 primOOBoffset = mesh.GetCentroid(); 1083 int vertexStride, triStride;
1084 hasOOBoffsetFromMesh = true; 1084
1085 1085 mesh.getVertexListAsPtrToFloatArray(out vertices, out vertexStride, out vertexCount); // Note, that vertices are fixed in unmanaged heap
1086 mesh.releaseSourceMeshData(); 1086 mesh.getIndexListAsPtrToIntArray(out indices, out triStride, out indexCount); // Also fixed, needs release after usage
1087 1087
1088 IntPtr geo = IntPtr.Zero; 1088 if (vertexCount == 0 || indexCount == 0)
1089 1089 {
1090 try 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 _triMeshData = d.GeomTriMeshDataCreate(); 1092 mesh.releaseSourceMeshData();
1093 1093 return false;
1094 d.GeomTriMeshDataBuildSimple(_triMeshData, vertices, vertexStride, vertexCount, indices, indexCount, triStride); 1094 }
1095 d.GeomTriMeshDataPreprocess(_triMeshData); 1095
1096 1096 primOOBoffset = mesh.GetCentroid();
1097 _parent_scene.waitForSpaceUnlock(m_targetSpace); 1097 hasOOBoffsetFromMesh = true;
1098 geo = d.CreateTriMesh(m_targetSpace, _triMeshData, null, null, null); 1098
1099 } 1099 mesh.releaseSourceMeshData();
1100 1100
1101 catch (Exception e) 1101 IntPtr geo = IntPtr.Zero;
1102 { 1102
1103 m_log.ErrorFormat("[PHYSICS]: SetGeom Mesh failed for {0} exception: {1}", Name, e); 1103 try
1104 if (_triMeshData != IntPtr.Zero) 1104 {
1105 { 1105 _triMeshData = d.GeomTriMeshDataCreate();
1106 d.GeomTriMeshDataDestroy(_triMeshData); 1106
1107 _triMeshData = IntPtr.Zero; 1107 d.GeomTriMeshDataBuildSimple(_triMeshData, vertices, vertexStride, vertexCount, indices, indexCount, triStride);
1108 } 1108 d.GeomTriMeshDataPreprocess(_triMeshData);
1109 return false; 1109
1110 } 1110 _parent_scene.waitForSpaceUnlock(m_targetSpace);
1111 1111 geo = d.CreateTriMesh(m_targetSpace, _triMeshData, null, null, null);
1112 SetGeom(geo); 1112 }
1113 return true; 1113
1114 } 1114 catch (Exception e)
1115 1115 {
1116 private void SetGeom(IntPtr geom) 1116 m_log.ErrorFormat("[PHYSICS]: SetGeom Mesh failed for {0} exception: {1}", Name, e);
1117 { 1117 if (_triMeshData != IntPtr.Zero)
1118 prim_geom = geom; 1118 {
1119 //Console.WriteLine("SetGeom to " + prim_geom + " for " + Name); 1119 d.GeomTriMeshDataDestroy(_triMeshData);
1120 if (prim_geom != IntPtr.Zero) 1120 _triMeshData = IntPtr.Zero;
1121 { 1121 }
1122 if (m_NoColide) 1122 return false;
1123 { 1123 }
1124 d.GeomSetCategoryBits(prim_geom, 0); 1124
1125 if (m_isphysical) 1125 SetGeom(geo);
1126 { 1126 return true;
1127 d.GeomSetCollideBits(prim_geom, (int)CollisionCategories.Land); 1127 }
1128 } 1128
1129 else 1129 private void SetGeom(IntPtr geom)
1130 { 1130 {
1131 d.GeomSetCollideBits(prim_geom, 0); 1131 prim_geom = geom;
1132 d.GeomDisable(prim_geom); 1132 //Console.WriteLine("SetGeom to " + prim_geom + " for " + Name);
1133 } 1133 if (prim_geom != IntPtr.Zero)
1134 } 1134 {
1135 else 1135 if (m_NoColide)
1136 { 1136 {
1137 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories); 1137 d.GeomSetCategoryBits(prim_geom, 0);
1138 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); 1138 if (m_isphysical)
1139 } 1139 {
1140 1140 d.GeomSetCollideBits(prim_geom, (int)CollisionCategories.Land);
1141 CalcPrimBodyData(); 1141 }
1142 1142 else
1143 _parent_scene.geom_name_map[prim_geom] = Name; 1143 {
1144 _parent_scene.actor_name_map[prim_geom] = this; 1144 d.GeomSetCollideBits(prim_geom, 0);
1145 1145 d.GeomDisable(prim_geom);
1146 } 1146 }
1147 else 1147 }
1148 m_log.Warn("Setting bad Geom"); 1148 else
1149 } 1149 {
1150 1150 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
1151 1151 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
1152 /// <summary> 1152 }
1153 /// Create a geometry for the given mesh in the given target space. 1153
1154 /// </summary> 1154 CalcPrimBodyData();
1155 /// <param name="m_targetSpace"></param> 1155
1156 /// <param name="mesh">If null, then a mesh is used that is based on the profile shape data.</param> 1156 _parent_scene.geom_name_map[prim_geom] = Name;
1157 private void CreateGeom() 1157 _parent_scene.actor_name_map[prim_geom] = this;
1158 { 1158
1159 if (_triMeshData != IntPtr.Zero) 1159 }
1160 { 1160 else
1161 d.GeomTriMeshDataDestroy(_triMeshData); 1161 m_log.Warn("Setting bad Geom");
1162 _triMeshData = IntPtr.Zero; 1162 }
1163 } 1163
1164 1164
1165 bool haveMesh = false; 1165 /// <summary>
1166 hasOOBoffsetFromMesh = false; 1166 /// Create a geometry for the given mesh in the given target space.
1167 m_NoColide = false; 1167 /// </summary>
1168 1168 /// <param name="m_targetSpace"></param>
1169 if (_parent_scene.needsMeshing(_pbs)) 1169 /// <param name="mesh">If null, then a mesh is used that is based on the profile shape data.</param>
1170 { 1170 private void CreateGeom()
1171 haveMesh = setMesh(_parent_scene); // this will give a mesh to non trivial known prims 1171 {
1172 if (!haveMesh) 1172 if (_triMeshData != IntPtr.Zero)
1173 m_NoColide = true; 1173 {
1174 } 1174 d.GeomTriMeshDataDestroy(_triMeshData);
1175 1175 _triMeshData = IntPtr.Zero;
1176 if (!haveMesh) 1176 }
1177 { 1177
1178 if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1 1178 bool haveMesh = false;
1179 && _size.X == _size.Y && _size.Y == _size.Z) 1179 hasOOBoffsetFromMesh = false;
1180 { // it's a sphere 1180 m_NoColide = false;
1181 _parent_scene.waitForSpaceUnlock(m_targetSpace); 1181
1182 try 1182 if (_parent_scene.needsMeshing(_pbs))
1183 { 1183 {
1184 SetGeom(d.CreateSphere(m_targetSpace, _size.X * 0.5f)); 1184 haveMesh = setMesh(_parent_scene); // this will give a mesh to non trivial known prims
1185 } 1185 if (!haveMesh)
1186 catch (Exception e) 1186 m_NoColide = true;
1187 { 1187 }
1188 m_log.WarnFormat("[PHYSICS]: Create sphere failed: {0}", e); 1188
1189 return; 1189 if (!haveMesh)
1190 } 1190 {
1191 } 1191 if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1
1192 else 1192 && _size.X == _size.Y && _size.Y == _size.Z)
1193 {// do it as a box 1193 { // it's a sphere
1194 _parent_scene.waitForSpaceUnlock(m_targetSpace); 1194 _parent_scene.waitForSpaceUnlock(m_targetSpace);
1195 try 1195 try
1196 { 1196 {
1197 //Console.WriteLine(" CreateGeom 4"); 1197 SetGeom(d.CreateSphere(m_targetSpace, _size.X * 0.5f));
1198 SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z)); 1198 }
1199 } 1199 catch (Exception e)
1200 catch (Exception e) 1200 {
1201 { 1201 m_log.WarnFormat("[PHYSICS]: Create sphere failed: {0}", e);
1202 m_log.Warn("[PHYSICS]: Create box failed: {0}", e); 1202 return;
1203 return; 1203 }
1204 } 1204 }
1205 } 1205 else
1206 } 1206 {// do it as a box
1207 } 1207 _parent_scene.waitForSpaceUnlock(m_targetSpace);
1208 1208 try
1209 /// <summary> 1209 {
1210 /// Set a new geometry for this prim. 1210 //Console.WriteLine(" CreateGeom 4");
1211 /// </summary> 1211 SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z));
1212 /// <param name="geom"></param> 1212 }
1213 private void RemoveGeom() 1213 catch (Exception e)
1214 { 1214 {
1215 if (prim_geom != IntPtr.Zero) 1215 m_log.Warn("[PHYSICS]: Create box failed: {0}", e);
1216 { 1216 return;
1217 _parent_scene.geom_name_map.Remove(prim_geom); 1217 }
1218 _parent_scene.actor_name_map.Remove(prim_geom); 1218 }
1219 try 1219 }
1220 { 1220 }
1221 d.GeomDestroy(prim_geom); 1221
1222 if (_triMeshData != IntPtr.Zero) 1222 /// <summary>
1223 { 1223 /// Set a new geometry for this prim.
1224 d.GeomTriMeshDataDestroy(_triMeshData); 1224 /// </summary>
1225 _triMeshData = IntPtr.Zero; 1225 /// <param name="geom"></param>
1226 } 1226 private void RemoveGeom()
1227 } 1227 {
1228 // catch (System.AccessViolationException) 1228 if (prim_geom != IntPtr.Zero)
1229 catch (Exception e) 1229 {
1230 { 1230 _parent_scene.geom_name_map.Remove(prim_geom);
1231 m_log.ErrorFormat("[PHYSICS]: PrimGeom destruction failed for {0} exception {1}", Name, e); 1231 _parent_scene.actor_name_map.Remove(prim_geom);
1232 } 1232 try
1233 1233 {
1234 prim_geom = IntPtr.Zero; 1234 d.GeomDestroy(prim_geom);
1235 } 1235 if (_triMeshData != IntPtr.Zero)
1236 else 1236 {
1237 { 1237 d.GeomTriMeshDataDestroy(_triMeshData);
1238 m_log.ErrorFormat("[PHYSICS]: PrimGeom destruction BAD {0}", Name); 1238 _triMeshData = IntPtr.Zero;
1239 } 1239 }
1240 Body = IntPtr.Zero; 1240 }
1241 hasOOBoffsetFromMesh = false; 1241 // catch (System.AccessViolationException)
1242 CalcPrimBodyData(); 1242 catch (Exception e)
1243 } 1243 {
1244 1244 m_log.ErrorFormat("[PHYSICS]: PrimGeom destruction failed for {0} exception {1}", Name, e);
1245 private void ChildSetGeom(OdePrim odePrim) 1245 }
1246 { 1246
1247 // well.. 1247 prim_geom = IntPtr.Zero;
1248 DestroyBody(); 1248 }
1249 MakeBody(); 1249 else
1250 } 1250 {
1251 1251 m_log.ErrorFormat("[PHYSICS]: PrimGeom destruction BAD {0}", Name);
1252 //sets non physical prim m_targetSpace to right space in spaces grid for static prims 1252 }
1253 // should only be called for non physical prims unless they are becoming non physical 1253 Body = IntPtr.Zero;
1254 private void SetInStaticSpace(OdePrim prim) 1254 hasOOBoffsetFromMesh = false;
1255 { 1255 CalcPrimBodyData();
1256 IntPtr targetSpace = _parent_scene.MoveGeomToStaticSpace(prim.prim_geom, prim._position, prim.m_targetSpace); 1256 }
1257 prim.m_targetSpace = targetSpace; 1257
1258 d.GeomEnable(prim_geom); 1258 private void ChildSetGeom(OdePrim odePrim)
1259 } 1259 {
1260 1260 // well..
1261 public void enableBodySoft() 1261 DestroyBody();
1262 { 1262 MakeBody();
1263 if (!childPrim && !m_isSelected) 1263 }
1264 { 1264
1265 if (m_isphysical && Body != IntPtr.Zero) 1265 //sets non physical prim m_targetSpace to right space in spaces grid for static prims
1266 { 1266 // should only be called for non physical prims unless they are becoming non physical
1267 if (m_isphantom && !m_isVolumeDetect) 1267 private void SetInStaticSpace(OdePrim prim)
1268 { 1268 {
1269 m_collisionCategories = 0; 1269 IntPtr targetSpace = _parent_scene.MoveGeomToStaticSpace(prim.prim_geom, prim._position, prim.m_targetSpace);
1270 m_collisionFlags = CollisionCategories.Land; 1270 prim.m_targetSpace = targetSpace;
1271 } 1271 d.GeomEnable(prim_geom);
1272 else 1272 }
1273 { 1273
1274 m_collisionCategories |= CollisionCategories.Body; 1274 public void enableBodySoft()
1275 m_collisionFlags |= (CollisionCategories.Land | CollisionCategories.Wind); 1275 {
1276 } 1276 if (!childPrim && !m_isSelected)
1277 1277 {
1278 foreach (OdePrim prm in childrenPrim) 1278 if (m_isphysical && Body != IntPtr.Zero)
1279 { 1279 {
1280 prm.m_collisionCategories = m_collisionCategories; 1280 if (m_isphantom && !m_isVolumeDetect)
1281 prm.m_collisionFlags = m_collisionFlags; 1281 {
1282 1282 m_collisionCategories = 0;
1283 if (prm.prim_geom != IntPtr.Zero) 1283 m_collisionFlags = CollisionCategories.Land;
1284 { 1284 }
1285 if (prm.m_NoColide) 1285 else
1286 { 1286 {
1287 d.GeomSetCategoryBits(prm.prim_geom, 0); 1287 m_collisionCategories |= CollisionCategories.Body;
1288 d.GeomSetCollideBits(prm.prim_geom, (int)CollisionCategories.Land); 1288 m_collisionFlags |= (CollisionCategories.Land | CollisionCategories.Wind);
1289 } 1289 }
1290 else 1290
1291 { 1291 foreach (OdePrim prm in childrenPrim)
1292 d.GeomSetCategoryBits(prm.prim_geom, (int)m_collisionCategories); 1292 {
1293 d.GeomSetCollideBits(prm.prim_geom, (int)m_collisionFlags); 1293 prm.m_collisionCategories = m_collisionCategories;
1294 } 1294 prm.m_collisionFlags = m_collisionFlags;
1295 d.GeomEnable(prm.prim_geom); 1295
1296 } 1296 if (prm.prim_geom != IntPtr.Zero)
1297 } 1297 {
1298 1298 if (prm.m_NoColide)
1299 if (prim_geom != IntPtr.Zero) 1299 {
1300 { 1300 d.GeomSetCategoryBits(prm.prim_geom, 0);
1301 if (m_NoColide) 1301 d.GeomSetCollideBits(prm.prim_geom, (int)CollisionCategories.Land);
1302 { 1302 }
1303 d.GeomSetCategoryBits(prim_geom, 0); 1303 else
1304 d.GeomSetCollideBits(prim_geom, (int)CollisionCategories.Land); 1304 {
1305 } 1305 d.GeomSetCategoryBits(prm.prim_geom, (int)m_collisionCategories);
1306 else 1306 d.GeomSetCollideBits(prm.prim_geom, (int)m_collisionFlags);
1307 { 1307 }
1308 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories); 1308 d.GeomEnable(prm.prim_geom);
1309 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); 1309 }
1310 } 1310 }
1311 d.GeomEnable(prim_geom); 1311
1312 } 1312 if (prim_geom != IntPtr.Zero)
1313 d.BodyEnable(Body); 1313 {
1314 } 1314 if (m_NoColide)
1315 } 1315 {
1316 m_disabled = false; 1316 d.GeomSetCategoryBits(prim_geom, 0);
1317 resetCollisionAccounting(); // this sets m_disable to false 1317 d.GeomSetCollideBits(prim_geom, (int)CollisionCategories.Land);
1318 } 1318 }
1319 1319 else
1320 private void disableBodySoft() 1320 {
1321 { 1321 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
1322 m_disabled = true; 1322 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
1323 if (!childPrim) 1323 }
1324 { 1324 d.GeomEnable(prim_geom);
1325 if (m_isphysical && Body != IntPtr.Zero) 1325 }
1326 { 1326 d.BodyEnable(Body);
1327 m_collisionCategories &= ~CollisionCategories.Body; 1327 }
1328 m_collisionFlags &= ~(CollisionCategories.Wind | CollisionCategories.Land); 1328 }
1329 1329 m_disabled = false;
1330 foreach (OdePrim prm in childrenPrim) 1330 resetCollisionAccounting(); // this sets m_disable to false
1331 { 1331 }
1332 prm.m_collisionCategories = m_collisionCategories; 1332
1333 prm.m_collisionFlags = m_collisionFlags; 1333 private void disableBodySoft()
1334 1334 {
1335 if (prm.prim_geom != IntPtr.Zero) 1335 m_disabled = true;
1336 { 1336 if (!childPrim)
1337 if (prm.m_NoColide) 1337 {
1338 { 1338 if (m_isphysical && Body != IntPtr.Zero)
1339 d.GeomSetCategoryBits(prm.prim_geom, 0); 1339 {
1340 d.GeomSetCollideBits(prm.prim_geom, 0); 1340 m_collisionCategories &= ~CollisionCategories.Body;
1341 } 1341 m_collisionFlags &= ~(CollisionCategories.Wind | CollisionCategories.Land);
1342 else 1342
1343 { 1343 foreach (OdePrim prm in childrenPrim)
1344 d.GeomSetCategoryBits(prm.prim_geom, (int)m_collisionCategories); 1344 {
1345 d.GeomSetCollideBits(prm.prim_geom, (int)m_collisionFlags); 1345 prm.m_collisionCategories = m_collisionCategories;
1346 } 1346 prm.m_collisionFlags = m_collisionFlags;
1347 d.GeomDisable(prm.prim_geom); 1347
1348 } 1348 if (prm.prim_geom != IntPtr.Zero)
1349 } 1349 {
1350 1350 if (prm.m_NoColide)
1351 if (prim_geom != IntPtr.Zero) 1351 {
1352 { 1352 d.GeomSetCategoryBits(prm.prim_geom, 0);
1353 if (m_NoColide) 1353 d.GeomSetCollideBits(prm.prim_geom, 0);
1354 { 1354 }
1355 d.GeomSetCategoryBits(prim_geom, 0); 1355 else
1356 d.GeomSetCollideBits(prim_geom, 0); 1356 {
1357 } 1357 d.GeomSetCategoryBits(prm.prim_geom, (int)m_collisionCategories);
1358 else 1358 d.GeomSetCollideBits(prm.prim_geom, (int)m_collisionFlags);
1359 { 1359 }
1360 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories); 1360 d.GeomDisable(prm.prim_geom);
1361 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); 1361 }
1362 } 1362 }
1363 d.GeomDisable(prim_geom); 1363
1364 } 1364 if (prim_geom != IntPtr.Zero)
1365 1365 {
1366 d.BodyDisable(Body); 1366 if (m_NoColide)
1367 } 1367 {
1368 } 1368 d.GeomSetCategoryBits(prim_geom, 0);
1369 } 1369 d.GeomSetCollideBits(prim_geom, 0);
1370 1370 }
1371 private void MakeBody() 1371 else
1372 { 1372 {
1373 if (!m_isphysical) // only physical get bodies 1373 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
1374 return; 1374 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
1375 1375 }
1376 if (childPrim) // child prims don't get bodies; 1376 d.GeomDisable(prim_geom);
1377 return; 1377 }
1378 1378
1379 if (m_building) 1379 d.BodyDisable(Body);
1380 return; 1380 }
1381 1381 }
1382 if (prim_geom == IntPtr.Zero) 1382 }
1383 { 1383
1384 m_log.Warn("[PHYSICS]: Unable to link the linkset. Root has no geom yet"); 1384 private void MakeBody()
1385 return; 1385 {
1386 } 1386 if (!m_isphysical) // only physical get bodies
1387 1387 return;
1388 if (Body != IntPtr.Zero) 1388
1389 { 1389 if (childPrim) // child prims don't get bodies;
1390 d.BodyDestroy(Body); 1390 return;
1391 Body = IntPtr.Zero; 1391
1392 m_log.Warn("[PHYSICS]: MakeBody called having a body"); 1392 if (m_building)
1393 } 1393 return;
1394 1394
1395 1395 if (prim_geom == IntPtr.Zero)
1396 if (d.GeomGetBody(prim_geom) != IntPtr.Zero) 1396 {
1397 { 1397 m_log.Warn("[PHYSICS]: Unable to link the linkset. Root has no geom yet");
1398 d.GeomSetBody(prim_geom, IntPtr.Zero); 1398 return;
1399 m_log.Warn("[PHYSICS]: MakeBody root geom already had a body"); 1399 }
1400 } 1400
1401 1401 if (Body != IntPtr.Zero)
1402 d.Matrix3 mymat = new d.Matrix3(); 1402 {
1403 d.Quaternion myrot = new d.Quaternion(); 1403 d.BodyDestroy(Body);
1404 d.Mass objdmass = new d.Mass { }; 1404 Body = IntPtr.Zero;
1405 1405 m_log.Warn("[PHYSICS]: MakeBody called having a body");
1406 Body = d.BodyCreate(_parent_scene.world); 1406 }
1407 1407
1408 DMassDup(ref primdMass, out objdmass); 1408
1409 1409 if (d.GeomGetBody(prim_geom) != IntPtr.Zero)
1410 // rotate inertia 1410 {
1411 myrot.X = _orientation.X; 1411 d.GeomSetBody(prim_geom, IntPtr.Zero);
1412 myrot.Y = _orientation.Y; 1412 m_log.Warn("[PHYSICS]: MakeBody root geom already had a body");
1413 myrot.Z = _orientation.Z; 1413 }
1414 myrot.W = _orientation.W; 1414
1415 1415 d.Matrix3 mymat = new d.Matrix3();
1416 d.RfromQ(out mymat, ref myrot); 1416 d.Quaternion myrot = new d.Quaternion();
1417 d.MassRotate(ref objdmass, ref mymat); 1417 d.Mass objdmass = new d.Mass { };
1418 1418
1419 // set the body rotation and position 1419 Body = d.BodyCreate(_parent_scene.world);
1420 d.BodySetRotation(Body, ref mymat); 1420
1421 1421 DMassDup(ref primdMass, out objdmass);
1422 // recompute full object inertia if needed 1422
1423 if (childrenPrim.Count > 0) 1423 // rotate inertia
1424 { 1424 myrot.X = _orientation.X;
1425 d.Matrix3 mat = new d.Matrix3(); 1425 myrot.Y = _orientation.Y;
1426 d.Quaternion quat = new d.Quaternion(); 1426 myrot.Z = _orientation.Z;
1427 d.Mass tmpdmass = new d.Mass { }; 1427 myrot.W = _orientation.W;
1428 Vector3 rcm; 1428
1429 1429 d.RfromQ(out mymat, ref myrot);
1430 rcm.X = _position.X + objdmass.c.X; 1430 d.MassRotate(ref objdmass, ref mymat);
1431 rcm.Y = _position.Y + objdmass.c.Y; 1431
1432 rcm.Z = _position.Z + objdmass.c.Z; 1432 // set the body rotation and position
1433 1433 d.BodySetRotation(Body, ref mymat);
1434 lock (childrenPrim) 1434
1435 { 1435 // recompute full object inertia if needed
1436 foreach (OdePrim prm in childrenPrim) 1436 if (childrenPrim.Count > 0)
1437 { 1437 {
1438 if (prm.prim_geom == IntPtr.Zero) 1438 d.Matrix3 mat = new d.Matrix3();
1439 { 1439 d.Quaternion quat = new d.Quaternion();
1440 m_log.Warn("[PHYSICS]: Unable to link one of the linkset elements, skipping it. No geom yet"); 1440 d.Mass tmpdmass = new d.Mass { };
1441 continue; 1441 Vector3 rcm;
1442 } 1442
1443 1443 rcm.X = _position.X + objdmass.c.X;
1444 DMassCopy(ref prm.primdMass, ref tmpdmass); 1444 rcm.Y = _position.Y + objdmass.c.Y;
1445 1445 rcm.Z = _position.Z + objdmass.c.Z;
1446 // apply prim current rotation to inertia 1446
1447 quat.X = prm._orientation.X; 1447 lock (childrenPrim)
1448 quat.Y = prm._orientation.Y; 1448 {
1449 quat.Z = prm._orientation.Z; 1449 foreach (OdePrim prm in childrenPrim)
1450 quat.W = prm._orientation.W; 1450 {
1451 d.RfromQ(out mat, ref quat); 1451 if (prm.prim_geom == IntPtr.Zero)
1452 d.MassRotate(ref tmpdmass, ref mat); 1452 {
1453 1453 m_log.Warn("[PHYSICS]: Unable to link one of the linkset elements, skipping it. No geom yet");
1454 Vector3 ppos = prm._position; 1454 continue;
1455 ppos.X += tmpdmass.c.X - rcm.X; 1455 }
1456 ppos.Y += tmpdmass.c.Y - rcm.Y; 1456
1457 ppos.Z += tmpdmass.c.Z - rcm.Z; 1457 DMassCopy(ref prm.primdMass, ref tmpdmass);
1458 1458
1459 // refer inertia to root prim center of mass position 1459 // apply prim current rotation to inertia
1460 d.MassTranslate(ref tmpdmass, 1460 quat.X = prm._orientation.X;
1461 ppos.X, 1461 quat.Y = prm._orientation.Y;
1462 ppos.Y, 1462 quat.Z = prm._orientation.Z;
1463 ppos.Z); 1463 quat.W = prm._orientation.W;
1464 1464 d.RfromQ(out mat, ref quat);
1465 d.MassAdd(ref objdmass, ref tmpdmass); // add to total object inertia 1465 d.MassRotate(ref tmpdmass, ref mat);
1466 // fix prim colision cats 1466
1467 1467 Vector3 ppos = prm._position;
1468 if (d.GeomGetBody(prm.prim_geom) != IntPtr.Zero) 1468 ppos.X += tmpdmass.c.X - rcm.X;
1469 { 1469 ppos.Y += tmpdmass.c.Y - rcm.Y;
1470 d.GeomSetBody(prm.prim_geom, IntPtr.Zero); 1470 ppos.Z += tmpdmass.c.Z - rcm.Z;
1471 m_log.Warn("[PHYSICS]: MakeBody child geom already had a body"); 1471
1472 } 1472 // refer inertia to root prim center of mass position
1473 1473 d.MassTranslate(ref tmpdmass,
1474 d.GeomClearOffset(prm.prim_geom); 1474 ppos.X,
1475 d.GeomSetBody(prm.prim_geom, Body); 1475 ppos.Y,
1476 prm.Body = Body; 1476 ppos.Z);
1477 d.GeomSetOffsetWorldRotation(prm.prim_geom, ref mat); // set relative rotation 1477
1478 } 1478 d.MassAdd(ref objdmass, ref tmpdmass); // add to total object inertia
1479 } 1479 // fix prim colision cats
1480 } 1480
1481 1481 if (d.GeomGetBody(prm.prim_geom) != IntPtr.Zero)
1482 d.GeomClearOffset(prim_geom); // make sure we don't have a hidden offset 1482 {
1483 // associate root geom with body 1483 d.GeomSetBody(prm.prim_geom, IntPtr.Zero);
1484 d.GeomSetBody(prim_geom, Body); 1484 m_log.Warn("[PHYSICS]: MakeBody child geom already had a body");
1485 1485 }
1486 d.BodySetPosition(Body, _position.X + objdmass.c.X, _position.Y + objdmass.c.Y, _position.Z + objdmass.c.Z); 1486
1487 d.GeomSetOffsetWorldPosition(prim_geom, _position.X, _position.Y, _position.Z); 1487 d.GeomClearOffset(prm.prim_geom);
1488 1488 d.GeomSetBody(prm.prim_geom, Body);
1489 d.MassTranslate(ref objdmass, -objdmass.c.X, -objdmass.c.Y, -objdmass.c.Z); // ode wants inertia at center of body 1489 prm.Body = Body;
1490 myrot.W = -myrot.W; 1490 d.GeomSetOffsetWorldRotation(prm.prim_geom, ref mat); // set relative rotation
1491 d.RfromQ(out mymat, ref myrot); 1491 }
1492 d.MassRotate(ref objdmass, ref mymat); 1492 }
1493 d.BodySetMass(Body, ref objdmass); 1493 }
1494 _mass = objdmass.mass; 1494
1495 1495 d.GeomClearOffset(prim_geom); // make sure we don't have a hidden offset
1496 // disconnect from world gravity so we can apply buoyancy 1496 // associate root geom with body
1497 d.BodySetGravityMode(Body, false); 1497 d.GeomSetBody(prim_geom, Body);
1498 1498
1499 d.BodySetAutoDisableFlag(Body, true); 1499 d.BodySetPosition(Body, _position.X + objdmass.c.X, _position.Y + objdmass.c.Y, _position.Z + objdmass.c.Z);
1500 d.BodySetAutoDisableSteps(Body, body_autodisable_frames); 1500 d.GeomSetOffsetWorldPosition(prim_geom, _position.X, _position.Y, _position.Z);
1501 // d.BodySetLinearDampingThreshold(Body, 0.01f); 1501
1502 // d.BodySetAngularDampingThreshold(Body, 0.001f); 1502 d.MassTranslate(ref objdmass, -objdmass.c.X, -objdmass.c.Y, -objdmass.c.Z); // ode wants inertia at center of body
1503 d.BodySetDamping(Body, .002f, .002f); 1503 myrot.W = -myrot.W;
1504 1504 d.RfromQ(out mymat, ref myrot);
1505 1505 d.MassRotate(ref objdmass, ref mymat);
1506 if (m_targetSpace != IntPtr.Zero) 1506 d.BodySetMass(Body, ref objdmass);
1507 { 1507 _mass = objdmass.mass;
1508 _parent_scene.waitForSpaceUnlock(m_targetSpace); 1508
1509 if (d.SpaceQuery(m_targetSpace, prim_geom)) 1509 // disconnect from world gravity so we can apply buoyancy
1510 d.SpaceRemove(m_targetSpace, prim_geom); 1510 d.BodySetGravityMode(Body, false);
1511 } 1511
1512 1512 d.BodySetAutoDisableFlag(Body, true);
1513 1513 d.BodySetAutoDisableSteps(Body, body_autodisable_frames);
1514 if (childrenPrim.Count == 0) 1514 // d.BodySetLinearDampingThreshold(Body, 0.01f);
1515 { 1515 // d.BodySetAngularDampingThreshold(Body, 0.001f);
1516 collide_geom = prim_geom; 1516 d.BodySetDamping(Body, .002f, .002f);
1517 m_targetSpace = _parent_scene.ActiveSpace; 1517
1518 d.SpaceAdd(m_targetSpace, prim_geom); 1518
1519 } 1519 if (m_targetSpace != IntPtr.Zero)
1520 else 1520 {
1521 { 1521 _parent_scene.waitForSpaceUnlock(m_targetSpace);
1522 m_targetSpace = d.HashSpaceCreate(_parent_scene.ActiveSpace); 1522 if (d.SpaceQuery(m_targetSpace, prim_geom))
1523 d.HashSpaceSetLevels(m_targetSpace, -2, 8); 1523 d.SpaceRemove(m_targetSpace, prim_geom);
1524 d.SpaceSetSublevel(m_targetSpace, 3); 1524 }
1525 d.SpaceSetCleanup(m_targetSpace, false); 1525
1526 d.SpaceAdd(m_targetSpace, prim_geom); 1526
1527 collide_geom = m_targetSpace; 1527 if (childrenPrim.Count == 0)
1528 } 1528 {
1529 1529 collide_geom = prim_geom;
1530 if (m_delaySelect) 1530 m_targetSpace = _parent_scene.ActiveSpace;
1531 { 1531 d.SpaceAdd(m_targetSpace, prim_geom);
1532 m_isSelected = true; 1532 }
1533 m_delaySelect = false; 1533 else
1534 } 1534 {
1535 1535 m_targetSpace = d.HashSpaceCreate(_parent_scene.ActiveSpace);
1536 lock (childrenPrim) 1536 d.HashSpaceSetLevels(m_targetSpace, -2, 8);
1537 { 1537 d.SpaceSetSublevel(m_targetSpace, 3);
1538 foreach (OdePrim prm in childrenPrim) 1538 d.SpaceSetCleanup(m_targetSpace, false);
1539 { 1539 d.SpaceAdd(m_targetSpace, prim_geom);
1540 if (prm.prim_geom == IntPtr.Zero) 1540 collide_geom = m_targetSpace;
1541 continue; 1541 }
1542 1542
1543 Vector3 ppos = prm._position; 1543 if (m_delaySelect)
1544 d.GeomSetOffsetWorldPosition(prm.prim_geom, ppos.X, ppos.Y, ppos.Z); // set relative position 1544 {
1545 1545 m_isSelected = true;
1546 if (prm.m_targetSpace != m_targetSpace) 1546 m_delaySelect = false;
1547 { 1547 }
1548 if (prm.m_targetSpace != IntPtr.Zero) 1548
1549 { 1549 lock (childrenPrim)
1550 _parent_scene.waitForSpaceUnlock(prm.m_targetSpace); 1550 {
1551 if (d.SpaceQuery(prm.m_targetSpace, prm.prim_geom)) 1551 foreach (OdePrim prm in childrenPrim)
1552 d.SpaceRemove(prm.m_targetSpace, prm.prim_geom); 1552 {
1553 } 1553 if (prm.prim_geom == IntPtr.Zero)
1554 prm.m_targetSpace = m_targetSpace; 1554 continue;
1555 d.SpaceAdd(m_targetSpace, prm.prim_geom); 1555
1556 } 1556 Vector3 ppos = prm._position;
1557 1557 d.GeomSetOffsetWorldPosition(prm.prim_geom, ppos.X, ppos.Y, ppos.Z); // set relative position
1558 if (m_isSelected || m_disabled) 1558
1559 { 1559 if (prm.m_targetSpace != m_targetSpace)
1560 prm.m_collisionCategories &= ~CollisionCategories.Body; 1560 {
1561 prm.m_collisionFlags &= ~(CollisionCategories.Land | CollisionCategories.Wind); 1561 if (prm.m_targetSpace != IntPtr.Zero)
1562 d.GeomDisable(prm.prim_geom); 1562 {
1563 } 1563 _parent_scene.waitForSpaceUnlock(prm.m_targetSpace);
1564 else 1564 if (d.SpaceQuery(prm.m_targetSpace, prm.prim_geom))
1565 { 1565 d.SpaceRemove(prm.m_targetSpace, prm.prim_geom);
1566 if (m_isphantom && !m_isVolumeDetect) 1566 }
1567 { 1567 prm.m_targetSpace = m_targetSpace;
1568 prm.m_collisionCategories = 0; 1568 d.SpaceAdd(m_targetSpace, prm.prim_geom);
1569 prm.m_collisionFlags = CollisionCategories.Land; 1569 }
1570 } 1570
1571 else 1571 if (m_isSelected || m_disabled)
1572 { 1572 {
1573 prm.m_collisionCategories |= CollisionCategories.Body; 1573 prm.m_collisionCategories &= ~CollisionCategories.Body;
1574 prm.m_collisionFlags |= (CollisionCategories.Land | CollisionCategories.Wind); 1574 prm.m_collisionFlags &= ~(CollisionCategories.Land | CollisionCategories.Wind);
1575 } 1575 d.GeomDisable(prm.prim_geom);
1576 d.GeomEnable(prm.prim_geom); 1576 }
1577 } 1577 else
1578 1578 {
1579 if (prm.m_NoColide) 1579 if (m_isphantom && !m_isVolumeDetect)
1580 { 1580 {
1581 d.GeomSetCategoryBits(prm.prim_geom, 0); 1581 prm.m_collisionCategories = 0;
1582 d.GeomSetCollideBits(prm.prim_geom, (int)CollisionCategories.Land); 1582 prm.m_collisionFlags = CollisionCategories.Land;
1583 d.GeomEnable(prm.prim_geom); 1583 }
1584 } 1584 else
1585 else 1585 {
1586 { 1586 prm.m_collisionCategories |= CollisionCategories.Body;
1587 d.GeomSetCategoryBits(prm.prim_geom, (int)prm.m_collisionCategories); 1587 prm.m_collisionFlags |= (CollisionCategories.Land | CollisionCategories.Wind);
1588 d.GeomSetCollideBits(prm.prim_geom, (int)prm.m_collisionFlags); 1588 }
1589 } 1589 d.GeomEnable(prm.prim_geom);
1590 prm.m_collisionscore = 0; 1590 }
1591 1591
1592 if(!m_disabled) 1592 if (prm.m_NoColide)
1593 prm.m_disabled = false; 1593 {
1594 1594 d.GeomSetCategoryBits(prm.prim_geom, 0);
1595 _parent_scene.addActivePrim(prm); 1595 d.GeomSetCollideBits(prm.prim_geom, (int)CollisionCategories.Land);
1596 } 1596 d.GeomEnable(prm.prim_geom);
1597 } 1597 }
1598 1598 else
1599 // The body doesn't already have a finite rotation mode set here 1599 {
1600 if ((!m_angularlock.ApproxEquals(Vector3.One, 0.0f)) && _parent == null) 1600 d.GeomSetCategoryBits(prm.prim_geom, (int)prm.m_collisionCategories);
1601 { 1601 d.GeomSetCollideBits(prm.prim_geom, (int)prm.m_collisionFlags);
1602 createAMotor(m_angularlock); 1602 }
1603 } 1603 prm.m_collisionscore = 0;
1604 1604
1605 if (m_isSelected || m_disabled) 1605 if(!m_disabled)
1606 { 1606 prm.m_disabled = false;
1607 m_collisionCategories &= ~CollisionCategories.Body; 1607
1608 m_collisionFlags &= ~(CollisionCategories.Land | CollisionCategories.Wind); 1608 _parent_scene.addActivePrim(prm);
1609 1609 }
1610 d.GeomDisable(prim_geom); 1610 }
1611 d.BodyDisable(Body); 1611
1612 } 1612 // The body doesn't already have a finite rotation mode set here
1613 else 1613 if ((!m_angularlock.ApproxEquals(Vector3.One, 0.0f)) && _parent == null)
1614 { 1614 {
1615 if (m_isphantom && !m_isVolumeDetect) 1615 createAMotor(m_angularlock);
1616 { 1616 }
1617 m_collisionCategories = 0; 1617
1618 m_collisionFlags = CollisionCategories.Land; 1618 if (m_isSelected || m_disabled)
1619 } 1619 {
1620 else 1620 m_collisionCategories &= ~CollisionCategories.Body;
1621 { 1621 m_collisionFlags &= ~(CollisionCategories.Land | CollisionCategories.Wind);
1622 m_collisionCategories |= CollisionCategories.Body; 1622
1623 m_collisionFlags |= (CollisionCategories.Land | CollisionCategories.Wind); 1623 d.GeomDisable(prim_geom);
1624 } 1624 d.BodyDisable(Body);
1625 1625 }
1626 d.BodySetAngularVel(Body, m_rotationalVelocity.X, m_rotationalVelocity.Y, m_rotationalVelocity.Z); 1626 else
1627 d.BodySetLinearVel(Body, _velocity.X, _velocity.Y, _velocity.Z); 1627 {
1628 } 1628 if (m_isphantom && !m_isVolumeDetect)
1629 1629 {
1630 if (m_NoColide) 1630 m_collisionCategories = 0;
1631 { 1631 m_collisionFlags = CollisionCategories.Land;
1632 d.GeomSetCategoryBits(prim_geom, 0); 1632 }
1633 d.GeomSetCollideBits(prim_geom, (int)CollisionCategories.Land); 1633 else
1634 } 1634 {
1635 else 1635 m_collisionCategories |= CollisionCategories.Body;
1636 { 1636 m_collisionFlags |= (CollisionCategories.Land | CollisionCategories.Wind);
1637 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories); 1637 }
1638 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); 1638
1639 } 1639 d.BodySetAngularVel(Body, m_rotationalVelocity.X, m_rotationalVelocity.Y, m_rotationalVelocity.Z);
1640 1640 d.BodySetLinearVel(Body, _velocity.X, _velocity.Y, _velocity.Z);
1641 m_collisionscore = 0; 1641 }
1642 1642
1643 m_softcolide = true; 1643 if (m_NoColide)
1644 _parent_scene.addActivePrim(this); 1644 {
1645 _parent_scene.addActiveGroups(this); 1645 d.GeomSetCategoryBits(prim_geom, 0);
1646 } 1646 d.GeomSetCollideBits(prim_geom, (int)CollisionCategories.Land);
1647 1647 }
1648 private void DestroyBody() 1648 else
1649 { 1649 {
1650 if (Body != IntPtr.Zero) 1650 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
1651 { 1651 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
1652 _parent_scene.remActivePrim(this); 1652 }
1653 m_collisionCategories &= ~CollisionCategories.Body; 1653
1654 m_collisionFlags &= ~(CollisionCategories.Wind | CollisionCategories.Land); 1654 m_collisionscore = 0;
1655 if (prim_geom != IntPtr.Zero) 1655
1656 { 1656 m_softcolide = true;
1657 if (m_NoColide) 1657 _parent_scene.addActivePrim(this);
1658 { 1658 _parent_scene.addActiveGroups(this);
1659 d.GeomSetCategoryBits(prim_geom, 0); 1659 }
1660 d.GeomSetCollideBits(prim_geom, 0); 1660
1661 } 1661 private void DestroyBody()
1662 else 1662 {
1663 { 1663 if (Body != IntPtr.Zero)
1664 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories); 1664 {
1665 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); 1665 _parent_scene.remActivePrim(this);
1666 } 1666 m_collisionCategories &= ~CollisionCategories.Body;
1667 UpdateDataFromGeom(); 1667 m_collisionFlags &= ~(CollisionCategories.Wind | CollisionCategories.Land);
1668 d.GeomSetBody(prim_geom, IntPtr.Zero); 1668 if (prim_geom != IntPtr.Zero)
1669 SetInStaticSpace(this); 1669 {
1670 } 1670 if (m_NoColide)
1671 1671 {
1672 if (!childPrim) 1672 d.GeomSetCategoryBits(prim_geom, 0);
1673 { 1673 d.GeomSetCollideBits(prim_geom, 0);
1674 lock (childrenPrim) 1674 }
1675 { 1675 else
1676 foreach (OdePrim prm in childrenPrim) 1676 {
1677 { 1677 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
1678 _parent_scene.remActivePrim(prm); 1678 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
1679 prm.m_collisionCategories = m_collisionCategories; 1679 }
1680 prm.m_collisionFlags = m_collisionFlags; 1680 UpdateDataFromGeom();
1681 if (prm.prim_geom != IntPtr.Zero) 1681 d.GeomSetBody(prim_geom, IntPtr.Zero);
1682 { 1682 SetInStaticSpace(this);
1683 if (prm.m_NoColide) 1683 }
1684 { 1684
1685 d.GeomSetCategoryBits(prm.prim_geom, 0); 1685 if (!childPrim)
1686 d.GeomSetCollideBits(prm.prim_geom, 0); 1686 {
1687 } 1687 lock (childrenPrim)
1688 else 1688 {
1689 { 1689 foreach (OdePrim prm in childrenPrim)
1690 d.GeomSetCategoryBits(prm.prim_geom, (int)m_collisionCategories); 1690 {
1691 d.GeomSetCollideBits(prm.prim_geom, (int)m_collisionFlags); 1691 _parent_scene.remActivePrim(prm);
1692 } 1692 prm.m_collisionCategories = m_collisionCategories;
1693 prm.UpdateDataFromGeom(); 1693 prm.m_collisionFlags = m_collisionFlags;
1694 SetInStaticSpace(prm); 1694 if (prm.prim_geom != IntPtr.Zero)
1695 } 1695 {
1696 prm.Body = IntPtr.Zero; 1696 if (prm.m_NoColide)
1697 prm._mass = prm.primMass; 1697 {
1698 prm.m_collisionscore = 0; 1698 d.GeomSetCategoryBits(prm.prim_geom, 0);
1699 } 1699 d.GeomSetCollideBits(prm.prim_geom, 0);
1700 } 1700 }
1701 if (Amotor != IntPtr.Zero) 1701 else
1702 { 1702 {
1703 d.JointDestroy(Amotor); 1703 d.GeomSetCategoryBits(prm.prim_geom, (int)m_collisionCategories);
1704 Amotor = IntPtr.Zero; 1704 d.GeomSetCollideBits(prm.prim_geom, (int)m_collisionFlags);
1705 } 1705 }
1706 _parent_scene.remActiveGroup(this); 1706 prm.UpdateDataFromGeom();
1707 d.BodyDestroy(Body); 1707 SetInStaticSpace(prm);
1708 } 1708 }
1709 Body = IntPtr.Zero; 1709 prm.Body = IntPtr.Zero;
1710 } 1710 prm._mass = prm.primMass;
1711 _mass = primMass; 1711 prm.m_collisionscore = 0;
1712 m_collisionscore = 0; 1712 }
1713 } 1713 }
1714 1714 if (Amotor != IntPtr.Zero)
1715 #region Mass Calculation 1715 {
1716 1716 d.JointDestroy(Amotor);
1717 private float CalculatePrimVolume() 1717 Amotor = IntPtr.Zero;
1718 { 1718 }
1719 float volume = _size.X * _size.Y * _size.Z; // default 1719 _parent_scene.remActiveGroup(this);
1720 float tmp; 1720 d.BodyDestroy(Body);
1721 1721 }
1722 float hollowAmount = (float)_pbs.ProfileHollow * 2.0e-5f; 1722 Body = IntPtr.Zero;
1723 float hollowVolume = hollowAmount * hollowAmount; 1723 }
1724 1724 _mass = primMass;
1725 switch (_pbs.ProfileShape) 1725 m_collisionscore = 0;
1726 { 1726 }
1727 case ProfileShape.Square: 1727
1728 // default box 1728 #region Mass Calculation
1729 1729
1730 if (_pbs.PathCurve == (byte)Extrusion.Straight) 1730 private float CalculatePrimVolume()
1731 { 1731 {
1732 if (hollowAmount > 0.0) 1732 float volume = _size.X * _size.Y * _size.Z; // default
1733 { 1733 float tmp;
1734 switch (_pbs.HollowShape) 1734
1735 { 1735 float hollowAmount = (float)_pbs.ProfileHollow * 2.0e-5f;
1736 case HollowShape.Square: 1736 float hollowVolume = hollowAmount * hollowAmount;
1737 case HollowShape.Same: 1737
1738 break; 1738 switch (_pbs.ProfileShape)
1739 1739 {
1740 case HollowShape.Circle: 1740 case ProfileShape.Square:
1741 1741 // default box
1742 hollowVolume *= 0.78539816339f; 1742
1743 break; 1743 if (_pbs.PathCurve == (byte)Extrusion.Straight)
1744 1744 {
1745 case HollowShape.Triangle: 1745 if (hollowAmount > 0.0)
1746 1746 {
1747 hollowVolume *= (0.5f * .5f); 1747 switch (_pbs.HollowShape)
1748 break; 1748 {
1749 1749 case HollowShape.Square:
1750 default: 1750 case HollowShape.Same:
1751 hollowVolume = 0; 1751 break;
1752 break; 1752
1753 } 1753 case HollowShape.Circle:
1754 volume *= (1.0f - hollowVolume); 1754
1755 } 1755 hollowVolume *= 0.78539816339f;
1756 } 1756 break;
1757 1757
1758 else if (_pbs.PathCurve == (byte)Extrusion.Curve1) 1758 case HollowShape.Triangle:
1759 { 1759
1760 //a tube 1760 hollowVolume *= (0.5f * .5f);
1761 1761 break;
1762 volume *= 0.78539816339e-2f * (float)(200 - _pbs.PathScaleX); 1762
1763 tmp = 1.0f - 2.0e-2f * (float)(200 - _pbs.PathScaleY); 1763 default:
1764 volume -= volume * tmp * tmp; 1764 hollowVolume = 0;
1765 1765 break;
1766 if (hollowAmount > 0.0) 1766 }
1767 { 1767 volume *= (1.0f - hollowVolume);
1768 hollowVolume *= hollowAmount; 1768 }
1769 1769 }
1770 switch (_pbs.HollowShape) 1770
1771 { 1771 else if (_pbs.PathCurve == (byte)Extrusion.Curve1)
1772 case HollowShape.Square: 1772 {
1773 case HollowShape.Same: 1773 //a tube
1774 break; 1774
1775 1775 volume *= 0.78539816339e-2f * (float)(200 - _pbs.PathScaleX);
1776 case HollowShape.Circle: 1776 tmp = 1.0f - 2.0e-2f * (float)(200 - _pbs.PathScaleY);
1777 hollowVolume *= 0.78539816339f; 1777 volume -= volume * tmp * tmp;
1778 break; 1778
1779 1779 if (hollowAmount > 0.0)
1780 case HollowShape.Triangle: 1780 {
1781 hollowVolume *= 0.5f * 0.5f; 1781 hollowVolume *= hollowAmount;
1782 break; 1782
1783 default: 1783 switch (_pbs.HollowShape)
1784 hollowVolume = 0; 1784 {
1785 break; 1785 case HollowShape.Square:
1786 } 1786 case HollowShape.Same:
1787 volume *= (1.0f - hollowVolume); 1787 break;
1788 } 1788
1789 } 1789 case HollowShape.Circle:
1790 1790 hollowVolume *= 0.78539816339f;
1791 break; 1791 break;
1792 1792
1793 case ProfileShape.Circle: 1793 case HollowShape.Triangle:
1794 1794 hollowVolume *= 0.5f * 0.5f;
1795 if (_pbs.PathCurve == (byte)Extrusion.Straight) 1795 break;
1796 { 1796 default:
1797 volume *= 0.78539816339f; // elipse base 1797 hollowVolume = 0;
1798 1798 break;
1799 if (hollowAmount > 0.0) 1799 }
1800 { 1800 volume *= (1.0f - hollowVolume);
1801 switch (_pbs.HollowShape) 1801 }
1802 { 1802 }
1803 case HollowShape.Same: 1803
1804 case HollowShape.Circle: 1804 break;
1805 break; 1805
1806 1806 case ProfileShape.Circle:
1807 case HollowShape.Square: 1807
1808 hollowVolume *= 0.5f * 2.5984480504799f; 1808 if (_pbs.PathCurve == (byte)Extrusion.Straight)
1809 break; 1809 {
1810 1810 volume *= 0.78539816339f; // elipse base
1811 case HollowShape.Triangle: 1811
1812 hollowVolume *= .5f * 1.27323954473516f; 1812 if (hollowAmount > 0.0)
1813 break; 1813 {
1814 1814 switch (_pbs.HollowShape)
1815 default: 1815 {
1816 hollowVolume = 0; 1816 case HollowShape.Same:
1817 break; 1817 case HollowShape.Circle:
1818 } 1818 break;
1819 volume *= (1.0f - hollowVolume); 1819
1820 } 1820 case HollowShape.Square:
1821 } 1821 hollowVolume *= 0.5f * 2.5984480504799f;
1822 1822 break;
1823 else if (_pbs.PathCurve == (byte)Extrusion.Curve1) 1823
1824 { 1824 case HollowShape.Triangle:
1825 volume *= 0.61685027506808491367715568749226e-2f * (float)(200 - _pbs.PathScaleX); 1825 hollowVolume *= .5f * 1.27323954473516f;
1826 tmp = 1.0f - .02f * (float)(200 - _pbs.PathScaleY); 1826 break;
1827 volume *= (1.0f - tmp * tmp); 1827
1828 1828 default:
1829 if (hollowAmount > 0.0) 1829 hollowVolume = 0;
1830 { 1830 break;
1831 1831 }
1832 // calculate the hollow volume by it's shape compared to the prim shape 1832 volume *= (1.0f - hollowVolume);
1833 hollowVolume *= hollowAmount; 1833 }
1834 1834 }
1835 switch (_pbs.HollowShape) 1835
1836 { 1836 else if (_pbs.PathCurve == (byte)Extrusion.Curve1)
1837 case HollowShape.Same: 1837 {
1838 case HollowShape.Circle: 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 case HollowShape.Square: 1841
1842 hollowVolume *= 0.5f * 2.5984480504799f; 1842 if (hollowAmount > 0.0)
1843 break; 1843 {
1844 1844
1845 case HollowShape.Triangle: 1845 // calculate the hollow volume by it's shape compared to the prim shape
1846 hollowVolume *= .5f * 1.27323954473516f; 1846 hollowVolume *= hollowAmount;
1847 break; 1847
1848 1848 switch (_pbs.HollowShape)
1849 default: 1849 {
1850 hollowVolume = 0; 1850 case HollowShape.Same:
1851 break; 1851 case HollowShape.Circle:
1852 } 1852 break;
1853 volume *= (1.0f - hollowVolume); 1853
1854 } 1854 case HollowShape.Square:
1855 } 1855 hollowVolume *= 0.5f * 2.5984480504799f;
1856 break; 1856 break;
1857 1857
1858 case ProfileShape.HalfCircle: 1858 case HollowShape.Triangle:
1859 if (_pbs.PathCurve == (byte)Extrusion.Curve1) 1859 hollowVolume *= .5f * 1.27323954473516f;
1860 { 1860 break;
1861 volume *= 0.52359877559829887307710723054658f; 1861
1862 } 1862 default:
1863 break; 1863 hollowVolume = 0;
1864 1864 break;
1865 case ProfileShape.EquilateralTriangle: 1865 }
1866 1866 volume *= (1.0f - hollowVolume);
1867 if (_pbs.PathCurve == (byte)Extrusion.Straight) 1867 }
1868 { 1868 }
1869 volume *= 0.32475953f; 1869 break;
1870 1870
1871 if (hollowAmount > 0.0) 1871 case ProfileShape.HalfCircle:
1872 { 1872 if (_pbs.PathCurve == (byte)Extrusion.Curve1)
1873 1873 {
1874 // calculate the hollow volume by it's shape compared to the prim shape 1874 volume *= 0.52359877559829887307710723054658f;
1875 switch (_pbs.HollowShape) 1875 }
1876 { 1876 break;
1877 case HollowShape.Same: 1877
1878 case HollowShape.Triangle: 1878 case ProfileShape.EquilateralTriangle:
1879 hollowVolume *= .25f; 1879
1880 break; 1880 if (_pbs.PathCurve == (byte)Extrusion.Straight)
1881 1881 {
1882 case HollowShape.Square: 1882 volume *= 0.32475953f;
1883 hollowVolume *= 0.499849f * 3.07920140172638f; 1883
1884 break; 1884 if (hollowAmount > 0.0)
1885 1885 {
1886 case HollowShape.Circle: 1886
1887 // Hollow shape is a perfect cyllinder in respect to the cube's scale 1887 // calculate the hollow volume by it's shape compared to the prim shape
1888 // Cyllinder hollow volume calculation 1888 switch (_pbs.HollowShape)
1889 1889 {
1890 hollowVolume *= 0.1963495f * 3.07920140172638f; 1890 case HollowShape.Same:
1891 break; 1891 case HollowShape.Triangle:
1892 1892 hollowVolume *= .25f;
1893 default: 1893 break;
1894 hollowVolume = 0; 1894
1895 break; 1895 case HollowShape.Square:
1896 } 1896 hollowVolume *= 0.499849f * 3.07920140172638f;
1897 volume *= (1.0f - hollowVolume); 1897 break;
1898 } 1898
1899 } 1899 case HollowShape.Circle:
1900 else if (_pbs.PathCurve == (byte)Extrusion.Curve1) 1900 // Hollow shape is a perfect cyllinder in respect to the cube's scale
1901 { 1901 // Cyllinder hollow volume calculation
1902 volume *= 0.32475953f; 1902
1903 volume *= 0.01f * (float)(200 - _pbs.PathScaleX); 1903 hollowVolume *= 0.1963495f * 3.07920140172638f;
1904 tmp = 1.0f - .02f * (float)(200 - _pbs.PathScaleY); 1904 break;
1905 volume *= (1.0f - tmp * tmp); 1905
1906 1906 default:
1907 if (hollowAmount > 0.0) 1907 hollowVolume = 0;
1908 { 1908 break;
1909 1909 }
1910 hollowVolume *= hollowAmount; 1910 volume *= (1.0f - hollowVolume);
1911 1911 }
1912 switch (_pbs.HollowShape) 1912 }
1913 { 1913 else if (_pbs.PathCurve == (byte)Extrusion.Curve1)
1914 case HollowShape.Same: 1914 {
1915 case HollowShape.Triangle: 1915 volume *= 0.32475953f;
1916 hollowVolume *= .25f; 1916 volume *= 0.01f * (float)(200 - _pbs.PathScaleX);
1917 break; 1917 tmp = 1.0f - .02f * (float)(200 - _pbs.PathScaleY);
1918 1918 volume *= (1.0f - tmp * tmp);
1919 case HollowShape.Square: 1919
1920 hollowVolume *= 0.499849f * 3.07920140172638f; 1920 if (hollowAmount > 0.0)
1921 break; 1921 {
1922 1922
1923 case HollowShape.Circle: 1923 hollowVolume *= hollowAmount;
1924 1924
1925 hollowVolume *= 0.1963495f * 3.07920140172638f; 1925 switch (_pbs.HollowShape)
1926 break; 1926 {
1927 1927 case HollowShape.Same:
1928 default: 1928 case HollowShape.Triangle:
1929 hollowVolume = 0; 1929 hollowVolume *= .25f;
1930 break; 1930 break;
1931 } 1931
1932 volume *= (1.0f - hollowVolume); 1932 case HollowShape.Square:
1933 } 1933 hollowVolume *= 0.499849f * 3.07920140172638f;
1934 } 1934 break;
1935 break; 1935
1936 1936 case HollowShape.Circle:
1937 default: 1937
1938 break; 1938 hollowVolume *= 0.1963495f * 3.07920140172638f;
1939 } 1939 break;
1940 1940
1941 float taperX1; 1941 default:
1942 float taperY1; 1942 hollowVolume = 0;
1943 float taperX; 1943 break;
1944 float taperY; 1944 }
1945 float pathBegin; 1945 volume *= (1.0f - hollowVolume);
1946 float pathEnd; 1946 }
1947 float profileBegin; 1947 }
1948 float profileEnd; 1948 break;
1949 1949
1950 if (_pbs.PathCurve == (byte)Extrusion.Straight || _pbs.PathCurve == (byte)Extrusion.Flexible) 1950 default:
1951 { 1951 break;
1952 taperX1 = _pbs.PathScaleX * 0.01f; 1952 }
1953 if (taperX1 > 1.0f) 1953
1954 taperX1 = 2.0f - taperX1; 1954 float taperX1;
1955 taperX = 1.0f - taperX1; 1955 float taperY1;
1956 1956 float taperX;
1957 taperY1 = _pbs.PathScaleY * 0.01f; 1957 float taperY;
1958 if (taperY1 > 1.0f) 1958 float pathBegin;
1959 taperY1 = 2.0f - taperY1; 1959 float pathEnd;
1960 taperY = 1.0f - taperY1; 1960 float profileBegin;
1961 } 1961 float profileEnd;
1962 else 1962
1963 { 1963 if (_pbs.PathCurve == (byte)Extrusion.Straight || _pbs.PathCurve == (byte)Extrusion.Flexible)
1964 taperX = _pbs.PathTaperX * 0.01f; 1964 {
1965 if (taperX < 0.0f) 1965 taperX1 = _pbs.PathScaleX * 0.01f;
1966 taperX = -taperX; 1966 if (taperX1 > 1.0f)
1967 taperX1 = 1.0f - taperX; 1967 taperX1 = 2.0f - taperX1;
1968 1968 taperX = 1.0f - taperX1;
1969 taperY = _pbs.PathTaperY * 0.01f; 1969
1970 if (taperY < 0.0f) 1970 taperY1 = _pbs.PathScaleY * 0.01f;
1971 taperY = -taperY; 1971 if (taperY1 > 1.0f)
1972 taperY1 = 1.0f - taperY; 1972 taperY1 = 2.0f - taperY1;
1973 } 1973 taperY = 1.0f - taperY1;
1974 1974 }
1975 volume *= (taperX1 * taperY1 + 0.5f * (taperX1 * taperY + taperX * taperY1) + 0.3333333333f * taperX * taperY); 1975 else
1976 1976 {
1977 pathBegin = (float)_pbs.PathBegin * 2.0e-5f; 1977 taperX = _pbs.PathTaperX * 0.01f;
1978 pathEnd = 1.0f - (float)_pbs.PathEnd * 2.0e-5f; 1978 if (taperX < 0.0f)
1979 volume *= (pathEnd - pathBegin); 1979 taperX = -taperX;
1980 1980 taperX1 = 1.0f - taperX;
1981 // this is crude aproximation 1981
1982 profileBegin = (float)_pbs.ProfileBegin * 2.0e-5f; 1982 taperY = _pbs.PathTaperY * 0.01f;
1983 profileEnd = 1.0f - (float)_pbs.ProfileEnd * 2.0e-5f; 1983 if (taperY < 0.0f)
1984 volume *= (profileEnd - profileBegin); 1984 taperY = -taperY;
1985 1985 taperY1 = 1.0f - taperY;
1986 return volume; 1986 }
1987 } 1987
1988 1988 volume *= (taperX1 * taperY1 + 0.5f * (taperX1 * taperY + taperX * taperY1) + 0.3333333333f * taperX * taperY);
1989 1989
1990 private void CalcPrimBodyData() 1990 pathBegin = (float)_pbs.PathBegin * 2.0e-5f;
1991 { 1991 pathEnd = 1.0f - (float)_pbs.PathEnd * 2.0e-5f;
1992 float volume; 1992 volume *= (pathEnd - pathBegin);
1993 1993
1994 if (prim_geom == IntPtr.Zero) 1994 // this is crude aproximation
1995 { 1995 profileBegin = (float)_pbs.ProfileBegin * 2.0e-5f;
1996 // Ubit let's have a initial basic OOB 1996 profileEnd = 1.0f - (float)_pbs.ProfileEnd * 2.0e-5f;
1997 primOOBsize.X = _size.X; 1997 volume *= (profileEnd - profileBegin);
1998 primOOBsize.Y = _size.Y; 1998
1999 primOOBsize.Z = _size.Z; 1999 return volume;
2000 primOOBoffset = Vector3.Zero; 2000 }
2001 } 2001
2002 else 2002
2003 { 2003 private void CalcPrimBodyData()
2004 d.AABB AABB; 2004 {
2005 d.GeomGetAABB(prim_geom, out AABB); // get the AABB from engine geom 2005 float volume;
2006 2006
2007 primOOBsize.X = (AABB.MaxX - AABB.MinX); 2007 if (prim_geom == IntPtr.Zero)
2008 primOOBsize.Y = (AABB.MaxY - AABB.MinY); 2008 {
2009 primOOBsize.Z = (AABB.MaxZ - AABB.MinZ); 2009 // Ubit let's have a initial basic OOB
2010 if (!hasOOBoffsetFromMesh) 2010 primOOBsize.X = _size.X;
2011 { 2011 primOOBsize.Y = _size.Y;
2012 primOOBoffset.X = (AABB.MaxX + AABB.MinX) * 0.5f; 2012 primOOBsize.Z = _size.Z;
2013 primOOBoffset.Y = (AABB.MaxY + AABB.MinY) * 0.5f; 2013 primOOBoffset = Vector3.Zero;
2014 primOOBoffset.Z = (AABB.MaxZ + AABB.MinZ) * 0.5f; 2014 }
2015 } 2015 else
2016 } 2016 {
2017 2017 d.AABB AABB;
2018 // also its own inertia and mass 2018 d.GeomGetAABB(prim_geom, out AABB); // get the AABB from engine geom
2019 // keep using basic shape mass for now 2019
2020 volume = CalculatePrimVolume(); 2020 primOOBsize.X = (AABB.MaxX - AABB.MinX);
2021 2021 primOOBsize.Y = (AABB.MaxY - AABB.MinY);
2022 primMass = m_density * volume; 2022 primOOBsize.Z = (AABB.MaxZ - AABB.MinZ);
2023 2023 if (!hasOOBoffsetFromMesh)
2024 if (primMass <= 0) 2024 {
2025 primMass = 0.0001f;//ckrinke: Mass must be greater then zero. 2025 primOOBoffset.X = (AABB.MaxX + AABB.MinX) * 0.5f;
2026 if (primMass > _parent_scene.maximumMassObject) 2026 primOOBoffset.Y = (AABB.MaxY + AABB.MinY) * 0.5f;
2027 primMass = _parent_scene.maximumMassObject; 2027 primOOBoffset.Z = (AABB.MaxZ + AABB.MinZ) * 0.5f;
2028 2028 }
2029 _mass = primMass; // just in case 2029 }
2030 2030
2031 d.MassSetBoxTotal(out primdMass, primMass, primOOBsize.X, primOOBsize.Y, primOOBsize.Z); 2031 // also its own inertia and mass
2032 2032 // keep using basic shape mass for now
2033 d.MassTranslate(ref primdMass, 2033 volume = CalculatePrimVolume();
2034 primOOBoffset.X, 2034
2035 primOOBoffset.Y, 2035 primMass = m_density * volume;
2036 primOOBoffset.Z); 2036
2037 2037 if (primMass <= 0)
2038 primOOBsize *= 0.5f; // let obb size be a corner coords 2038 primMass = 0.0001f;//ckrinke: Mass must be greater then zero.
2039 primOOBradiusSQ = primOOBsize.LengthSquared(); 2039 if (primMass > _parent_scene.maximumMassObject)
2040 } 2040 primMass = _parent_scene.maximumMassObject;
2041 2041
2042 2042 _mass = primMass; // just in case
2043 #endregion 2043
2044 2044 d.MassSetBoxTotal(out primdMass, primMass, primOOBsize.X, primOOBsize.Y, primOOBsize.Z);
2045 2045
2046 /// <summary> 2046 d.MassTranslate(ref primdMass,
2047 /// Add a child prim to this parent prim. 2047 primOOBoffset.X,
2048 /// </summary> 2048 primOOBoffset.Y,
2049 /// <param name="prim">Child prim</param> 2049 primOOBoffset.Z);
2050 // I'm the parent 2050
2051 // prim is the child 2051 primOOBsize *= 0.5f; // let obb size be a corner coords
2052 public void ParentPrim(OdePrim prim) 2052 primOOBradiusSQ = primOOBsize.LengthSquared();
2053 { 2053 }
2054 //Console.WriteLine("ParentPrim " + m_primName); 2054
2055 if (this.m_localID != prim.m_localID) 2055
2056 { 2056 #endregion
2057 DestroyBody(); // for now we need to rebuil entire object on link change 2057
2058 2058
2059 lock (childrenPrim) 2059 /// <summary>
2060 { 2060 /// Add a child prim to this parent prim.
2061 // adopt the prim 2061 /// </summary>
2062 if (!childrenPrim.Contains(prim)) 2062 /// <param name="prim">Child prim</param>
2063 childrenPrim.Add(prim); 2063 // I'm the parent
2064 2064 // prim is the child
2065 // see if this prim has kids and adopt them also 2065 public void ParentPrim(OdePrim prim)
2066 // should not happen for now 2066 {
2067 foreach (OdePrim prm in prim.childrenPrim) 2067 //Console.WriteLine("ParentPrim " + m_primName);
2068 { 2068 if (this.m_localID != prim.m_localID)
2069 if (!childrenPrim.Contains(prm)) 2069 {
2070 { 2070 DestroyBody(); // for now we need to rebuil entire object on link change
2071 if (prm.Body != IntPtr.Zero) 2071
2072 { 2072 lock (childrenPrim)
2073 if (prm.prim_geom != IntPtr.Zero) 2073 {
2074 d.GeomSetBody(prm.prim_geom, IntPtr.Zero); 2074 // adopt the prim
2075 if (prm.Body != prim.Body) 2075 if (!childrenPrim.Contains(prim))
2076 prm.DestroyBody(); // don't loose bodies around 2076 childrenPrim.Add(prim);
2077 prm.Body = IntPtr.Zero; 2077
2078 } 2078 // see if this prim has kids and adopt them also
2079 2079 // should not happen for now
2080 childrenPrim.Add(prm); 2080 foreach (OdePrim prm in prim.childrenPrim)
2081 prm._parent = this; 2081 {
2082 } 2082 if (!childrenPrim.Contains(prm))
2083 } 2083 {
2084 } 2084 if (prm.Body != IntPtr.Zero)
2085 //Remove old children from the prim 2085 {
2086 prim.childrenPrim.Clear(); 2086 if (prm.prim_geom != IntPtr.Zero)
2087 2087 d.GeomSetBody(prm.prim_geom, IntPtr.Zero);
2088 if (prim.Body != IntPtr.Zero) 2088 if (prm.Body != prim.Body)
2089 { 2089 prm.DestroyBody(); // don't loose bodies around
2090 if (prim.prim_geom != IntPtr.Zero) 2090 prm.Body = IntPtr.Zero;
2091 d.GeomSetBody(prim.prim_geom, IntPtr.Zero); 2091 }
2092 prim.DestroyBody(); // don't loose bodies around 2092
2093 prim.Body = IntPtr.Zero; 2093 childrenPrim.Add(prm);
2094 } 2094 prm._parent = this;
2095 2095 }
2096 prim.childPrim = true; 2096 }
2097 prim._parent = this; 2097 }
2098 2098 //Remove old children from the prim
2099 MakeBody(); // full nasty reconstruction 2099 prim.childrenPrim.Clear();
2100 } 2100
2101 } 2101 if (prim.Body != IntPtr.Zero)
2102 2102 {
2103 private void UpdateChildsfromgeom() 2103 if (prim.prim_geom != IntPtr.Zero)
2104 { 2104 d.GeomSetBody(prim.prim_geom, IntPtr.Zero);
2105 if (childrenPrim.Count > 0) 2105 prim.DestroyBody(); // don't loose bodies around
2106 { 2106 prim.Body = IntPtr.Zero;
2107 foreach (OdePrim prm in childrenPrim) 2107 }
2108 prm.UpdateDataFromGeom(); 2108
2109 } 2109 prim.childPrim = true;
2110 } 2110 prim._parent = this;
2111 2111
2112 private void UpdateDataFromGeom() 2112 MakeBody(); // full nasty reconstruction
2113 { 2113 }
2114 if (prim_geom != IntPtr.Zero) 2114 }
2115 { 2115
2116 d.Vector3 lpos; 2116 private void UpdateChildsfromgeom()
2117 d.GeomCopyPosition(prim_geom, out lpos); 2117 {
2118 _position.X = lpos.X; 2118 if (childrenPrim.Count > 0)
2119 _position.Y = lpos.Y; 2119 {
2120 _position.Z = lpos.Z; 2120 foreach (OdePrim prm in childrenPrim)
2121 d.Quaternion qtmp = new d.Quaternion { }; 2121 prm.UpdateDataFromGeom();
2122 d.GeomCopyQuaternion(prim_geom, out qtmp); 2122 }
2123 _orientation.W = qtmp.W; 2123 }
2124 _orientation.X = qtmp.X; 2124
2125 _orientation.Y = qtmp.Y; 2125 private void UpdateDataFromGeom()
2126 _orientation.Z = qtmp.Z; 2126 {
2127 } 2127 if (prim_geom != IntPtr.Zero)
2128 } 2128 {
2129 2129 d.Vector3 lpos;
2130 private void ChildDelink(OdePrim odePrim, bool remakebodies) 2130 d.GeomCopyPosition(prim_geom, out lpos);
2131 { 2131 _position.X = lpos.X;
2132 // Okay, we have a delinked child.. destroy all body and remake 2132 _position.Y = lpos.Y;
2133 if (odePrim != this && !childrenPrim.Contains(odePrim)) 2133 _position.Z = lpos.Z;
2134 return; 2134 d.Quaternion qtmp = new d.Quaternion { };
2135 2135 d.GeomCopyQuaternion(prim_geom, out qtmp);
2136 DestroyBody(); 2136 _orientation.W = qtmp.W;
2137 2137 _orientation.X = qtmp.X;
2138 if (odePrim == this) // delinking the root prim 2138 _orientation.Y = qtmp.Y;
2139 { 2139 _orientation.Z = qtmp.Z;
2140 OdePrim newroot = null; 2140 }
2141 lock (childrenPrim) 2141 }
2142 { 2142
2143 if (childrenPrim.Count > 0) 2143 private void ChildDelink(OdePrim odePrim, bool remakebodies)
2144 { 2144 {
2145 newroot = childrenPrim[0]; 2145 // Okay, we have a delinked child.. destroy all body and remake
2146 childrenPrim.RemoveAt(0); 2146 if (odePrim != this && !childrenPrim.Contains(odePrim))
2147 foreach (OdePrim prm in childrenPrim) 2147 return;
2148 { 2148
2149 newroot.childrenPrim.Add(prm); 2149 DestroyBody();
2150 } 2150
2151 childrenPrim.Clear(); 2151 if (odePrim == this) // delinking the root prim
2152 } 2152 {
2153 if (newroot != null) 2153 OdePrim newroot = null;
2154 { 2154 lock (childrenPrim)
2155 newroot.childPrim = false; 2155 {
2156 newroot._parent = null; 2156 if (childrenPrim.Count > 0)
2157 if (remakebodies) 2157 {
2158 newroot.MakeBody(); 2158 newroot = childrenPrim[0];
2159 } 2159 childrenPrim.RemoveAt(0);
2160 } 2160 foreach (OdePrim prm in childrenPrim)
2161 } 2161 {
2162 2162 newroot.childrenPrim.Add(prm);
2163 else 2163 }
2164 { 2164 childrenPrim.Clear();
2165 lock (childrenPrim) 2165 }
2166 { 2166 if (newroot != null)
2167 childrenPrim.Remove(odePrim); 2167 {
2168 odePrim.childPrim = false; 2168 newroot.childPrim = false;
2169 odePrim._parent = null; 2169 newroot._parent = null;
2170 // odePrim.UpdateDataFromGeom(); 2170 if (remakebodies)
2171 if (remakebodies) 2171 newroot.MakeBody();
2172 odePrim.MakeBody(); 2172 }
2173 } 2173 }
2174 } 2174 }
2175 if (remakebodies) 2175
2176 MakeBody(); 2176 else
2177 } 2177 {
2178 2178 lock (childrenPrim)
2179 protected void ChildRemove(OdePrim odePrim, bool reMakeBody) 2179 {
2180 { 2180 childrenPrim.Remove(odePrim);
2181 // Okay, we have a delinked child.. destroy all body and remake 2181 odePrim.childPrim = false;
2182 if (odePrim != this && !childrenPrim.Contains(odePrim)) 2182 odePrim._parent = null;
2183 return; 2183 // odePrim.UpdateDataFromGeom();
2184 2184 if (remakebodies)
2185 DestroyBody(); 2185 odePrim.MakeBody();
2186 2186 }
2187 if (odePrim == this) 2187 }
2188 { 2188 if (remakebodies)
2189 OdePrim newroot = null; 2189 MakeBody();
2190 lock (childrenPrim) 2190 }
2191 { 2191
2192 if (childrenPrim.Count > 0) 2192 protected void ChildRemove(OdePrim odePrim, bool reMakeBody)
2193 { 2193 {
2194 newroot = childrenPrim[0]; 2194 // Okay, we have a delinked child.. destroy all body and remake
2195 childrenPrim.RemoveAt(0); 2195 if (odePrim != this && !childrenPrim.Contains(odePrim))
2196 foreach (OdePrim prm in childrenPrim) 2196 return;
2197 { 2197
2198 newroot.childrenPrim.Add(prm); 2198 DestroyBody();
2199 } 2199
2200 childrenPrim.Clear(); 2200 if (odePrim == this)
2201 } 2201 {
2202 if (newroot != null) 2202 OdePrim newroot = null;
2203 { 2203 lock (childrenPrim)
2204 newroot.childPrim = false; 2204 {
2205 newroot._parent = null; 2205 if (childrenPrim.Count > 0)
2206 newroot.MakeBody(); 2206 {
2207 } 2207 newroot = childrenPrim[0];
2208 } 2208 childrenPrim.RemoveAt(0);
2209 if (reMakeBody) 2209 foreach (OdePrim prm in childrenPrim)
2210 MakeBody(); 2210 {
2211 return; 2211 newroot.childrenPrim.Add(prm);
2212 } 2212 }
2213 else 2213 childrenPrim.Clear();
2214 { 2214 }
2215 lock (childrenPrim) 2215 if (newroot != null)
2216 { 2216 {
2217 childrenPrim.Remove(odePrim); 2217 newroot.childPrim = false;
2218 odePrim.childPrim = false; 2218 newroot._parent = null;
2219 odePrim._parent = null; 2219 newroot.MakeBody();
2220 if (reMakeBody) 2220 }
2221 odePrim.MakeBody(); 2221 }
2222 } 2222 if (reMakeBody)
2223 } 2223 MakeBody();
2224 MakeBody(); 2224 return;
2225 } 2225 }
2226 2226 else
2227 #region changes 2227 {
2228 2228 lock (childrenPrim)
2229 private void changeadd() 2229 {
2230 { 2230 childrenPrim.Remove(odePrim);
2231 CreateGeom(); 2231 odePrim.childPrim = false;
2232 2232 odePrim._parent = null;
2233 if (prim_geom != IntPtr.Zero) 2233 if (reMakeBody)
2234 { 2234 odePrim.MakeBody();
2235 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z); 2235 }
2236 d.Quaternion myrot = new d.Quaternion(); 2236 }
2237 myrot.X = _orientation.X; 2237 MakeBody();
2238 myrot.Y = _orientation.Y; 2238 }
2239 myrot.Z = _orientation.Z; 2239
2240 myrot.W = _orientation.W; 2240 #region changes
2241 d.GeomSetQuaternion(prim_geom, ref myrot); 2241
2242 2242 private void changeadd()
2243 if (!m_isphysical) 2243 {
2244 SetInStaticSpace(this); 2244 CreateGeom();
2245 } 2245
2246 2246 if (prim_geom != IntPtr.Zero)
2247 if (m_isphysical && Body == IntPtr.Zero) 2247 {
2248 { 2248 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
2249 MakeBody(); 2249 d.Quaternion myrot = new d.Quaternion();
2250 } 2250 myrot.X = _orientation.X;
2251 } 2251 myrot.Y = _orientation.Y;
2252 2252 myrot.Z = _orientation.Z;
2253 private void changeAngularLock(Vector3 newLock) 2253 myrot.W = _orientation.W;
2254 { 2254 d.GeomSetQuaternion(prim_geom, ref myrot);
2255 // do we have a Physical object? 2255
2256 if (Body != IntPtr.Zero) 2256 if (!m_isphysical)
2257 { 2257 SetInStaticSpace(this);
2258 //Check that we have a Parent 2258 }
2259 //If we have a parent then we're not authorative here 2259
2260 if (_parent == null) 2260 if (m_isphysical && Body == IntPtr.Zero)
2261 { 2261 {
2262 if (!newLock.ApproxEquals(Vector3.One, 0f)) 2262 MakeBody();
2263 { 2263 }
2264 createAMotor(newLock); 2264 }
2265 } 2265
2266 else 2266 private void changeAngularLock(Vector3 newLock)
2267 { 2267 {
2268 if (Amotor != IntPtr.Zero) 2268 // do we have a Physical object?
2269 { 2269 if (Body != IntPtr.Zero)
2270 d.JointDestroy(Amotor); 2270 {
2271 Amotor = IntPtr.Zero; 2271 //Check that we have a Parent
2272 } 2272 //If we have a parent then we're not authorative here
2273 } 2273 if (_parent == null)
2274 } 2274 {
2275 } 2275 if (!newLock.ApproxEquals(Vector3.One, 0f))
2276 // Store this for later in case we get turned into a separate body 2276 {
2277 m_angularlock = newLock; 2277 createAMotor(newLock);
2278 } 2278 }
2279 2279 else
2280 private void changeLink(OdePrim NewParent) 2280 {
2281 { 2281 if (Amotor != IntPtr.Zero)
2282 if (_parent == null && NewParent != null) 2282 {
2283 { 2283 d.JointDestroy(Amotor);
2284 NewParent.ParentPrim(this); 2284 Amotor = IntPtr.Zero;
2285 } 2285 }
2286 else if (_parent != null) 2286 }
2287 { 2287 }
2288 if (_parent is OdePrim) 2288 }
2289 { 2289 // Store this for later in case we get turned into a separate body
2290 if (NewParent != _parent) 2290 m_angularlock = newLock;
2291 { 2291 }
2292 (_parent as OdePrim).ChildDelink(this, false); // for now... 2292
2293 childPrim = false; 2293 private void changeLink(OdePrim NewParent)
2294 2294 {
2295 if (NewParent != null) 2295 if (_parent == null && NewParent != null)
2296 { 2296 {
2297 NewParent.ParentPrim(this); 2297 NewParent.ParentPrim(this);
2298 } 2298 }
2299 } 2299 else if (_parent != null)
2300 } 2300 {
2301 } 2301 if (_parent is OdePrim)
2302 _parent = NewParent; 2302 {
2303 } 2303 if (NewParent != _parent)
2304 2304 {
2305 2305 (_parent as OdePrim).ChildDelink(this, false); // for now...
2306 private void Stop() 2306 childPrim = false;
2307 { 2307
2308 if (!childPrim) 2308 if (NewParent != null)
2309 { 2309 {
2310 m_force = Vector3.Zero; 2310 NewParent.ParentPrim(this);
2311 m_forceacc = Vector3.Zero; 2311 }
2312 m_angularForceacc = Vector3.Zero; 2312 }
2313 _torque = Vector3.Zero; 2313 }
2314 _velocity = Vector3.Zero; 2314 }
2315 _acceleration = Vector3.Zero; 2315 _parent = NewParent;
2316 m_rotationalVelocity = Vector3.Zero; 2316 }
2317 _target_velocity = Vector3.Zero; 2317
2318 if (m_vehicle != null && m_vehicle.Type != Vehicle.TYPE_NONE) 2318
2319 m_vehicle.Stop(); 2319 private void Stop()
2320 } 2320 {
2321 2321 if (!childPrim)
2322 if (Body != IntPtr.Zero) 2322 {
2323 { 2323 m_force = Vector3.Zero;
2324 d.BodySetForce(Body, 0f, 0f, 0f); 2324 m_forceacc = Vector3.Zero;
2325 d.BodySetTorque(Body, 0f, 0f, 0f); 2325 m_angularForceacc = Vector3.Zero;
2326 d.BodySetLinearVel(Body, 0f, 0f, 0f); 2326 _torque = Vector3.Zero;
2327 d.BodySetAngularVel(Body, 0f, 0f, 0f); 2327 _velocity = Vector3.Zero;
2328 } 2328 _acceleration = Vector3.Zero;
2329 } 2329 m_rotationalVelocity = Vector3.Zero;
2330 2330 _target_velocity = Vector3.Zero;
2331 2331 if (m_vehicle != null && m_vehicle.Type != Vehicle.TYPE_NONE)
2332 private void changePhantomStatus(bool newval) 2332 m_vehicle.Stop();
2333 { 2333 }
2334 m_isphantom = newval; 2334
2335 2335 if (Body != IntPtr.Zero)
2336 if (m_isSelected) 2336 {
2337 { 2337 d.BodySetForce(Body, 0f, 0f, 0f);
2338 m_collisionCategories = CollisionCategories.Selected; 2338 d.BodySetTorque(Body, 0f, 0f, 0f);
2339 m_collisionFlags = (CollisionCategories.Sensor | CollisionCategories.Space); 2339 d.BodySetLinearVel(Body, 0f, 0f, 0f);
2340 } 2340 d.BodySetAngularVel(Body, 0f, 0f, 0f);
2341 else 2341 }
2342 { 2342 }
2343 if (m_isphantom && !m_isVolumeDetect) 2343
2344 { 2344
2345 m_collisionCategories = 0; 2345 private void changePhantomStatus(bool newval)
2346 if (m_isphysical) 2346 {
2347 m_collisionFlags = CollisionCategories.Land; 2347 m_isphantom = newval;
2348 else 2348
2349 m_collisionFlags = 0; // should never happen 2349 if (m_isSelected)
2350 } 2350 {
2351 2351 m_collisionCategories = CollisionCategories.Selected;
2352 else 2352 m_collisionFlags = (CollisionCategories.Sensor | CollisionCategories.Space);
2353 { 2353 }
2354 m_collisionCategories = CollisionCategories.Geom; 2354 else
2355 if (m_isphysical) 2355 {
2356 m_collisionCategories |= CollisionCategories.Body; 2356 if (m_isphantom && !m_isVolumeDetect)
2357 2357 {
2358 m_collisionFlags = m_default_collisionFlags | CollisionCategories.Land; 2358 m_collisionCategories = 0;
2359 2359 if (m_isphysical)
2360 if (m_collidesWater) 2360 m_collisionFlags = CollisionCategories.Land;
2361 m_collisionFlags |= CollisionCategories.Water; 2361 else
2362 } 2362 m_collisionFlags = 0; // should never happen
2363 } 2363 }
2364 2364
2365 if (!childPrim) 2365 else
2366 { 2366 {
2367 foreach (OdePrim prm in childrenPrim) 2367 m_collisionCategories = CollisionCategories.Geom;
2368 { 2368 if (m_isphysical)
2369 prm.m_collisionCategories = m_collisionCategories; 2369 m_collisionCategories |= CollisionCategories.Body;
2370 prm.m_collisionFlags = m_collisionFlags; 2370
2371 2371 m_collisionFlags = m_default_collisionFlags | CollisionCategories.Land;
2372 if (!prm.m_disabled && prm.prim_geom != IntPtr.Zero) 2372
2373 { 2373 if (m_collidesWater)
2374 if (prm.m_NoColide) 2374 m_collisionFlags |= CollisionCategories.Water;
2375 { 2375 }
2376 d.GeomSetCategoryBits(prm.prim_geom, 0); 2376 }
2377 if (m_isphysical) 2377
2378 d.GeomSetCollideBits(prm.prim_geom, (int)CollisionCategories.Land); 2378 if (!childPrim)
2379 else 2379 {
2380 d.GeomSetCollideBits(prm.prim_geom, 0); 2380 foreach (OdePrim prm in childrenPrim)
2381 } 2381 {
2382 else 2382 prm.m_collisionCategories = m_collisionCategories;
2383 { 2383 prm.m_collisionFlags = m_collisionFlags;
2384 d.GeomSetCategoryBits(prm.prim_geom, (int)m_collisionCategories); 2384
2385 d.GeomSetCollideBits(prm.prim_geom, (int)m_collisionFlags); 2385 if (!prm.m_disabled && prm.prim_geom != IntPtr.Zero)
2386 } 2386 {
2387 if(!m_isSelected) 2387 if (prm.m_NoColide)
2388 d.GeomEnable(prm.prim_geom); 2388 {
2389 } 2389 d.GeomSetCategoryBits(prm.prim_geom, 0);
2390 } 2390 if (m_isphysical)
2391 } 2391 d.GeomSetCollideBits(prm.prim_geom, (int)CollisionCategories.Land);
2392 2392 else
2393 if (!m_disabled && prim_geom != IntPtr.Zero) 2393 d.GeomSetCollideBits(prm.prim_geom, 0);
2394 { 2394 }
2395 if (m_NoColide) 2395 else
2396 { 2396 {
2397 d.GeomSetCategoryBits(prim_geom, 0); 2397 d.GeomSetCategoryBits(prm.prim_geom, (int)m_collisionCategories);
2398 if (m_isphysical) 2398 d.GeomSetCollideBits(prm.prim_geom, (int)m_collisionFlags);
2399 d.GeomSetCollideBits(prim_geom, (int)CollisionCategories.Land); 2399 }
2400 else 2400 if(!m_isSelected)
2401 d.GeomSetCollideBits(prim_geom, 0); 2401 d.GeomEnable(prm.prim_geom);
2402 } 2402 }
2403 else 2403 }
2404 { 2404 }
2405 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories); 2405
2406 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); 2406 if (!m_disabled && prim_geom != IntPtr.Zero)
2407 } 2407 {
2408 if(!m_isSelected) 2408 if (m_NoColide)
2409 d.GeomEnable(prim_geom); 2409 {
2410 } 2410 d.GeomSetCategoryBits(prim_geom, 0);
2411 } 2411 if (m_isphysical)
2412 2412 d.GeomSetCollideBits(prim_geom, (int)CollisionCategories.Land);
2413 private void changeSelectedStatus(bool newval) 2413 else
2414 { 2414 d.GeomSetCollideBits(prim_geom, 0);
2415 if (m_lastdoneSelected == newval) 2415 }
2416 return; 2416 else
2417 2417 {
2418 m_lastdoneSelected = newval; 2418 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
2419 DoSelectedStatus(newval); 2419 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
2420 } 2420 }
2421 2421 if(!m_isSelected)
2422 private void CheckDelaySelect() 2422 d.GeomEnable(prim_geom);
2423 { 2423 }
2424 if (m_delaySelect) 2424 }
2425 { 2425
2426 DoSelectedStatus(m_isSelected); 2426 private void changeSelectedStatus(bool newval)
2427 } 2427 {
2428 } 2428 if (m_lastdoneSelected == newval)
2429 2429 return;
2430 private void DoSelectedStatus(bool newval) 2430
2431 { 2431 m_lastdoneSelected = newval;
2432 m_isSelected = newval; 2432 DoSelectedStatus(newval);
2433 Stop(); 2433 }
2434 2434
2435 if (newval) 2435 private void CheckDelaySelect()
2436 { 2436 {
2437 if (!childPrim && Body != IntPtr.Zero) 2437 if (m_delaySelect)
2438 d.BodyDisable(Body); 2438 {
2439 2439 DoSelectedStatus(m_isSelected);
2440 if (m_delaySelect || m_isphysical) 2440 }
2441 { 2441 }
2442 m_collisionCategories = CollisionCategories.Selected; 2442
2443 m_collisionFlags = (CollisionCategories.Sensor | CollisionCategories.Space); 2443 private void DoSelectedStatus(bool newval)
2444 2444 {
2445 if (!childPrim) 2445 m_isSelected = newval;
2446 { 2446 Stop();
2447 foreach (OdePrim prm in childrenPrim) 2447
2448 { 2448 if (newval)
2449 prm.m_collisionCategories = m_collisionCategories; 2449 {
2450 prm.m_collisionFlags = m_collisionFlags; 2450 if (!childPrim && Body != IntPtr.Zero)
2451 2451 d.BodyDisable(Body);
2452 if (prm.prim_geom != null) 2452
2453 { 2453 if (m_delaySelect || m_isphysical)
2454 2454 {
2455 if (prm.m_NoColide) 2455 m_collisionCategories = CollisionCategories.Selected;
2456 { 2456 m_collisionFlags = (CollisionCategories.Sensor | CollisionCategories.Space);
2457 d.GeomSetCategoryBits(prm.prim_geom, 0); 2457
2458 d.GeomSetCollideBits(prm.prim_geom, 0); 2458 if (!childPrim)
2459 } 2459 {
2460 else 2460 foreach (OdePrim prm in childrenPrim)
2461 { 2461 {
2462 d.GeomSetCategoryBits(prm.prim_geom, (int)m_collisionCategories); 2462 prm.m_collisionCategories = m_collisionCategories;
2463 d.GeomSetCollideBits(prm.prim_geom, (int)m_collisionFlags); 2463 prm.m_collisionFlags = m_collisionFlags;
2464 } 2464
2465 d.GeomDisable(prm.prim_geom); 2465 if (prm.prim_geom != null)
2466 } 2466 {
2467 prm.m_delaySelect = false; 2467
2468 } 2468 if (prm.m_NoColide)
2469 } 2469 {
2470 2470 d.GeomSetCategoryBits(prm.prim_geom, 0);
2471 if (prim_geom != null) 2471 d.GeomSetCollideBits(prm.prim_geom, 0);
2472 { 2472 }
2473 if (m_NoColide) 2473 else
2474 { 2474 {
2475 d.GeomSetCategoryBits(prim_geom, 0); 2475 d.GeomSetCategoryBits(prm.prim_geom, (int)m_collisionCategories);
2476 d.GeomSetCollideBits(prim_geom, 0); 2476 d.GeomSetCollideBits(prm.prim_geom, (int)m_collisionFlags);
2477 } 2477 }
2478 else 2478 d.GeomDisable(prm.prim_geom);
2479 { 2479 }
2480 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories); 2480 prm.m_delaySelect = false;
2481 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); 2481 }
2482 } 2482 }
2483 d.GeomDisable(prim_geom); 2483
2484 } 2484 if (prim_geom != null)
2485 2485 {
2486 m_delaySelect = false; 2486 if (m_NoColide)
2487 } 2487 {
2488 else if(!m_isphysical) 2488 d.GeomSetCategoryBits(prim_geom, 0);
2489 { 2489 d.GeomSetCollideBits(prim_geom, 0);
2490 m_delaySelect = true; 2490 }
2491 } 2491 else
2492 } 2492 {
2493 else 2493 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
2494 { 2494 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
2495 if (!childPrim && Body != IntPtr.Zero && !m_disabled) 2495 }
2496 d.BodyEnable(Body); 2496 d.GeomDisable(prim_geom);
2497 2497 }
2498 if (m_isphantom && !m_isVolumeDetect) 2498
2499 { 2499 m_delaySelect = false;
2500 m_collisionCategories = 0; 2500 }
2501 if(m_isphysical) 2501 else if(!m_isphysical)
2502 m_collisionFlags = CollisionCategories.Land; 2502 {
2503 else 2503 m_delaySelect = true;
2504 m_collisionFlags = 0; 2504 }
2505 } 2505 }
2506 else 2506 else
2507 { 2507 {
2508 m_collisionCategories = CollisionCategories.Geom; 2508 if (!childPrim && Body != IntPtr.Zero && !m_disabled)
2509 if (m_isphysical) 2509 d.BodyEnable(Body);
2510 m_collisionCategories |= CollisionCategories.Body; 2510
2511 2511 if (m_isphantom && !m_isVolumeDetect)
2512 m_collisionFlags = m_default_collisionFlags | CollisionCategories.Land; 2512 {
2513 2513 m_collisionCategories = 0;
2514 if (m_collidesWater) 2514 if(m_isphysical)
2515 m_collisionFlags |= CollisionCategories.Water; 2515 m_collisionFlags = CollisionCategories.Land;
2516 } 2516 else
2517 2517 m_collisionFlags = 0;
2518 if (!childPrim) 2518 }
2519 { 2519 else
2520 foreach (OdePrim prm in childrenPrim) 2520 {
2521 { 2521 m_collisionCategories = CollisionCategories.Geom;
2522 prm.m_collisionCategories = m_collisionCategories; 2522 if (m_isphysical)
2523 prm.m_collisionFlags = m_collisionFlags; 2523 m_collisionCategories |= CollisionCategories.Body;
2524 2524
2525 if (!prm.m_disabled && prm.prim_geom != IntPtr.Zero) 2525 m_collisionFlags = m_default_collisionFlags | CollisionCategories.Land;
2526 { 2526
2527 if (prm.m_NoColide) 2527 if (m_collidesWater)
2528 { 2528 m_collisionFlags |= CollisionCategories.Water;
2529 d.GeomSetCategoryBits(prm.prim_geom, 0); 2529 }
2530 if (m_isphysical) 2530
2531 d.GeomSetCollideBits(prm.prim_geom, (int)CollisionCategories.Land); 2531 if (!childPrim)
2532 else 2532 {
2533 d.GeomSetCollideBits(prm.prim_geom, 0); 2533 foreach (OdePrim prm in childrenPrim)
2534 } 2534 {
2535 else 2535 prm.m_collisionCategories = m_collisionCategories;
2536 { 2536 prm.m_collisionFlags = m_collisionFlags;
2537 d.GeomSetCategoryBits(prm.prim_geom, (int)m_collisionCategories); 2537
2538 d.GeomSetCollideBits(prm.prim_geom, (int)m_collisionFlags); 2538 if (!prm.m_disabled && prm.prim_geom != IntPtr.Zero)
2539 } 2539 {
2540 d.GeomEnable(prm.prim_geom); 2540 if (prm.m_NoColide)
2541 } 2541 {
2542 prm.m_delaySelect = false; 2542 d.GeomSetCategoryBits(prm.prim_geom, 0);
2543 prm.m_softcolide = true; 2543 if (m_isphysical)
2544 } 2544 d.GeomSetCollideBits(prm.prim_geom, (int)CollisionCategories.Land);
2545 } 2545 else
2546 2546 d.GeomSetCollideBits(prm.prim_geom, 0);
2547 if (!m_disabled && prim_geom != IntPtr.Zero) 2547 }
2548 { 2548 else
2549 if (m_NoColide) 2549 {
2550 { 2550 d.GeomSetCategoryBits(prm.prim_geom, (int)m_collisionCategories);
2551 d.GeomSetCategoryBits(prim_geom, 0); 2551 d.GeomSetCollideBits(prm.prim_geom, (int)m_collisionFlags);
2552 if (m_isphysical) 2552 }
2553 d.GeomSetCollideBits(prim_geom, (int)CollisionCategories.Land); 2553 d.GeomEnable(prm.prim_geom);
2554 else 2554 }
2555 d.GeomSetCollideBits(prim_geom, 0); 2555 prm.m_delaySelect = false;
2556 } 2556 prm.m_softcolide = true;
2557 else 2557 }
2558 { 2558 }
2559 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories); 2559
2560 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); 2560 if (!m_disabled && prim_geom != IntPtr.Zero)
2561 } 2561 {
2562 d.GeomEnable(prim_geom); 2562 if (m_NoColide)
2563 } 2563 {
2564 2564 d.GeomSetCategoryBits(prim_geom, 0);
2565 m_delaySelect = false; 2565 if (m_isphysical)
2566 m_softcolide = true; 2566 d.GeomSetCollideBits(prim_geom, (int)CollisionCategories.Land);
2567 } 2567 else
2568 2568 d.GeomSetCollideBits(prim_geom, 0);
2569 resetCollisionAccounting(); 2569 }
2570 } 2570 else
2571 2571 {
2572 private void changePosition(Vector3 newPos) 2572 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
2573 { 2573 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
2574 CheckDelaySelect(); 2574 }
2575 if (m_isphysical) 2575 d.GeomEnable(prim_geom);
2576 { 2576 }
2577 if (childPrim) // inertia is messed, must rebuild 2577
2578 { 2578 m_delaySelect = false;
2579 if (m_building) 2579 m_softcolide = true;
2580 { 2580 }
2581 _position = newPos; 2581
2582 } 2582 resetCollisionAccounting();
2583 } 2583 }
2584 else 2584
2585 { 2585 private void changePosition(Vector3 newPos)
2586 if (_position != newPos) 2586 {
2587 { 2587 CheckDelaySelect();
2588 d.GeomSetPosition(prim_geom, newPos.X, newPos.Y, newPos.Z); 2588 if (m_isphysical)
2589 _position = newPos; 2589 {
2590 } 2590 if (childPrim) // inertia is messed, must rebuild
2591 if (Body != IntPtr.Zero && !d.BodyIsEnabled(Body)) 2591 {
2592 d.BodyEnable(Body); 2592 if (m_building)
2593 } 2593 {
2594 } 2594 _position = newPos;
2595 else 2595 }
2596 { 2596 }
2597 if (prim_geom != IntPtr.Zero) 2597 else
2598 { 2598 {
2599 if (newPos != _position) 2599 if (_position != newPos)
2600 { 2600 {
2601 d.GeomSetPosition(prim_geom, newPos.X, newPos.Y, newPos.Z); 2601 d.GeomSetPosition(prim_geom, newPos.X, newPos.Y, newPos.Z);
2602 _position = newPos; 2602 _position = newPos;
2603 2603 }
2604 m_targetSpace = _parent_scene.MoveGeomToStaticSpace(prim_geom, _position, m_targetSpace); 2604 if (Body != IntPtr.Zero && !d.BodyIsEnabled(Body))
2605 } 2605 d.BodyEnable(Body);
2606 } 2606 }
2607 } 2607 }
2608 givefakepos--; 2608 else
2609 if (givefakepos < 0) 2609 {
2610 givefakepos = 0; 2610 if (prim_geom != IntPtr.Zero)
2611 // changeSelectedStatus(); 2611 {
2612 m_softcolide = true; 2612 if (newPos != _position)
2613 resetCollisionAccounting(); 2613 {
2614 } 2614 d.GeomSetPosition(prim_geom, newPos.X, newPos.Y, newPos.Z);
2615 2615 _position = newPos;
2616 private void changeOrientation(Quaternion newOri) 2616
2617 { 2617 m_targetSpace = _parent_scene.MoveGeomToStaticSpace(prim_geom, _position, m_targetSpace);
2618 CheckDelaySelect(); 2618 }
2619 if (m_isphysical) 2619 }
2620 { 2620 }
2621 if (childPrim) // inertia is messed, must rebuild 2621 givefakepos--;
2622 { 2622 if (givefakepos < 0)
2623 if (m_building) 2623 givefakepos = 0;
2624 { 2624 // changeSelectedStatus();
2625 _orientation = newOri; 2625 m_softcolide = true;
2626 } 2626 resetCollisionAccounting();
2627 } 2627 }
2628 else 2628
2629 { 2629 private void changeOrientation(Quaternion newOri)
2630 if (newOri != _orientation) 2630 {
2631 { 2631 CheckDelaySelect();
2632 d.Quaternion myrot = new d.Quaternion(); 2632 if (m_isphysical)
2633 myrot.X = newOri.X; 2633 {
2634 myrot.Y = newOri.Y; 2634 if (childPrim) // inertia is messed, must rebuild
2635 myrot.Z = newOri.Z; 2635 {
2636 myrot.W = newOri.W; 2636 if (m_building)
2637 d.GeomSetQuaternion(prim_geom, ref myrot); 2637 {
2638 _orientation = newOri; 2638 _orientation = newOri;
2639 if (Body != IntPtr.Zero && !m_angularlock.ApproxEquals(Vector3.One, 0f)) 2639 }
2640 createAMotor(m_angularlock); 2640 }
2641 } 2641 else
2642 if (Body != IntPtr.Zero && !d.BodyIsEnabled(Body)) 2642 {
2643 d.BodyEnable(Body); 2643 if (newOri != _orientation)
2644 } 2644 {
2645 } 2645 d.Quaternion myrot = new d.Quaternion();
2646 else 2646 myrot.X = newOri.X;
2647 { 2647 myrot.Y = newOri.Y;
2648 if (prim_geom != IntPtr.Zero) 2648 myrot.Z = newOri.Z;
2649 { 2649 myrot.W = newOri.W;
2650 if (newOri != _orientation) 2650 d.GeomSetQuaternion(prim_geom, ref myrot);
2651 { 2651 _orientation = newOri;
2652 d.Quaternion myrot = new d.Quaternion(); 2652 if (Body != IntPtr.Zero && !m_angularlock.ApproxEquals(Vector3.One, 0f))
2653 myrot.X = newOri.X; 2653 createAMotor(m_angularlock);
2654 myrot.Y = newOri.Y; 2654 }
2655 myrot.Z = newOri.Z; 2655 if (Body != IntPtr.Zero && !d.BodyIsEnabled(Body))
2656 myrot.W = newOri.W; 2656 d.BodyEnable(Body);
2657 d.GeomSetQuaternion(prim_geom, ref myrot); 2657 }
2658 _orientation = newOri; 2658 }
2659 } 2659 else
2660 } 2660 {
2661 } 2661 if (prim_geom != IntPtr.Zero)
2662 givefakeori--; 2662 {
2663 if (givefakeori < 0) 2663 if (newOri != _orientation)
2664 givefakeori = 0; 2664 {
2665 m_softcolide = true; 2665 d.Quaternion myrot = new d.Quaternion();
2666 resetCollisionAccounting(); 2666 myrot.X = newOri.X;
2667 } 2667 myrot.Y = newOri.Y;
2668 2668 myrot.Z = newOri.Z;
2669 private void changePositionAndOrientation(Vector3 newPos, Quaternion newOri) 2669 myrot.W = newOri.W;
2670 { 2670 d.GeomSetQuaternion(prim_geom, ref myrot);
2671 CheckDelaySelect(); 2671 _orientation = newOri;
2672 if (m_isphysical) 2672 }
2673 { 2673 }
2674 if (childPrim && m_building) // inertia is messed, must rebuild 2674 }
2675 { 2675 givefakeori--;
2676 _position = newPos; 2676 if (givefakeori < 0)
2677 _orientation = newOri; 2677 givefakeori = 0;
2678 } 2678 m_softcolide = true;
2679 else 2679 resetCollisionAccounting();
2680 { 2680 }
2681 if (newOri != _orientation) 2681
2682 { 2682 private void changePositionAndOrientation(Vector3 newPos, Quaternion newOri)
2683 d.Quaternion myrot = new d.Quaternion(); 2683 {
2684 myrot.X = newOri.X; 2684 CheckDelaySelect();
2685 myrot.Y = newOri.Y; 2685 if (m_isphysical)
2686 myrot.Z = newOri.Z; 2686 {
2687 myrot.W = newOri.W; 2687 if (childPrim && m_building) // inertia is messed, must rebuild
2688 d.GeomSetQuaternion(prim_geom, ref myrot); 2688 {
2689 _orientation = newOri; 2689 _position = newPos;
2690 if (Body != IntPtr.Zero && !m_angularlock.ApproxEquals(Vector3.One, 0f)) 2690 _orientation = newOri;
2691 createAMotor(m_angularlock); 2691 }
2692 } 2692 else
2693 if (_position != newPos) 2693 {
2694 { 2694 if (newOri != _orientation)
2695 d.GeomSetPosition(prim_geom, newPos.X, newPos.Y, newPos.Z); 2695 {
2696 _position = newPos; 2696 d.Quaternion myrot = new d.Quaternion();
2697 } 2697 myrot.X = newOri.X;
2698 if (Body != IntPtr.Zero && !d.BodyIsEnabled(Body)) 2698 myrot.Y = newOri.Y;
2699 d.BodyEnable(Body); 2699 myrot.Z = newOri.Z;
2700 } 2700 myrot.W = newOri.W;
2701 } 2701 d.GeomSetQuaternion(prim_geom, ref myrot);
2702 else 2702 _orientation = newOri;
2703 { 2703 if (Body != IntPtr.Zero && !m_angularlock.ApproxEquals(Vector3.One, 0f))
2704 // string primScenAvatarIn = _parent_scene.whichspaceamIin(_position); 2704 createAMotor(m_angularlock);
2705 // int[] arrayitem = _parent_scene.calculateSpaceArrayItemFromPos(_position); 2705 }
2706 2706 if (_position != newPos)
2707 if (prim_geom != IntPtr.Zero) 2707 {
2708 { 2708 d.GeomSetPosition(prim_geom, newPos.X, newPos.Y, newPos.Z);
2709 if (newOri != _orientation) 2709 _position = newPos;
2710 { 2710 }
2711 d.Quaternion myrot = new d.Quaternion(); 2711 if (Body != IntPtr.Zero && !d.BodyIsEnabled(Body))
2712 myrot.X = newOri.X; 2712 d.BodyEnable(Body);
2713 myrot.Y = newOri.Y; 2713 }
2714 myrot.Z = newOri.Z; 2714 }
2715 myrot.W = newOri.W; 2715 else
2716 d.GeomSetQuaternion(prim_geom, ref myrot); 2716 {
2717 _orientation = newOri; 2717 // string primScenAvatarIn = _parent_scene.whichspaceamIin(_position);
2718 } 2718 // int[] arrayitem = _parent_scene.calculateSpaceArrayItemFromPos(_position);
2719 2719
2720 if (newPos != _position) 2720 if (prim_geom != IntPtr.Zero)
2721 { 2721 {
2722 d.GeomSetPosition(prim_geom, newPos.X, newPos.Y, newPos.Z); 2722 if (newOri != _orientation)
2723 _position = newPos; 2723 {
2724 2724 d.Quaternion myrot = new d.Quaternion();
2725 m_targetSpace = _parent_scene.MoveGeomToStaticSpace(prim_geom, _position, m_targetSpace); 2725 myrot.X = newOri.X;
2726 } 2726 myrot.Y = newOri.Y;
2727 } 2727 myrot.Z = newOri.Z;
2728 } 2728 myrot.W = newOri.W;
2729 givefakepos--; 2729 d.GeomSetQuaternion(prim_geom, ref myrot);
2730 if (givefakepos < 0) 2730 _orientation = newOri;
2731 givefakepos = 0; 2731 }
2732 givefakeori--; 2732
2733 if (givefakeori < 0) 2733 if (newPos != _position)
2734 givefakeori = 0; 2734 {
2735 2735 d.GeomSetPosition(prim_geom, newPos.X, newPos.Y, newPos.Z);
2736 m_softcolide = true; 2736 _position = newPos;
2737 resetCollisionAccounting(); 2737
2738 } 2738 m_targetSpace = _parent_scene.MoveGeomToStaticSpace(prim_geom, _position, m_targetSpace);
2739 2739 }
2740 2740 }
2741 private void changeDisable(bool disable) 2741 }
2742 { 2742 givefakepos--;
2743 if (disable) 2743 if (givefakepos < 0)
2744 { 2744 givefakepos = 0;
2745 if (!m_disabled) 2745 givefakeori--;
2746 disableBodySoft(); 2746 if (givefakeori < 0)
2747 } 2747 givefakeori = 0;
2748 else 2748
2749 { 2749 m_softcolide = true;
2750 if (m_disabled) 2750 resetCollisionAccounting();
2751 enableBodySoft(); 2751 }
2752 } 2752
2753 } 2753
2754 2754 private void changeDisable(bool disable)
2755 private void changePhysicsStatus(bool NewStatus) 2755 {
2756 { 2756 if (disable)
2757 CheckDelaySelect(); 2757 {
2758 2758 if (!m_disabled)
2759 m_isphysical = NewStatus; 2759 disableBodySoft();
2760 2760 }
2761 if (!childPrim) 2761 else
2762 { 2762 {
2763 if (NewStatus) 2763 if (m_disabled)
2764 { 2764 enableBodySoft();
2765 if (Body == IntPtr.Zero) 2765 }
2766 MakeBody(); 2766 }
2767 } 2767
2768 else 2768 private void changePhysicsStatus(bool NewStatus)
2769 { 2769 {
2770 if (Body != IntPtr.Zero) 2770 CheckDelaySelect();
2771 { 2771
2772 DestroyBody(); 2772 m_isphysical = NewStatus;
2773 } 2773
2774 Stop(); 2774 if (!childPrim)
2775 } 2775 {
2776 } 2776 if (NewStatus)
2777 2777 {
2778 resetCollisionAccounting(); 2778 if (Body == IntPtr.Zero)
2779 } 2779 MakeBody();
2780 2780 }
2781 private void changeprimsizeshape() 2781 else
2782 { 2782 {
2783 CheckDelaySelect(); 2783 if (Body != IntPtr.Zero)
2784 2784 {
2785 OdePrim parent = (OdePrim)_parent; 2785 DestroyBody();
2786 2786 }
2787 bool chp = childPrim; 2787 Stop();
2788 2788 }
2789 if (chp) 2789 }
2790 { 2790
2791 if (parent != null) 2791 resetCollisionAccounting();
2792 { 2792 }
2793 parent.DestroyBody(); 2793
2794 } 2794 private void changeprimsizeshape()
2795 } 2795 {
2796 else 2796 CheckDelaySelect();
2797 { 2797
2798 DestroyBody(); 2798 OdePrim parent = (OdePrim)_parent;
2799 } 2799
2800 2800 bool chp = childPrim;
2801 RemoveGeom(); 2801
2802 2802 if (chp)
2803 // we don't need to do space calculation because the client sends a position update also. 2803 {
2804 if (_size.X <= 0) 2804 if (parent != null)
2805 _size.X = 0.01f; 2805 {
2806 if (_size.Y <= 0) 2806 parent.DestroyBody();
2807 _size.Y = 0.01f; 2807 }
2808 if (_size.Z <= 0) 2808 }
2809 _size.Z = 0.01f; 2809 else
2810 // Construction of new prim 2810 {
2811 2811 DestroyBody();
2812 CreateGeom(); 2812 }
2813 2813
2814 if (prim_geom != IntPtr.Zero) 2814 RemoveGeom();
2815 { 2815
2816 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z); 2816 // we don't need to do space calculation because the client sends a position update also.
2817 d.Quaternion myrot = new d.Quaternion(); 2817 if (_size.X <= 0)
2818 myrot.X = _orientation.X; 2818 _size.X = 0.01f;
2819 myrot.Y = _orientation.Y; 2819 if (_size.Y <= 0)
2820 myrot.Z = _orientation.Z; 2820 _size.Y = 0.01f;
2821 myrot.W = _orientation.W; 2821 if (_size.Z <= 0)
2822 d.GeomSetQuaternion(prim_geom, ref myrot); 2822 _size.Z = 0.01f;
2823 } 2823 // Construction of new prim
2824 2824
2825 if (chp) 2825 CreateGeom();
2826 { 2826
2827 if (parent != null) 2827 if (prim_geom != IntPtr.Zero)
2828 { 2828 {
2829 parent.MakeBody(); 2829 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
2830 } 2830 d.Quaternion myrot = new d.Quaternion();
2831 } 2831 myrot.X = _orientation.X;
2832 else 2832 myrot.Y = _orientation.Y;
2833 MakeBody(); 2833 myrot.Z = _orientation.Z;
2834 2834 myrot.W = _orientation.W;
2835 m_softcolide = true; 2835 d.GeomSetQuaternion(prim_geom, ref myrot);
2836 resetCollisionAccounting(); 2836 }
2837 } 2837
2838 2838 if (chp)
2839 private void changeSize(Vector3 newSize) 2839 {
2840 { 2840 if (parent != null)
2841 _size = newSize; 2841 {
2842 changeprimsizeshape(); 2842 parent.MakeBody();
2843 } 2843 }
2844 2844 }
2845 private void changeShape(PrimitiveBaseShape newShape) 2845 else
2846 { 2846 MakeBody();
2847 _pbs = newShape; 2847
2848 changeprimsizeshape(); 2848 m_softcolide = true;
2849 } 2849 resetCollisionAccounting();
2850 2850 }
2851 private void changeFloatOnWater(bool newval) 2851
2852 { 2852 private void changeSize(Vector3 newSize)
2853 m_collidesWater = newval; 2853 {
2854 2854 _size = newSize;
2855 if (prim_geom != IntPtr.Zero && !m_isphantom) 2855 changeprimsizeshape();
2856 { 2856 }
2857 if (m_collidesWater) 2857
2858 { 2858 private void changeShape(PrimitiveBaseShape newShape)
2859 m_collisionFlags |= CollisionCategories.Water; 2859 {
2860 } 2860 if(newShape != null)
2861 else 2861 _pbs = newShape;
2862 { 2862 changeprimsizeshape();
2863 m_collisionFlags &= ~CollisionCategories.Water; 2863 }
2864 } 2864
2865 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); 2865 private void changeFloatOnWater(bool newval)
2866 } 2866 {
2867 } 2867 m_collidesWater = newval;
2868 2868
2869 private void changeSetTorque(Vector3 newtorque) 2869 if (prim_geom != IntPtr.Zero && !m_isphantom)
2870 { 2870 {
2871 if (!m_isSelected) 2871 if (m_collidesWater)
2872 { 2872 {
2873 if (m_isphysical && Body != IntPtr.Zero) 2873 m_collisionFlags |= CollisionCategories.Water;
2874 { 2874 }
2875 if (m_disabled) 2875 else
2876 enableBodySoft(); 2876 {
2877 else if (!d.BodyIsEnabled(Body)) 2877 m_collisionFlags &= ~CollisionCategories.Water;
2878 d.BodyEnable(Body); 2878 }
2879 2879 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
2880 } 2880 }
2881 _torque = newtorque; 2881 }
2882 } 2882
2883 } 2883 private void changeSetTorque(Vector3 newtorque)
2884 2884 {
2885 private void changeForce(Vector3 force) 2885 if (!m_isSelected)
2886 { 2886 {
2887 m_force = force; 2887 if (m_isphysical && Body != IntPtr.Zero)
2888 if (Body != IntPtr.Zero && !d.BodyIsEnabled(Body)) 2888 {
2889 d.BodyEnable(Body); 2889 if (m_disabled)
2890 } 2890 enableBodySoft();
2891 2891 else if (!d.BodyIsEnabled(Body))
2892 private void changeAddForce(Vector3 force) 2892 d.BodyEnable(Body);
2893 { 2893
2894 m_forceacc += force; 2894 }
2895 if (!m_isSelected) 2895 _torque = newtorque;
2896 { 2896 }
2897 lock (this) 2897 }
2898 { 2898
2899 //m_log.Info("[PHYSICS]: dequeing forcelist"); 2899 private void changeForce(Vector3 force)
2900 if (m_isphysical && Body != IntPtr.Zero) 2900 {
2901 { 2901 m_force = force;
2902 if (m_disabled) 2902 if (Body != IntPtr.Zero && !d.BodyIsEnabled(Body))
2903 enableBodySoft(); 2903 d.BodyEnable(Body);
2904 else if (!d.BodyIsEnabled(Body)) 2904 }
2905 d.BodyEnable(Body); 2905
2906 } 2906 private void changeAddForce(Vector3 force)
2907 } 2907 {
2908 2908 m_forceacc += force;
2909 m_collisionscore = 0; 2909 if (!m_isSelected)
2910 } 2910 {
2911 } 2911 lock (this)
2912 2912 {
2913 private void changeAddAngularForce(Vector3 aforce) 2913 //m_log.Info("[PHYSICS]: dequeing forcelist");
2914 { 2914 if (m_isphysical && Body != IntPtr.Zero)
2915 m_angularForceacc += aforce; 2915 {
2916 if (!m_isSelected) 2916 if (m_disabled)
2917 { 2917 enableBodySoft();
2918 lock (this) 2918 else if (!d.BodyIsEnabled(Body))
2919 { 2919 d.BodyEnable(Body);
2920 if (m_isphysical && Body != IntPtr.Zero) 2920 }
2921 { 2921 }
2922 if (m_disabled) 2922
2923 enableBodySoft(); 2923 m_collisionscore = 0;
2924 else if (!d.BodyIsEnabled(Body)) 2924 }
2925 d.BodyEnable(Body); 2925 }
2926 } 2926
2927 } 2927 private void changeAddAngularForce(Vector3 aforce)
2928 m_collisionscore = 0; 2928 {
2929 } 2929 m_angularForceacc += aforce;
2930 } 2930 if (!m_isSelected)
2931 2931 {
2932 private void changevelocity(Vector3 newVel) 2932 lock (this)
2933 { 2933 {
2934 if (!m_isSelected) 2934 if (m_isphysical && Body != IntPtr.Zero)
2935 { 2935 {
2936 if (Body != IntPtr.Zero) 2936 if (m_disabled)
2937 { 2937 enableBodySoft();
2938 if (m_disabled) 2938 else if (!d.BodyIsEnabled(Body))
2939 enableBodySoft(); 2939 d.BodyEnable(Body);
2940 else if (!d.BodyIsEnabled(Body)) 2940 }
2941 d.BodyEnable(Body); 2941 }
2942 2942 m_collisionscore = 0;
2943 d.BodySetLinearVel(Body, newVel.X, newVel.Y, newVel.Z); 2943 }
2944 } 2944 }
2945 //resetCollisionAccounting(); 2945
2946 } 2946 private void changevelocity(Vector3 newVel)
2947 _velocity = newVel; 2947 {
2948 } 2948 if (!m_isSelected)
2949 2949 {
2950 private void changeVolumedetetion(bool newVolDtc) 2950 if (Body != IntPtr.Zero)
2951 { 2951 {
2952 m_isVolumeDetect = newVolDtc; 2952 if (m_disabled)
2953 } 2953 enableBodySoft();
2954 2954 else if (!d.BodyIsEnabled(Body))
2955 protected void changeBuilding(bool newbuilding) 2955 d.BodyEnable(Body);
2956 { 2956
2957 if ((bool)newbuilding) 2957 d.BodySetLinearVel(Body, newVel.X, newVel.Y, newVel.Z);
2958 { 2958 }
2959 m_building = true; 2959 //resetCollisionAccounting();
2960 if (!childPrim) 2960 }
2961 DestroyBody(); 2961 _velocity = newVel;
2962 } 2962 }
2963 else 2963
2964 { 2964 private void changeVolumedetetion(bool newVolDtc)
2965 m_building = false; 2965 {
2966 CheckDelaySelect(); 2966 m_isVolumeDetect = newVolDtc;
2967 if (!childPrim) 2967 }
2968 MakeBody(); 2968
2969 } 2969 protected void changeBuilding(bool newbuilding)
2970 if (!childPrim && childrenPrim.Count > 0) 2970 {
2971 { 2971 if ((bool)newbuilding)
2972 foreach (OdePrim prm in childrenPrim) 2972 {
2973 prm.changeBuilding(m_building); // call directly 2973 m_building = true;
2974 } 2974 if (!childPrim)
2975 } 2975 DestroyBody();
2976 2976 }
2977 public void changeSetVehicle(VehicleData vdata) 2977 else
2978 { 2978 {
2979 if (m_vehicle == null) 2979 m_building = false;
2980 m_vehicle = new ODEDynamics(this); 2980 CheckDelaySelect();
2981 m_vehicle.DoSetVehicle(vdata); 2981 if (!childPrim)
2982 } 2982 MakeBody();
2983 private void changeVehicleType(int value) 2983 }
2984 { 2984 if (!childPrim && childrenPrim.Count > 0)
2985 if (value == (int)Vehicle.TYPE_NONE) 2985 {
2986 { 2986 foreach (OdePrim prm in childrenPrim)
2987 if (m_vehicle != null) 2987 prm.changeBuilding(m_building); // call directly
2988 m_vehicle = null; 2988 }
2989 } 2989 }
2990 else 2990
2991 { 2991 public void changeSetVehicle(VehicleData vdata)
2992 if (m_vehicle == null) 2992 {
2993 m_vehicle = new ODEDynamics(this); 2993 if (m_vehicle == null)
2994 2994 m_vehicle = new ODEDynamics(this);
2995 m_vehicle.ProcessTypeChange((Vehicle)value); 2995 m_vehicle.DoSetVehicle(vdata);
2996 } 2996 }
2997 } 2997 private void changeVehicleType(int value)
2998 2998 {
2999 private void changeVehicleFloatParam(strVehicleFloatParam fp) 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 3003 }
3004 m_vehicle.ProcessFloatVehicleParam((Vehicle)fp.param, fp.value); 3004 else
3005 } 3005 {
3006 3006 if (m_vehicle == null)
3007 private void changeVehicleVectorParam(strVehicleVectorParam vp) 3007 m_vehicle = new ODEDynamics(this);
3008 { 3008
3009 if (m_vehicle == null) 3009 m_vehicle.ProcessTypeChange((Vehicle)value);
3010 return; 3010 }
3011 m_vehicle.ProcessVectorVehicleParam((Vehicle)vp.param, vp.value); 3011 }
3012 } 3012
3013 3013 private void changeVehicleFloatParam(strVehicleFloatParam fp)
3014 private void changeVehicleRotationParam(strVehicleQuatParam qp) 3014 {
3015 { 3015 if (m_vehicle == null)
3016 if (m_vehicle == null) 3016 return;
3017 return; 3017
3018 m_vehicle.ProcessRotationVehicleParam((Vehicle)qp.param, qp.value); 3018 m_vehicle.ProcessFloatVehicleParam((Vehicle)fp.param, fp.value);
3019 } 3019 }
3020 3020
3021 private void changeVehicleFlags(strVehicleBoolParam bp) 3021 private void changeVehicleVectorParam(strVehicleVectorParam vp)
3022 { 3022 {
3023 if (m_vehicle == null) 3023 if (m_vehicle == null)
3024 return; 3024 return;
3025 m_vehicle.ProcessVehicleFlags(bp.param, bp.value); 3025 m_vehicle.ProcessVectorVehicleParam((Vehicle)vp.param, vp.value);
3026 } 3026 }
3027 3027
3028 #endregion 3028 private void changeVehicleRotationParam(strVehicleQuatParam qp)
3029 3029 {
3030 public void Move() 3030 if (m_vehicle == null)
3031 { 3031 return;
3032 if (!childPrim && m_isphysical && Body != IntPtr.Zero && 3032 m_vehicle.ProcessRotationVehicleParam((Vehicle)qp.param, qp.value);
3033 !m_disabled && !m_isSelected && d.BodyIsEnabled(Body) && !m_building && !m_outbounds) 3033 }
3034 // !m_disabled && !m_isSelected && !m_building && !m_outbounds) 3034
3035 { 3035 private void changeVehicleFlags(strVehicleBoolParam bp)
3036// if (!d.BodyIsEnabled(Body)) d.BodyEnable(Body); // KF add 161009 3036 {
3037 3037 if (m_vehicle == null)
3038 float timestep = _parent_scene.ODE_STEPSIZE; 3038 return;
3039 3039 m_vehicle.ProcessVehicleFlags(bp.param, bp.value);
3040 // check outside region 3040 }
3041 d.Vector3 lpos; 3041
3042 d.GeomCopyPosition(prim_geom, out lpos); // root position that is seem by rest of simulator 3042 #endregion
3043 3043
3044 if (lpos.Z < -100 || lpos.Z > 100000f) 3044 public void Move()
3045 { 3045 {
3046 m_outbounds = true; 3046 if (!childPrim && m_isphysical && Body != IntPtr.Zero &&
3047 3047 !m_disabled && !m_isSelected && d.BodyIsEnabled(Body) && !m_building && !m_outbounds)
3048 lpos.Z = Util.Clip(lpos.Z, -100f, 100000f); 3048 // !m_disabled && !m_isSelected && !m_building && !m_outbounds)
3049 _acceleration.X = 0; 3049 {
3050 _acceleration.Y = 0; 3050// if (!d.BodyIsEnabled(Body)) d.BodyEnable(Body); // KF add 161009
3051 _acceleration.Z = 0; 3051
3052 3052 float timestep = _parent_scene.ODE_STEPSIZE;
3053 _velocity.X = 0; 3053
3054 _velocity.Y = 0; 3054 // check outside region
3055 _velocity.Z = 0; 3055 d.Vector3 lpos;
3056 m_rotationalVelocity.X = 0; 3056 d.GeomCopyPosition(prim_geom, out lpos); // root position that is seem by rest of simulator
3057 m_rotationalVelocity.Y = 0; 3057
3058 m_rotationalVelocity.Z = 0; 3058 if (lpos.Z < -100 || lpos.Z > 100000f)
3059 3059 {
3060 d.BodySetLinearVel(Body, 0, 0, 0); // stop it 3060 m_outbounds = true;
3061 d.BodySetAngularVel(Body, 0, 0, 0); // stop it 3061
3062 d.BodySetPosition(Body, lpos.X, lpos.Y, lpos.Z); // put it somewhere 3062 lpos.Z = Util.Clip(lpos.Z, -100f, 100000f);
3063 m_lastposition = _position; 3063 _acceleration.X = 0;
3064 m_lastorientation = _orientation; 3064 _acceleration.Y = 0;
3065 3065 _acceleration.Z = 0;
3066 base.RequestPhysicsterseUpdate(); 3066
3067 3067 _velocity.X = 0;
3068 m_throttleUpdates = false; 3068 _velocity.Y = 0;
3069 throttleCounter = 0; 3069 _velocity.Z = 0;
3070 _zeroFlag = true; 3070 m_rotationalVelocity.X = 0;
3071 3071 m_rotationalVelocity.Y = 0;
3072 disableBodySoft(); // disable it and colisions 3072 m_rotationalVelocity.Z = 0;
3073 base.RaiseOutOfBounds(_position); 3073
3074 return; 3074 d.BodySetLinearVel(Body, 0, 0, 0); // stop it
3075 } 3075 d.BodySetAngularVel(Body, 0, 0, 0); // stop it
3076 3076 d.BodySetPosition(Body, lpos.X, lpos.Y, lpos.Z); // put it somewhere
3077 if (lpos.X < 0f) 3077 m_lastposition = _position;
3078 { 3078 m_lastorientation = _orientation;
3079 _position.X = Util.Clip(lpos.X, -2f, -0.1f); 3079
3080 m_outbounds = true; 3080 base.RequestPhysicsterseUpdate();
3081 } 3081
3082 else if(lpos.X > _parent_scene.WorldExtents.X) 3082 m_throttleUpdates = false;
3083 { 3083 throttleCounter = 0;
3084 _position.X = Util.Clip(lpos.X, _parent_scene.WorldExtents.X + 0.1f, _parent_scene.WorldExtents.X + 2f); 3084 _zeroFlag = true;
3085 m_outbounds = true; 3085
3086 } 3086 disableBodySoft(); // disable it and colisions
3087 if (lpos.Y < 0f) 3087 base.RaiseOutOfBounds(_position);
3088 { 3088 return;
3089 _position.Y = Util.Clip(lpos.Y, -2f, -0.1f); 3089 }
3090 m_outbounds = true; 3090
3091 } 3091 if (lpos.X < 0f)
3092 else if(lpos.Y > _parent_scene.WorldExtents.Y) 3092 {
3093 { 3093 _position.X = Util.Clip(lpos.X, -2f, -0.1f);
3094 _position.Y = Util.Clip(lpos.Y, _parent_scene.WorldExtents.Y + 0.1f, _parent_scene.WorldExtents.Y + 2f); 3094 m_outbounds = true;
3095 m_outbounds = true; 3095 }
3096 } 3096 else if(lpos.X > _parent_scene.WorldExtents.X)
3097 3097 {
3098 if(m_outbounds) 3098 _position.X = Util.Clip(lpos.X, _parent_scene.WorldExtents.X + 0.1f, _parent_scene.WorldExtents.X + 2f);
3099 { 3099 m_outbounds = true;
3100 m_lastposition = _position; 3100 }
3101 m_lastorientation = _orientation; 3101 if (lpos.Y < 0f)
3102 3102 {
3103 d.Vector3 dtmp = d.BodyGetAngularVel(Body); 3103 _position.Y = Util.Clip(lpos.Y, -2f, -0.1f);
3104 m_rotationalVelocity.X = dtmp.X; 3104 m_outbounds = true;
3105 m_rotationalVelocity.Y = dtmp.Y; 3105 }
3106 m_rotationalVelocity.Z = dtmp.Z; 3106 else if(lpos.Y > _parent_scene.WorldExtents.Y)
3107 3107 {
3108 dtmp = d.BodyGetLinearVel(Body); 3108 _position.Y = Util.Clip(lpos.Y, _parent_scene.WorldExtents.Y + 0.1f, _parent_scene.WorldExtents.Y + 2f);
3109 _velocity.X = dtmp.X; 3109 m_outbounds = true;
3110 _velocity.Y = dtmp.Y; 3110 }
3111 _velocity.Z = dtmp.Z; 3111
3112 3112 if(m_outbounds)
3113 d.BodySetLinearVel(Body, 0, 0, 0); // stop it 3113 {
3114 d.BodySetAngularVel(Body, 0, 0, 0); 3114 m_lastposition = _position;
3115 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z); 3115 m_lastorientation = _orientation;
3116 disableBodySoft(); // stop collisions 3116
3117 base.RequestPhysicsterseUpdate(); 3117 d.Vector3 dtmp = d.BodyGetAngularVel(Body);
3118 return; 3118 m_rotationalVelocity.X = dtmp.X;
3119 } 3119 m_rotationalVelocity.Y = dtmp.Y;
3120 3120 m_rotationalVelocity.Z = dtmp.Z;
3121 3121
3122 float fx = 0; 3122 dtmp = d.BodyGetLinearVel(Body);
3123 float fy = 0; 3123 _velocity.X = dtmp.X;
3124 float fz = 0; 3124 _velocity.Y = dtmp.Y;
3125 3125 _velocity.Z = dtmp.Z;
3126 if (m_vehicle != null && m_vehicle.Type != Vehicle.TYPE_NONE) 3126
3127 { 3127 d.BodySetLinearVel(Body, 0, 0, 0); // stop it
3128 // 'VEHICLES' are dealt with in ODEDynamics.cs 3128 d.BodySetAngularVel(Body, 0, 0, 0);
3129 m_vehicle.Step(); 3129 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
3130 } 3130 disableBodySoft(); // stop collisions
3131 else 3131 base.RequestPhysicsterseUpdate();
3132 { 3132 return;
3133 float m_mass = _mass; 3133 }
3134 3134
3135 // fz = 0f; 3135
3136 //m_log.Info(m_collisionFlags.ToString()); 3136 float fx = 0;
3137 if (m_usePID) 3137 float fy = 0;
3138 { 3138 float fz = 0;
3139 3139
3140 // If the PID Controller isn't active then we set our force 3140 if (m_vehicle != null && m_vehicle.Type != Vehicle.TYPE_NONE)
3141 // calculating base velocity to the current position 3141 {
3142 3142 // 'VEHICLES' are dealt with in ODEDynamics.cs
3143 if ((m_PIDTau < 1) && (m_PIDTau != 0)) 3143 m_vehicle.Step();
3144 { 3144 }
3145 //PID_G = PID_G / m_PIDTau; 3145 else
3146 m_PIDTau = 1; 3146 {
3147 } 3147 float m_mass = _mass;
3148 3148
3149 if ((PID_G - m_PIDTau) <= 0) 3149 // fz = 0f;
3150 { 3150 //m_log.Info(m_collisionFlags.ToString());
3151 PID_G = m_PIDTau + 1; 3151 if (m_usePID)
3152 } 3152 {
3153 3153
3154 d.Vector3 vel = d.BodyGetLinearVel(Body); 3154 // If the PID Controller isn't active then we set our force
3155 d.Vector3 pos = d.BodyGetPosition(Body); 3155 // calculating base velocity to the current position
3156 _target_velocity = 3156
3157 new Vector3( 3157 if ((m_PIDTau < 1) && (m_PIDTau != 0))
3158 (m_PIDTarget.X - pos.X) * ((PID_G - m_PIDTau) * timestep), 3158 {
3159 (m_PIDTarget.Y - pos.Y) * ((PID_G - m_PIDTau) * timestep), 3159 //PID_G = PID_G / m_PIDTau;
3160 (m_PIDTarget.Z - pos.Z) * ((PID_G - m_PIDTau) * timestep) 3160 m_PIDTau = 1;
3161 ); 3161 }
3162 3162
3163 // if velocity is zero, use position control; otherwise, velocity control 3163 if ((PID_G - m_PIDTau) <= 0)
3164 3164 {
3165 if (_target_velocity.ApproxEquals(Vector3.Zero, 0.1f)) 3165 PID_G = m_PIDTau + 1;
3166 { 3166 }
3167 // keep track of where we stopped. No more slippin' & slidin' 3167
3168 3168 d.Vector3 vel = d.BodyGetLinearVel(Body);
3169 // We only want to deactivate the PID Controller if we think we want to have our surrogate 3169 d.Vector3 pos = d.BodyGetPosition(Body);
3170 // react to the physics scene by moving it's position. 3170 _target_velocity =
3171 // Avatar to Avatar collisions 3171 new Vector3(
3172 // Prim to avatar collisions 3172 (m_PIDTarget.X - pos.X) * ((PID_G - m_PIDTau) * timestep),
3173 3173 (m_PIDTarget.Y - pos.Y) * ((PID_G - m_PIDTau) * timestep),
3174 //fx = (_target_velocity.X - vel.X) * (PID_D) + (_zeroPosition.X - pos.X) * (PID_P * 2); 3174 (m_PIDTarget.Z - pos.Z) * ((PID_G - m_PIDTau) * timestep)
3175 //fy = (_target_velocity.Y - vel.Y) * (PID_D) + (_zeroPosition.Y - pos.Y) * (PID_P * 2); 3175 );
3176 //fz = fz + (_target_velocity.Z - vel.Z) * (PID_D) + (_zeroPosition.Z - pos.Z) * PID_P; 3176
3177 d.BodySetPosition(Body, m_PIDTarget.X, m_PIDTarget.Y, m_PIDTarget.Z); 3177 // if velocity is zero, use position control; otherwise, velocity control
3178 d.BodySetLinearVel(Body, 0, 0, 0); 3178
3179 d.BodyAddForce(Body, 0, 0, fz); 3179 if (_target_velocity.ApproxEquals(Vector3.Zero, 0.1f))
3180 return; 3180 {
3181 } 3181 // keep track of where we stopped. No more slippin' & slidin'
3182 else 3182
3183 { 3183 // We only want to deactivate the PID Controller if we think we want to have our surrogate
3184 _zeroFlag = false; 3184 // react to the physics scene by moving it's position.
3185 3185 // Avatar to Avatar collisions
3186 // We're flying and colliding with something 3186 // Prim to avatar collisions
3187 fx = ((_target_velocity.X) - vel.X) * (PID_D); 3187
3188 fy = ((_target_velocity.Y) - vel.Y) * (PID_D); 3188 //fx = (_target_velocity.X - vel.X) * (PID_D) + (_zeroPosition.X - pos.X) * (PID_P * 2);
3189 3189 //fy = (_target_velocity.Y - vel.Y) * (PID_D) + (_zeroPosition.Y - pos.Y) * (PID_P * 2);
3190 // vec.Z = (_target_velocity.Z - vel.Z) * PID_D + (_zeroPosition.Z - pos.Z) * PID_P; 3190 //fz = fz + (_target_velocity.Z - vel.Z) * (PID_D) + (_zeroPosition.Z - pos.Z) * PID_P;
3191 3191 d.BodySetPosition(Body, m_PIDTarget.X, m_PIDTarget.Y, m_PIDTarget.Z);
3192 fz = ((_target_velocity.Z - vel.Z) * (PID_D)); 3192 d.BodySetLinearVel(Body, 0, 0, 0);
3193 } 3193 d.BodyAddForce(Body, 0, 0, fz);
3194 } // end if (m_usePID) 3194 return;
3195 3195 }
3196 // Hover PID Controller needs to be mutually exlusive to MoveTo PID controller 3196 else
3197 else if (m_useHoverPID) 3197 {
3198 { 3198 _zeroFlag = false;
3199 //Console.WriteLine("Hover " + Name); 3199
3200 3200 // We're flying and colliding with something
3201 // If we're using the PID controller, then we have no gravity 3201 fx = ((_target_velocity.X) - vel.X) * (PID_D);
3202 3202 fy = ((_target_velocity.Y) - vel.Y) * (PID_D);
3203 // no lock; for now it's only called from within Simulate() 3203
3204 3204 // vec.Z = (_target_velocity.Z - vel.Z) * PID_D + (_zeroPosition.Z - pos.Z) * PID_P;
3205 // If the PID Controller isn't active then we set our force 3205
3206 // calculating base velocity to the current position 3206 fz = ((_target_velocity.Z - vel.Z) * (PID_D));
3207 3207 }
3208 if ((m_PIDTau < 1)) 3208 } // end if (m_usePID)
3209 { 3209
3210 PID_G = PID_G / m_PIDTau; 3210 // Hover PID Controller needs to be mutually exlusive to MoveTo PID controller
3211 } 3211 else if (m_useHoverPID)
3212 3212 {
3213 if ((PID_G - m_PIDTau) <= 0) 3213 //Console.WriteLine("Hover " + Name);
3214 { 3214
3215 PID_G = m_PIDTau + 1; 3215 // If we're using the PID controller, then we have no gravity
3216 } 3216
3217 3217 // no lock; for now it's only called from within Simulate()
3218 // Where are we, and where are we headed? 3218
3219 d.Vector3 pos = d.BodyGetPosition(Body); 3219 // If the PID Controller isn't active then we set our force
3220 d.Vector3 vel = d.BodyGetLinearVel(Body); 3220 // calculating base velocity to the current position
3221 3221
3222 // Non-Vehicles have a limited set of Hover options. 3222 if ((m_PIDTau < 1))
3223 // determine what our target height really is based on HoverType 3223 {
3224 switch (m_PIDHoverType) 3224 PID_G = PID_G / m_PIDTau;
3225 { 3225 }
3226 case PIDHoverType.Ground: 3226
3227 m_groundHeight = _parent_scene.GetTerrainHeightAtXY(pos.X, pos.Y); 3227 if ((PID_G - m_PIDTau) <= 0)
3228 m_targetHoverHeight = m_groundHeight + m_PIDHoverHeight; 3228 {
3229 break; 3229 PID_G = m_PIDTau + 1;
3230 case PIDHoverType.GroundAndWater: 3230 }
3231 m_groundHeight = _parent_scene.GetTerrainHeightAtXY(pos.X, pos.Y); 3231
3232 m_waterHeight = _parent_scene.GetWaterLevel(); 3232 // Where are we, and where are we headed?
3233 if (m_groundHeight > m_waterHeight) 3233 d.Vector3 pos = d.BodyGetPosition(Body);
3234 { 3234 d.Vector3 vel = d.BodyGetLinearVel(Body);
3235 m_targetHoverHeight = m_groundHeight + m_PIDHoverHeight; 3235
3236 } 3236 // Non-Vehicles have a limited set of Hover options.
3237 else 3237 // determine what our target height really is based on HoverType
3238 { 3238 switch (m_PIDHoverType)
3239 m_targetHoverHeight = m_waterHeight + m_PIDHoverHeight; 3239 {
3240 } 3240 case PIDHoverType.Ground:
3241 break; 3241 m_groundHeight = _parent_scene.GetTerrainHeightAtXY(pos.X, pos.Y);
3242 3242 m_targetHoverHeight = m_groundHeight + m_PIDHoverHeight;
3243 } // end switch (m_PIDHoverType) 3243 break;
3244 3244 case PIDHoverType.GroundAndWater:
3245 3245 m_groundHeight = _parent_scene.GetTerrainHeightAtXY(pos.X, pos.Y);
3246 _target_velocity = 3246 m_waterHeight = _parent_scene.GetWaterLevel();
3247 new Vector3(0.0f, 0.0f, 3247 if (m_groundHeight > m_waterHeight)
3248 (m_targetHoverHeight - pos.Z) * ((PID_G - m_PIDHoverTau) * timestep) 3248 {
3249 ); 3249 m_targetHoverHeight = m_groundHeight + m_PIDHoverHeight;
3250 3250 }
3251 // if velocity is zero, use position control; otherwise, velocity control 3251 else
3252 3252 {
3253 if (_target_velocity.ApproxEquals(Vector3.Zero, 0.1f)) 3253 m_targetHoverHeight = m_waterHeight + m_PIDHoverHeight;
3254 { 3254 }
3255 // keep track of where we stopped. No more slippin' & slidin' 3255 break;
3256 3256
3257 // We only want to deactivate the PID Controller if we think we want to have our surrogate 3257 } // end switch (m_PIDHoverType)
3258 // react to the physics scene by moving it's position. 3258
3259 // Avatar to Avatar collisions 3259
3260 // Prim to avatar collisions 3260 _target_velocity =
3261 3261 new Vector3(0.0f, 0.0f,
3262 d.BodySetPosition(Body, pos.X, pos.Y, m_targetHoverHeight); 3262 (m_targetHoverHeight - pos.Z) * ((PID_G - m_PIDHoverTau) * timestep)
3263 d.BodySetLinearVel(Body, vel.X, vel.Y, 0); 3263 );
3264 // ? d.BodyAddForce(Body, 0, 0, fz); 3264
3265 return; 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 _zeroFlag = false; 3269 // keep track of where we stopped. No more slippin' & slidin'
3270 3270
3271 // We're flying and colliding with something 3271 // We only want to deactivate the PID Controller if we think we want to have our surrogate
3272 fz = ((_target_velocity.Z - vel.Z) * (PID_D)); 3272 // react to the physics scene by moving it's position.
3273 } 3273 // Avatar to Avatar collisions
3274 } 3274 // Prim to avatar collisions
3275 else 3275
3276 { 3276 d.BodySetPosition(Body, pos.X, pos.Y, m_targetHoverHeight);
3277 float b = (1.0f - m_buoyancy); 3277 d.BodySetLinearVel(Body, vel.X, vel.Y, 0);
3278 fx = _parent_scene.gravityx * b; 3278 // ? d.BodyAddForce(Body, 0, 0, fz);
3279 fy = _parent_scene.gravityy * b; 3279 return;
3280 fz = _parent_scene.gravityz * b; 3280 }
3281 } 3281 else
3282 3282 {
3283 fx *= m_mass; 3283 _zeroFlag = false;
3284 fy *= m_mass; 3284
3285 fz *= m_mass; 3285 // We're flying and colliding with something
3286 3286 fz = ((_target_velocity.Z - vel.Z) * (PID_D));
3287 // constant force 3287 }
3288 fx += m_force.X; 3288 }
3289 fy += m_force.Y; 3289 else
3290 fz += m_force.Z; 3290 {
3291 3291 float b = (1.0f - m_buoyancy);
3292 fx += m_forceacc.X; 3292 fx = _parent_scene.gravityx * b;
3293 fy += m_forceacc.Y; 3293 fy = _parent_scene.gravityy * b;
3294 fz += m_forceacc.Z; 3294 fz = _parent_scene.gravityz * b;
3295 3295 }
3296 m_forceacc = Vector3.Zero; 3296
3297 3297 fx *= m_mass;
3298 //m_log.Info("[OBJPID]: X:" + fx.ToString() + " Y:" + fy.ToString() + " Z:" + fz.ToString()); 3298 fy *= m_mass;
3299 if (fx != 0 || fy != 0 || fz != 0) 3299 fz *= m_mass;
3300 { 3300
3301 d.BodyAddForce(Body, fx, fy, fz); 3301 // constant force
3302 //Console.WriteLine("AddForce " + fx + "," + fy + "," + fz); 3302 fx += m_force.X;
3303 } 3303 fy += m_force.Y;
3304 3304 fz += m_force.Z;
3305 Vector3 trq; 3305
3306 3306 fx += m_forceacc.X;
3307 trq = _torque; 3307 fy += m_forceacc.Y;
3308 trq += m_angularForceacc; 3308 fz += m_forceacc.Z;
3309 m_angularForceacc = Vector3.Zero; 3309
3310 if (trq.X != 0 || trq.Y != 0 || trq.Z != 0) 3310 m_forceacc = Vector3.Zero;
3311 { 3311
3312 d.BodyAddTorque(Body, trq.X, trq.Y, trq.Z); 3312 //m_log.Info("[OBJPID]: X:" + fx.ToString() + " Y:" + fy.ToString() + " Z:" + fz.ToString());
3313 } 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 else 3317 }
3318 { // is not physical, or is not a body or is selected 3318
3319 // _zeroPosition = d.BodyGetPosition(Body); 3319 Vector3 trq;
3320 return; 3320
3321 //Console.WriteLine("Nothing " + Name); 3321 trq = _torque;
3322 3322 trq += m_angularForceacc;
3323 } 3323 m_angularForceacc = Vector3.Zero;
3324 } 3324 if (trq.X != 0 || trq.Y != 0 || trq.Z != 0)
3325 3325 {
3326 3326 d.BodyAddTorque(Body, trq.X, trq.Y, trq.Z);
3327 public void UpdatePositionAndVelocity(float simulatedtime) 3327 }
3328 { 3328
3329 // no lock; called from Simulate() -- if you call this from elsewhere, gotta lock or do Monitor.Enter/Exit! 3329 }
3330 if (_parent == null && !m_disabled && !m_building && !m_outbounds) 3330 }
3331 { 3331 else
3332 if (Body != IntPtr.Zero) 3332 { // is not physical, or is not a body or is selected
3333 { 3333 // _zeroPosition = d.BodyGetPosition(Body);
3334 Vector3 pv = Vector3.Zero; 3334 return;
3335 bool lastZeroFlag = _zeroFlag; 3335 //Console.WriteLine("Nothing " + Name);
3336 3336
3337 d.Vector3 lpos; 3337 }
3338 d.GeomCopyPosition(prim_geom, out lpos); // root position that is seem by rest of simulator 3338 }
3339 3339
3340 3340
3341 d.Quaternion ori; 3341 public void UpdatePositionAndVelocity(float simulatedtime)
3342 d.GeomCopyQuaternion(prim_geom, out ori); 3342 {
3343 d.Vector3 vel = d.BodyGetLinearVel(Body); 3343 // no lock; called from Simulate() -- if you call this from elsewhere, gotta lock or do Monitor.Enter/Exit!
3344 d.Vector3 rotvel = d.BodyGetAngularVel(Body); 3344 if (_parent == null && !m_disabled && !m_building && !m_outbounds)
3345 3345 {
3346 if ((Math.Abs(m_lastposition.X - lpos.X) < 0.01) 3346 if (Body != IntPtr.Zero)
3347 && (Math.Abs(m_lastposition.Y - lpos.Y) < 0.01) 3347 {
3348 && (Math.Abs(m_lastposition.Z - lpos.Z) < 0.01) 3348 Vector3 pv = Vector3.Zero;
3349 && (Math.Abs(m_lastorientation.X - ori.X) < 0.0001) 3349 bool lastZeroFlag = _zeroFlag;
3350 && (Math.Abs(m_lastorientation.Y - ori.Y) < 0.0001) 3350
3351 && (Math.Abs(m_lastorientation.Z - ori.Z) < 0.0001) 3351 d.Vector3 lpos;
3352 ) 3352 d.GeomCopyPosition(prim_geom, out lpos); // root position that is seem by rest of simulator
3353 { 3353
3354 _zeroFlag = true; 3354
3355 //Console.WriteLine("ZFT 2"); 3355 d.Quaternion ori;
3356 m_throttleUpdates = false; 3356 d.GeomCopyQuaternion(prim_geom, out ori);
3357 } 3357 d.Vector3 vel = d.BodyGetLinearVel(Body);
3358 else 3358 d.Vector3 rotvel = d.BodyGetAngularVel(Body);
3359 { 3359
3360 //m_log.Debug(Math.Abs(m_lastposition.X - l_position.X).ToString()); 3360 if ((Math.Abs(m_lastposition.X - lpos.X) < 0.01)
3361 _zeroFlag = false; 3361 && (Math.Abs(m_lastposition.Y - lpos.Y) < 0.01)
3362 m_lastUpdateSent = false; 3362 && (Math.Abs(m_lastposition.Z - lpos.Z) < 0.01)
3363 //m_throttleUpdates = false; 3363 && (Math.Abs(m_lastorientation.X - ori.X) < 0.0001)
3364 } 3364 && (Math.Abs(m_lastorientation.Y - ori.Y) < 0.0001)
3365 3365 && (Math.Abs(m_lastorientation.Z - ori.Z) < 0.0001)
3366 if (_zeroFlag) 3366 )
3367 { 3367 {
3368 m_lastposition = _position; 3368 _zeroFlag = true;
3369 m_lastorientation = _orientation; 3369 //Console.WriteLine("ZFT 2");
3370 3370 m_throttleUpdates = false;
3371 _velocity.X = 0.0f; 3371 }
3372 _velocity.Y = 0.0f; 3372 else
3373 _velocity.Z = 0.0f; 3373 {
3374 3374 //m_log.Debug(Math.Abs(m_lastposition.X - l_position.X).ToString());
3375 _acceleration.X = 0; 3375 _zeroFlag = false;
3376 _acceleration.Y = 0; 3376 m_lastUpdateSent = false;
3377 _acceleration.Z = 0; 3377 //m_throttleUpdates = false;
3378 3378 }
3379 m_rotationalVelocity.X = 0; 3379
3380 m_rotationalVelocity.Y = 0; 3380 if (_zeroFlag)
3381 m_rotationalVelocity.Z = 0; 3381 {
3382 if (!m_lastUpdateSent) 3382 m_lastposition = _position;
3383 { 3383 m_lastorientation = _orientation;
3384 m_throttleUpdates = false; 3384
3385 throttleCounter = 0; 3385 _velocity.X = 0.0f;
3386 m_rotationalVelocity = pv; 3386 _velocity.Y = 0.0f;
3387 3387 _velocity.Z = 0.0f;
3388 base.RequestPhysicsterseUpdate(); 3388
3389 3389 _acceleration.X = 0;
3390 m_lastUpdateSent = true; 3390 _acceleration.Y = 0;
3391 } 3391 _acceleration.Z = 0;
3392 } 3392
3393 else 3393 m_rotationalVelocity.X = 0;
3394 { 3394 m_rotationalVelocity.Y = 0;
3395 if (lastZeroFlag != _zeroFlag) 3395 m_rotationalVelocity.Z = 0;
3396 { 3396 if (!m_lastUpdateSent)
3397 base.RequestPhysicsterseUpdate(); 3397 {
3398 } 3398 m_throttleUpdates = false;
3399 3399 throttleCounter = 0;
3400 m_lastVelocity = _velocity; 3400 m_rotationalVelocity = pv;
3401 3401
3402 _position.X = lpos.X; 3402 base.RequestPhysicsterseUpdate();
3403 _position.Y = lpos.Y; 3403
3404 _position.Z = lpos.Z; 3404 m_lastUpdateSent = true;
3405 3405 }
3406 _velocity.X = vel.X; 3406 }
3407 _velocity.Y = vel.Y; 3407 else
3408 _velocity.Z = vel.Z; 3408 {
3409 3409 if (lastZeroFlag != _zeroFlag)
3410 _orientation.X = ori.X; 3410 {
3411 _orientation.Y = ori.Y; 3411 base.RequestPhysicsterseUpdate();
3412 _orientation.Z = ori.Z; 3412 }
3413 _orientation.W = ori.W; 3413
3414 3414 m_lastVelocity = _velocity;
3415 _acceleration = ((_velocity - m_lastVelocity) / simulatedtime); 3415
3416 3416 _position.X = lpos.X;
3417 if (m_rotationalVelocity.ApproxEquals(pv, 0.0001f)) 3417 _position.Y = lpos.Y;
3418 { 3418 _position.Z = lpos.Z;
3419 m_rotationalVelocity = pv; 3419
3420 } 3420 _velocity.X = vel.X;
3421 else 3421 _velocity.Y = vel.Y;
3422 { 3422 _velocity.Z = vel.Z;
3423 m_rotationalVelocity.X = rotvel.X; 3423
3424 m_rotationalVelocity.Y = rotvel.Y; 3424 _orientation.X = ori.X;
3425 m_rotationalVelocity.Z = rotvel.Z; 3425 _orientation.Y = ori.Y;
3426 } 3426 _orientation.Z = ori.Z;
3427 3427 _orientation.W = ori.W;
3428 m_lastUpdateSent = false; 3428
3429 if (!m_throttleUpdates || throttleCounter > _parent_scene.geomUpdatesPerThrottledUpdate) 3429 _acceleration = ((_velocity - m_lastVelocity) / simulatedtime);
3430 { 3430
3431 m_lastposition = _position; 3431 if (m_rotationalVelocity.ApproxEquals(pv, 0.0001f))
3432 m_lastorientation = _orientation; 3432 {
3433 base.RequestPhysicsterseUpdate(); 3433 m_rotationalVelocity = pv;
3434 } 3434 }
3435 else 3435 else
3436 { 3436 {
3437 throttleCounter++; 3437 m_rotationalVelocity.X = rotvel.X;
3438 } 3438 m_rotationalVelocity.Y = rotvel.Y;
3439 } 3439 m_rotationalVelocity.Z = rotvel.Z;
3440 } 3440 }
3441 else if (!m_lastUpdateSent || !_zeroFlag) 3441
3442 { 3442 m_lastUpdateSent = false;
3443 // Not a body.. so Make sure the client isn't interpolating 3443 if (!m_throttleUpdates || throttleCounter > _parent_scene.geomUpdatesPerThrottledUpdate)
3444 _velocity.X = 0; 3444 {
3445 _velocity.Y = 0; 3445 m_lastposition = _position;
3446 _velocity.Z = 0; 3446 m_lastorientation = _orientation;
3447 3447 base.RequestPhysicsterseUpdate();
3448 _acceleration.X = 0; 3448 }
3449 _acceleration.Y = 0; 3449 else
3450 _acceleration.Z = 0; 3450 {
3451 3451 throttleCounter++;
3452 m_rotationalVelocity.X = 0; 3452 }
3453 m_rotationalVelocity.Y = 0; 3453 }
3454 m_rotationalVelocity.Z = 0; 3454 }
3455 _zeroFlag = true; 3455 else if (!m_lastUpdateSent || !_zeroFlag)
3456 3456 {
3457 if (!m_lastUpdateSent) 3457 // Not a body.. so Make sure the client isn't interpolating
3458 { 3458 _velocity.X = 0;
3459 m_throttleUpdates = false; 3459 _velocity.Y = 0;
3460 throttleCounter = 0; 3460 _velocity.Z = 0;
3461 3461
3462 base.RequestPhysicsterseUpdate(); 3462 _acceleration.X = 0;
3463 3463 _acceleration.Y = 0;
3464 m_lastUpdateSent = true; 3464 _acceleration.Z = 0;
3465 } 3465
3466 } 3466 m_rotationalVelocity.X = 0;
3467 } 3467 m_rotationalVelocity.Y = 0;
3468 } 3468 m_rotationalVelocity.Z = 0;
3469 3469 _zeroFlag = true;
3470 internal static bool QuaternionIsFinite(Quaternion q) 3470
3471 { 3471 if (!m_lastUpdateSent)
3472 if (Single.IsNaN(q.X) || Single.IsInfinity(q.X)) 3472 {
3473 return false; 3473 m_throttleUpdates = false;
3474 if (Single.IsNaN(q.Y) || Single.IsInfinity(q.Y)) 3474 throttleCounter = 0;
3475 return false; 3475
3476 if (Single.IsNaN(q.Z) || Single.IsInfinity(q.Z)) 3476 base.RequestPhysicsterseUpdate();
3477 return false; 3477
3478 if (Single.IsNaN(q.W) || Single.IsInfinity(q.W)) 3478 m_lastUpdateSent = true;
3479 return false; 3479 }
3480 return true; 3480 }
3481 } 3481 }
3482 3482 }
3483 internal static void DMassCopy(ref d.Mass src, ref d.Mass dst) 3483
3484 { 3484 internal static bool QuaternionIsFinite(Quaternion q)
3485 dst.c.W = src.c.W; 3485 {
3486 dst.c.X = src.c.X; 3486 if (Single.IsNaN(q.X) || Single.IsInfinity(q.X))
3487 dst.c.Y = src.c.Y; 3487 return false;
3488 dst.c.Z = src.c.Z; 3488 if (Single.IsNaN(q.Y) || Single.IsInfinity(q.Y))
3489 dst.mass = src.mass; 3489 return false;
3490 dst.I.M00 = src.I.M00; 3490 if (Single.IsNaN(q.Z) || Single.IsInfinity(q.Z))
3491 dst.I.M01 = src.I.M01; 3491 return false;
3492 dst.I.M02 = src.I.M02; 3492 if (Single.IsNaN(q.W) || Single.IsInfinity(q.W))
3493 dst.I.M10 = src.I.M10; 3493 return false;
3494 dst.I.M11 = src.I.M11; 3494 return true;
3495 dst.I.M12 = src.I.M12; 3495 }
3496 dst.I.M20 = src.I.M20; 3496
3497 dst.I.M21 = src.I.M21; 3497 internal static void DMassCopy(ref d.Mass src, ref d.Mass dst)
3498 dst.I.M22 = src.I.M22; 3498 {
3499 } 3499 dst.c.W = src.c.W;
3500 3500 dst.c.X = src.c.X;
3501 private static void DMassDup(ref d.Mass src, out d.Mass dst) 3501 dst.c.Y = src.c.Y;
3502 { 3502 dst.c.Z = src.c.Z;
3503 dst = new d.Mass { }; 3503 dst.mass = src.mass;
3504 3504 dst.I.M00 = src.I.M00;
3505 dst.c.W = src.c.W; 3505 dst.I.M01 = src.I.M01;
3506 dst.c.X = src.c.X; 3506 dst.I.M02 = src.I.M02;
3507 dst.c.Y = src.c.Y; 3507 dst.I.M10 = src.I.M10;
3508 dst.c.Z = src.c.Z; 3508 dst.I.M11 = src.I.M11;
3509 dst.mass = src.mass; 3509 dst.I.M12 = src.I.M12;
3510 dst.I.M00 = src.I.M00; 3510 dst.I.M20 = src.I.M20;
3511 dst.I.M01 = src.I.M01; 3511 dst.I.M21 = src.I.M21;
3512 dst.I.M02 = src.I.M02; 3512 dst.I.M22 = src.I.M22;
3513 dst.I.M10 = src.I.M10; 3513 }
3514 dst.I.M11 = src.I.M11; 3514
3515 dst.I.M12 = src.I.M12; 3515 private static void DMassDup(ref d.Mass src, out d.Mass dst)
3516 dst.I.M20 = src.I.M20; 3516 {
3517 dst.I.M21 = src.I.M21; 3517 dst = new d.Mass { };
3518 dst.I.M22 = src.I.M22; 3518
3519 } 3519 dst.c.W = src.c.W;
3520 private void donullchange() 3520 dst.c.X = src.c.X;
3521 { 3521 dst.c.Y = src.c.Y;
3522 } 3522 dst.c.Z = src.c.Z;
3523 3523 dst.mass = src.mass;
3524 public bool DoAChange(changes what, object arg) 3524 dst.I.M00 = src.I.M00;
3525 { 3525 dst.I.M01 = src.I.M01;
3526 if (prim_geom == IntPtr.Zero && what != changes.Add && what != changes.Remove) 3526 dst.I.M02 = src.I.M02;
3527 { 3527 dst.I.M10 = src.I.M10;
3528 return false; 3528 dst.I.M11 = src.I.M11;
3529 } 3529 dst.I.M12 = src.I.M12;
3530 3530 dst.I.M20 = src.I.M20;
3531 // nasty switch 3531 dst.I.M21 = src.I.M21;
3532 switch (what) 3532 dst.I.M22 = src.I.M22;
3533 { 3533 }
3534 case changes.Add: 3534 private void donullchange()
3535 changeadd(); 3535 {
3536 break; 3536 }
3537 case changes.Remove: 3537
3538 //If its being removed, we don't want to rebuild the physical rep at all, so ignore this stuff... 3538 public bool DoAChange(changes what, object arg)
3539 //When we return true, it destroys all of the prims in the linkset anyway 3539 {
3540 if (_parent != null) 3540 if (prim_geom == IntPtr.Zero && what != changes.Add && what != changes.Remove)
3541 { 3541 {
3542 OdePrim parent = (OdePrim)_parent; 3542 return false;
3543 parent.ChildRemove(this, false); 3543 }
3544 } 3544
3545 else 3545 // nasty switch
3546 ChildRemove(this, false); 3546 switch (what)
3547 3547 {
3548 m_vehicle = null; 3548 case changes.Add:
3549 RemoveGeom(); 3549 changeadd();
3550 m_targetSpace = IntPtr.Zero; 3550 break;
3551 if (m_eventsubscription > 0) 3551 case changes.Remove:
3552 UnSubscribeEvents(); 3552 //If its being removed, we don't want to rebuild the physical rep at all, so ignore this stuff...
3553 return true; 3553 //When we return true, it destroys all of the prims in the linkset anyway
3554 3554 if (_parent != null)
3555 case changes.Link: 3555 {
3556 OdePrim tmp = (OdePrim)arg; 3556 OdePrim parent = (OdePrim)_parent;
3557 changeLink(tmp); 3557 parent.ChildRemove(this, false);
3558 break; 3558 }
3559 3559 else
3560 case changes.DeLink: 3560 ChildRemove(this, false);
3561 changeLink(null); 3561
3562 break; 3562 m_vehicle = null;
3563 3563 RemoveGeom();
3564 case changes.Position: 3564 m_targetSpace = IntPtr.Zero;
3565 changePosition((Vector3)arg); 3565 if (m_eventsubscription > 0)
3566 break; 3566 UnSubscribeEvents();
3567 3567 return true;
3568 case changes.Orientation: 3568
3569 changeOrientation((Quaternion)arg); 3569 case changes.Link:
3570 break; 3570 OdePrim tmp = (OdePrim)arg;
3571 3571 changeLink(tmp);
3572 case changes.PosOffset: 3572 break;
3573 donullchange(); 3573
3574 break; 3574 case changes.DeLink:
3575 3575 changeLink(null);
3576 case changes.OriOffset: 3576 break;
3577 donullchange(); 3577
3578 break; 3578 case changes.Position:
3579 3579 changePosition((Vector3)arg);
3580 case changes.Velocity: 3580 break;
3581 changevelocity((Vector3)arg); 3581
3582 break; 3582 case changes.Orientation:
3583 3583 changeOrientation((Quaternion)arg);
3584 // case changes.Acceleration: 3584 break;
3585 // changeacceleration((Vector3)arg); 3585
3586 // break; 3586 case changes.PosOffset:
3587 // case changes.AngVelocity: 3587 donullchange();
3588 // changeangvelocity((Vector3)arg); 3588 break;
3589 // break; 3589
3590 3590 case changes.OriOffset:
3591 case changes.Force: 3591 donullchange();
3592 changeForce((Vector3)arg); 3592 break;
3593 break; 3593
3594 3594 case changes.Velocity:
3595 case changes.Torque: 3595 changevelocity((Vector3)arg);
3596 changeSetTorque((Vector3)arg); 3596 break;
3597 break; 3597
3598 3598 // case changes.Acceleration:
3599 case changes.AddForce: 3599 // changeacceleration((Vector3)arg);
3600 changeAddForce((Vector3)arg); 3600 // break;
3601 break; 3601 // case changes.AngVelocity:
3602 3602 // changeangvelocity((Vector3)arg);
3603 case changes.AddAngForce: 3603 // break;
3604 changeAddAngularForce((Vector3)arg); 3604
3605 break; 3605 case changes.Force:
3606 3606 changeForce((Vector3)arg);
3607 case changes.AngLock: 3607 break;
3608 changeAngularLock((Vector3)arg); 3608
3609 break; 3609 case changes.Torque:
3610 3610 changeSetTorque((Vector3)arg);
3611 case changes.Size: 3611 break;
3612 changeSize((Vector3)arg); 3612
3613 break; 3613 case changes.AddForce:
3614 3614 changeAddForce((Vector3)arg);
3615 case changes.Shape: 3615 break;
3616 changeShape((PrimitiveBaseShape)arg); 3616
3617 break; 3617 case changes.AddAngForce:
3618 3618 changeAddAngularForce((Vector3)arg);
3619 case changes.CollidesWater: 3619 break;
3620 changeFloatOnWater((bool)arg); 3620
3621 break; 3621 case changes.AngLock:
3622 3622 changeAngularLock((Vector3)arg);
3623 case changes.VolumeDtc: 3623 break;
3624 changeVolumedetetion((bool)arg); 3624
3625 break; 3625 case changes.Size:
3626 3626 changeSize((Vector3)arg);
3627 case changes.Phantom: 3627 break;
3628 changePhantomStatus((bool)arg); 3628
3629 break; 3629 case changes.Shape:
3630 3630 changeShape((PrimitiveBaseShape)arg);
3631 case changes.Physical: 3631 break;
3632 changePhysicsStatus((bool)arg); 3632
3633 break; 3633 case changes.CollidesWater:
3634 3634 changeFloatOnWater((bool)arg);
3635 case changes.Selected: 3635 break;
3636 changeSelectedStatus((bool)arg); 3636
3637 break; 3637 case changes.VolumeDtc:
3638 3638 changeVolumedetetion((bool)arg);
3639 case changes.disabled: 3639 break;
3640 changeDisable((bool)arg); 3640
3641 break; 3641 case changes.Phantom:
3642 3642 changePhantomStatus((bool)arg);
3643 case changes.building: 3643 break;
3644 changeBuilding((bool)arg); 3644
3645 break; 3645 case changes.Physical:
3646 3646 changePhysicsStatus((bool)arg);
3647 case changes.VehicleType: 3647 break;
3648 changeVehicleType((int)arg); 3648
3649 break; 3649 case changes.Selected:
3650 3650 changeSelectedStatus((bool)arg);
3651 case changes.VehicleFlags: 3651 break;
3652 changeVehicleFlags((strVehicleBoolParam) arg); 3652
3653 break; 3653 case changes.disabled:
3654 3654 changeDisable((bool)arg);
3655 case changes.VehicleFloatParam: 3655 break;
3656 changeVehicleFloatParam((strVehicleFloatParam) arg); 3656
3657 break; 3657 case changes.building:
3658 3658 changeBuilding((bool)arg);
3659 case changes.VehicleVectorParam: 3659 break;
3660 changeVehicleVectorParam((strVehicleVectorParam) arg); 3660
3661 break; 3661 case changes.VehicleType:
3662 3662 changeVehicleType((int)arg);
3663 case changes.VehicleRotationParam: 3663 break;
3664 changeVehicleRotationParam((strVehicleQuatParam) arg); 3664
3665 break; 3665 case changes.VehicleFlags:
3666 3666 changeVehicleFlags((strVehicleBoolParam) arg);
3667 case changes.SetVehicle: 3667 break;
3668 changeSetVehicle((VehicleData) arg); 3668
3669 break; 3669 case changes.VehicleFloatParam:
3670 case changes.Null: 3670 changeVehicleFloatParam((strVehicleFloatParam) arg);
3671 donullchange(); 3671 break;
3672 break; 3672
3673 3673 case changes.VehicleVectorParam:
3674 default: 3674 changeVehicleVectorParam((strVehicleVectorParam) arg);
3675 donullchange(); 3675 break;
3676 break; 3676
3677 } 3677 case changes.VehicleRotationParam:
3678 return false; 3678 changeVehicleRotationParam((strVehicleQuatParam) arg);
3679 } 3679 break;
3680 3680
3681 public void AddChange(changes what, object arg) 3681 case changes.SetVehicle:
3682 { 3682 changeSetVehicle((VehicleData) arg);
3683 _parent_scene.AddChange((PhysicsActor) this, what, arg); 3683 break;
3684 } 3684 case changes.Null:
3685 3685 donullchange();
3686 3686 break;
3687 private struct strVehicleBoolParam 3687
3688 { 3688 default:
3689 public int param; 3689 donullchange();
3690 public bool value; 3690 break;
3691 } 3691 }
3692 3692 return false;
3693 private struct strVehicleFloatParam 3693 }
3694 { 3694
3695 public int param; 3695 public void AddChange(changes what, object arg)
3696 public float value; 3696 {
3697 } 3697 _parent_scene.AddChange((PhysicsActor) this, what, arg);
3698 3698 }
3699 private struct strVehicleQuatParam 3699
3700 { 3700
3701 public int param; 3701 private struct strVehicleBoolParam
3702 public Quaternion value; 3702 {
3703 } 3703 public int param;
3704 3704 public bool value;
3705 private struct strVehicleVectorParam 3705 }
3706 { 3706
3707 public int param; 3707 private struct strVehicleFloatParam
3708 public Vector3 value; 3708 {
3709 } 3709 public int param;
3710 } 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 }
3711} \ No newline at end of file 3725} \ No newline at end of file