diff options
author | MW | 2007-09-11 07:04:05 +0000 |
---|---|---|
committer | MW | 2007-09-11 07:04:05 +0000 |
commit | e2e13a9756e1de21e1b11a9dba7105f831b0df30 (patch) | |
tree | ce1c283826b1056af569f4a6d7b575247d110071 /OpenSim/Region/Physics/BulletXPlugin/BulletXPlugin.cs | |
parent | add DeleteAsset (diff) | |
download | opensim-SC-e2e13a9756e1de21e1b11a9dba7105f831b0df30.zip opensim-SC-e2e13a9756e1de21e1b11a9dba7105f831b0df30.tar.gz opensim-SC-e2e13a9756e1de21e1b11a9dba7105f831b0df30.tar.bz2 opensim-SC-e2e13a9756e1de21e1b11a9dba7105f831b0df30.tar.xz |
Added part 3 of Darok's BulletX patch. The bulletX plugin is now a project in the opensim build/solution. To use change the physics setting in opensim.ini to "modified_BulletX". At the moment I have been unable to test this as when using the bulletX plugin for me opensim is using 100% of processor.
Diffstat (limited to '')
-rw-r--r-- | OpenSim/Region/Physics/BulletXPlugin/BulletXPlugin.cs | 575 |
1 files changed, 485 insertions, 90 deletions
diff --git a/OpenSim/Region/Physics/BulletXPlugin/BulletXPlugin.cs b/OpenSim/Region/Physics/BulletXPlugin/BulletXPlugin.cs index 45723e3..6d8e1a8 100644 --- a/OpenSim/Region/Physics/BulletXPlugin/BulletXPlugin.cs +++ b/OpenSim/Region/Physics/BulletXPlugin/BulletXPlugin.cs | |||
@@ -1,11 +1,10 @@ | |||
1 | #region Copyright | 1 | #region Copyright |
2 | /* | 2 | /* |
3 | * Copyright (c) Contributors, http://opensimulator.org/ | 3 | * Copyright (c) Contributors, http://www.openmetaverse.org/ |
4 | * See CONTRIBUTORS.TXT for a full list of copyright holders. | 4 | * See CONTRIBUTORS.TXT for a full list of copyright holders. |
5 | * | 5 | * |
6 | * Redistribution and use in source and binary forms, with or without | 6 | * Redistribution and use in source and binary forms, with or without |
7 | * modification, are permitted provided that the following conditions are | 7 | * modification, are permitted provided that the following conditions are met: |
8 | met: | ||
9 | * * Redistributions of source code must retain the above copyright | 8 | * * Redistributions of source code must retain the above copyright |
10 | * notice, this list of conditions and the following disclaimer. | 9 | * notice, this list of conditions and the following disclaimer. |
11 | * * Redistributions in binary form must reproduce the above copyright | 10 | * * Redistributions in binary form must reproduce the above copyright |
@@ -13,23 +12,19 @@ met: | |||
13 | * documentation and/or other materials provided with the distribution. | 12 | * documentation and/or other materials provided with the distribution. |
14 | * * Neither the name of the OpenSim Project nor the | 13 | * * Neither the name of the OpenSim Project nor the |
15 | * names of its contributors may be used to endorse or promote products | 14 | * names of its contributors may be used to endorse or promote products |
16 | * derived from this software without specific prior written | 15 | * derived from this software without specific prior written permission. |
17 | permission. | ||
18 | * | 16 | * |
19 | * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS AND ANY | 17 | * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS AND ANY |
20 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | 18 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
21 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | 19 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
22 | * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY | 20 | * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY |
23 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | 21 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
24 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | 22 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
25 | SERVICES; | 23 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
26 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED | ||
27 | AND | ||
28 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 24 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
29 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 25 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
30 | THIS | ||
31 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 26 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
32 | * | 27 | * |
33 | */ | 28 | */ |
34 | #endregion | 29 | #endregion |
35 | #region References | 30 | #region References |
@@ -47,9 +42,10 @@ using XnaDevRu.BulletX.Dynamics; | |||
47 | namespace OpenSim.Region.Physics.BulletXPlugin | 42 | namespace OpenSim.Region.Physics.BulletXPlugin |
48 | { | 43 | { |
49 | /// <summary> | 44 | /// <summary> |
50 | /// This Class converts objects and types for BulletX | 45 | /// BulletXConversions are called now BulletXMaths |
46 | /// This Class converts objects and types for BulletX and give some operations | ||
51 | /// </summary> | 47 | /// </summary> |
52 | public class BulletXConversions | 48 | public class BulletXMaths |
53 | { | 49 | { |
54 | //Vector3 | 50 | //Vector3 |
55 | public static MonoXnaCompactMaths.Vector3 PhysicsVectorToXnaVector3(PhysicsVector physicsVector) | 51 | public static MonoXnaCompactMaths.Vector3 PhysicsVectorToXnaVector3(PhysicsVector physicsVector) |
@@ -69,6 +65,114 @@ namespace OpenSim.Region.Physics.BulletXPlugin | |||
69 | { | 65 | { |
70 | return new AxiomQuaternion(xnaQuaternion.W, xnaQuaternion.X, xnaQuaternion.Y, xnaQuaternion.Z); | 66 | return new AxiomQuaternion(xnaQuaternion.W, xnaQuaternion.X, xnaQuaternion.Y, xnaQuaternion.Z); |
71 | } | 67 | } |
68 | |||
69 | //Next methods are extracted from XnaDevRu.BulletX(See 3rd party license): | ||
70 | //- SetRotation (class MatrixOperations) | ||
71 | //- GetRotation (class MatrixOperations) | ||
72 | //- GetElement (class MathHelper) | ||
73 | //- SetElement (class MathHelper) | ||
74 | internal static void SetRotation(ref Matrix m, MonoXnaCompactMaths.Quaternion q) | ||
75 | { | ||
76 | float d = q.LengthSquared(); | ||
77 | float s = 2f / d; | ||
78 | float xs = q.X * s, ys = q.Y * s, zs = q.Z * s; | ||
79 | float wx = q.W * xs, wy = q.W * ys, wz = q.W * zs; | ||
80 | float xx = q.X * xs, xy = q.X * ys, xz = q.X * zs; | ||
81 | float yy = q.Y * ys, yz = q.Y * zs, zz = q.Z * zs; | ||
82 | m = new Matrix(1 - (yy + zz), xy - wz, xz + wy, 0, | ||
83 | xy + wz, 1 - (xx + zz), yz - wx, 0, | ||
84 | xz - wy, yz + wx, 1 - (xx + yy), 0, | ||
85 | m.M41, m.M42, m.M43, 1); | ||
86 | } | ||
87 | internal static MonoXnaCompactMaths.Quaternion GetRotation(Matrix m) | ||
88 | { | ||
89 | MonoXnaCompactMaths.Quaternion q = new MonoXnaCompactMaths.Quaternion(); | ||
90 | |||
91 | float trace = m.M11 + m.M22 + m.M33; | ||
92 | |||
93 | if (trace > 0) | ||
94 | { | ||
95 | float s = (float)Math.Sqrt(trace + 1); | ||
96 | q.W = s * 0.5f; | ||
97 | s = 0.5f / s; | ||
98 | |||
99 | q.X = (m.M32 - m.M23) * s; | ||
100 | q.Y = (m.M13 - m.M31) * s; | ||
101 | q.Z = (m.M21 - m.M12) * s; | ||
102 | } | ||
103 | else | ||
104 | { | ||
105 | int i = m.M11 < m.M22 ? | ||
106 | (m.M22 < m.M33 ? 2 : 1) : | ||
107 | (m.M11 < m.M33 ? 2 : 0); | ||
108 | int j = (i + 1) % 3; | ||
109 | int k = (i + 2) % 3; | ||
110 | |||
111 | float s = (float)Math.Sqrt(GetElement(m, i, i) - GetElement(m, j, j) - GetElement(m, k, k) + 1); | ||
112 | SetElement(ref q, i, s * 0.5f); | ||
113 | s = 0.5f / s; | ||
114 | |||
115 | q.W = (GetElement(m, k, j) - GetElement(m, j, k)) * s; | ||
116 | SetElement(ref q, j, (GetElement(m, j, i) + GetElement(m, i, j)) * s); | ||
117 | SetElement(ref q, k, (GetElement(m, k, i) + GetElement(m, i, k)) * s); | ||
118 | } | ||
119 | |||
120 | return q; | ||
121 | } | ||
122 | internal static float SetElement(ref MonoXnaCompactMaths.Quaternion q, int index, float value) | ||
123 | { | ||
124 | switch (index) | ||
125 | { | ||
126 | case 0: | ||
127 | q.X = value; break; | ||
128 | case 1: | ||
129 | q.Y = value; break; | ||
130 | case 2: | ||
131 | q.Z = value; break; | ||
132 | case 3: | ||
133 | q.W = value; break; | ||
134 | } | ||
135 | |||
136 | return 0; | ||
137 | } | ||
138 | internal static float GetElement(Matrix mat, int row, int col) | ||
139 | { | ||
140 | switch (row) | ||
141 | { | ||
142 | case 0: | ||
143 | switch (col) | ||
144 | { | ||
145 | case 0: | ||
146 | return mat.M11; | ||
147 | case 1: | ||
148 | return mat.M12; | ||
149 | case 2: | ||
150 | return mat.M13; | ||
151 | } break; | ||
152 | case 1: | ||
153 | switch (col) | ||
154 | { | ||
155 | case 0: | ||
156 | return mat.M21; | ||
157 | case 1: | ||
158 | return mat.M22; | ||
159 | case 2: | ||
160 | return mat.M23; | ||
161 | } break; | ||
162 | case 2: | ||
163 | switch (col) | ||
164 | { | ||
165 | case 0: | ||
166 | return mat.M31; | ||
167 | case 1: | ||
168 | return mat.M32; | ||
169 | case 2: | ||
170 | return mat.M33; | ||
171 | } break; | ||
172 | } | ||
173 | |||
174 | return 0; | ||
175 | } | ||
72 | } | 176 | } |
73 | /// <summary> | 177 | /// <summary> |
74 | /// PhysicsPlugin Class for BulletX | 178 | /// PhysicsPlugin Class for BulletX |
@@ -94,7 +198,7 @@ namespace OpenSim.Region.Physics.BulletXPlugin | |||
94 | } | 198 | } |
95 | public string GetName() | 199 | public string GetName() |
96 | { | 200 | { |
97 | return ("BulletXEngine"); | 201 | return ("modified_BulletX");//Changed!! "BulletXEngine" To "modified_BulletX" |
98 | } | 202 | } |
99 | public void Dispose() | 203 | public void Dispose() |
100 | { | 204 | { |
@@ -105,10 +209,12 @@ namespace OpenSim.Region.Physics.BulletXPlugin | |||
105 | /// </summary> | 209 | /// </summary> |
106 | public class BulletXScene : PhysicsScene | 210 | public class BulletXScene : PhysicsScene |
107 | { | 211 | { |
212 | #region BulletXScene Fields | ||
108 | public DiscreteDynamicsWorld ddWorld; | 213 | public DiscreteDynamicsWorld ddWorld; |
109 | private CollisionDispatcher cDispatcher; | 214 | private CollisionDispatcher cDispatcher; |
110 | private OverlappingPairCache opCache; | 215 | private OverlappingPairCache opCache; |
111 | private SequentialImpulseConstraintSolver sicSolver; | 216 | private SequentialImpulseConstraintSolver sicSolver; |
217 | public static Object BulletXLock = new Object(); | ||
112 | 218 | ||
113 | private const int minXY = 0; | 219 | private const int minXY = 0; |
114 | private const int minZ = 0; | 220 | private const int minZ = 0; |
@@ -128,6 +234,7 @@ namespace OpenSim.Region.Physics.BulletXPlugin | |||
128 | public static float HeightLevel0 { get { return heightLevel0; } } | 234 | public static float HeightLevel0 { get { return heightLevel0; } } |
129 | public static float HeightLevel1 { get { return heightLevel1; } } | 235 | public static float HeightLevel1 { get { return heightLevel1; } } |
130 | public static float LowGravityFactor { get { return lowGravityFactor; } } | 236 | public static float LowGravityFactor { get { return lowGravityFactor; } } |
237 | #endregion | ||
131 | 238 | ||
132 | public BulletXScene() | 239 | public BulletXScene() |
133 | { | 240 | { |
@@ -137,8 +244,11 @@ namespace OpenSim.Region.Physics.BulletXPlugin | |||
137 | opCache = new AxisSweep3(worldMinDim, worldMaxDim, maxHandles); | 244 | opCache = new AxisSweep3(worldMinDim, worldMaxDim, maxHandles); |
138 | sicSolver = new SequentialImpulseConstraintSolver(); | 245 | sicSolver = new SequentialImpulseConstraintSolver(); |
139 | 246 | ||
140 | ddWorld = new DiscreteDynamicsWorld(cDispatcher, opCache, sicSolver); | 247 | lock (BulletXLock) |
141 | ddWorld.Gravity = new MonoXnaCompactMaths.Vector3(0, 0, -gravity); | 248 | { |
249 | ddWorld = new DiscreteDynamicsWorld(cDispatcher, opCache, sicSolver); | ||
250 | ddWorld.Gravity = new MonoXnaCompactMaths.Vector3(0, 0, -gravity); | ||
251 | } | ||
142 | 252 | ||
143 | this._heightmap = new float[65536]; | 253 | this._heightmap = new float[65536]; |
144 | } | 254 | } |
@@ -148,47 +258,110 @@ namespace OpenSim.Region.Physics.BulletXPlugin | |||
148 | pos.X = position.X; | 258 | pos.X = position.X; |
149 | pos.Y = position.Y; | 259 | pos.Y = position.Y; |
150 | pos.Z = position.Z + 20; | 260 | pos.Z = position.Z + 20; |
151 | BulletXCharacter newAv = new BulletXCharacter(this, pos); | 261 | BulletXCharacter newAv = null; |
152 | _characters.Add(newAv); | 262 | lock (BulletXLock) |
263 | { | ||
264 | newAv = new BulletXCharacter(this, pos); | ||
265 | _characters.Add(newAv); | ||
266 | } | ||
153 | return newAv; | 267 | return newAv; |
154 | } | 268 | } |
155 | public override void RemoveAvatar(PhysicsActor actor) | 269 | public override void RemoveAvatar(PhysicsActor actor) |
156 | { | 270 | { |
157 | if (actor is BulletXCharacter) | 271 | if (actor is BulletXCharacter) |
158 | { | 272 | { |
159 | _characters.Remove((BulletXCharacter)actor); | 273 | lock (BulletXLock) |
274 | { | ||
275 | _characters.Remove((BulletXCharacter)actor); | ||
276 | } | ||
160 | } | 277 | } |
161 | } | 278 | } |
162 | public override PhysicsActor AddPrim(PhysicsVector position, PhysicsVector size, AxiomQuaternion rotation) | 279 | public override PhysicsActor AddPrim(PhysicsVector position, PhysicsVector size, AxiomQuaternion rotation) |
163 | { | 280 | { |
164 | return new BulletXPrim(this, position, size, rotation); | 281 | BulletXPrim newPrim = null; |
282 | lock (BulletXLock) | ||
283 | { | ||
284 | newPrim = new BulletXPrim(this, position, size, rotation); | ||
285 | _prims.Add(newPrim); | ||
286 | } | ||
287 | return newPrim; | ||
165 | } | 288 | } |
166 | public override void RemovePrim(PhysicsActor prim) | 289 | public override void RemovePrim(PhysicsActor prim) |
167 | { | 290 | { |
168 | if (prim is BulletXPrim) | 291 | if (prim is BulletXPrim) |
169 | { | 292 | { |
170 | _prims.Remove((BulletXPrim)prim); | 293 | lock (BulletXLock) |
294 | { | ||
295 | _prims.Remove((BulletXPrim)prim); | ||
296 | } | ||
171 | } | 297 | } |
172 | } | 298 | } |
173 | public override void Simulate(float timeStep) | 299 | public override void Simulate(float timeStep) |
174 | { | 300 | { |
301 | lock (BulletXLock) | ||
302 | { | ||
303 | BXSMove(timeStep); | ||
304 | ddWorld.StepSimulation(timeStep, 0, timeStep); | ||
305 | //Heightmap Validation: | ||
306 | BXSValidateHeight(); | ||
307 | //End heightmap validation. | ||
308 | BXSUpdateKinetics(); | ||
309 | } | ||
310 | } | ||
311 | private void BXSMove(float timeStep) | ||
312 | { | ||
175 | foreach (BulletXCharacter actor in _characters) | 313 | foreach (BulletXCharacter actor in _characters) |
176 | { | 314 | { |
177 | actor.Move(timeStep); | 315 | actor.Move(timeStep); |
178 | |||
179 | } | 316 | } |
180 | ddWorld.StepSimulation(timeStep, 0, timeStep); | 317 | foreach (BulletXPrim prim in _prims) |
318 | { | ||
319 | } | ||
320 | } | ||
321 | private void BXSValidateHeight() | ||
322 | { | ||
323 | float _height; | ||
181 | foreach (BulletXCharacter actor in _characters) | 324 | foreach (BulletXCharacter actor in _characters) |
182 | { | 325 | { |
183 | actor.ValidateHeight(this._heightmap[ | 326 | if ((actor.RigidBodyHorizontalPosition.x < 0) || (actor.RigidBodyHorizontalPosition.y < 0)) |
327 | { | ||
328 | _height = 0; | ||
329 | } | ||
330 | else | ||
331 | { | ||
332 | _height = this._heightmap[ | ||
184 | (int)Math.Round(actor.RigidBodyHorizontalPosition.x) * 256 | 333 | (int)Math.Round(actor.RigidBodyHorizontalPosition.x) * 256 |
185 | + (int)Math.Round(actor.RigidBodyHorizontalPosition.y)]); | 334 | + (int)Math.Round(actor.RigidBodyHorizontalPosition.y)]; |
335 | } | ||
336 | actor.ValidateHeight(_height); | ||
186 | } | 337 | } |
338 | foreach (BulletXPrim prim in _prims) | ||
339 | { | ||
340 | if ((prim.RigidBodyHorizontalPosition.x < 0) || (prim.RigidBodyHorizontalPosition.y < 0)) | ||
341 | { | ||
342 | _height = 0; | ||
343 | } | ||
344 | else | ||
345 | { | ||
346 | _height = this._heightmap[ | ||
347 | (int)Math.Round(prim.RigidBodyHorizontalPosition.x) * 256 | ||
348 | + (int)Math.Round(prim.RigidBodyHorizontalPosition.y)]; | ||
349 | } | ||
350 | prim.ValidateHeight(_height); | ||
351 | } | ||
352 | } | ||
353 | private void BXSUpdateKinetics() | ||
354 | { | ||
355 | //UpdatePosition > UpdateKinetics. | ||
356 | //Not only position will be updated, also velocity cause acceleration. | ||
187 | foreach (BulletXCharacter actor in _characters) | 357 | foreach (BulletXCharacter actor in _characters) |
188 | { | 358 | { |
189 | actor.UpdatePosition(); | 359 | actor.UpdateKinetics(); |
360 | } | ||
361 | foreach (BulletXPrim prim in _prims) | ||
362 | { | ||
363 | prim.UpdateKinetics(); | ||
190 | } | 364 | } |
191 | |||
192 | } | 365 | } |
193 | public override void GetResults() | 366 | public override void GetResults() |
194 | { | 367 | { |
@@ -212,6 +385,10 @@ namespace OpenSim.Region.Physics.BulletXPlugin | |||
212 | int y = i >> 8; | 385 | int y = i >> 8; |
213 | this._heightmap[i] = heightMap[x * 256 + y]; | 386 | this._heightmap[i] = heightMap[x * 256 + y]; |
214 | } | 387 | } |
388 | lock (BulletXLock) | ||
389 | { | ||
390 | //Updating BulletX HeightMap??? | ||
391 | } | ||
215 | } | 392 | } |
216 | public override void DeleteTerrain() | 393 | public override void DeleteTerrain() |
217 | { | 394 | { |
@@ -230,6 +407,7 @@ namespace OpenSim.Region.Physics.BulletXPlugin | |||
230 | private AxiomQuaternion _orientation; | 407 | private AxiomQuaternion _orientation; |
231 | private bool flying; | 408 | private bool flying; |
232 | private RigidBody rigidBody; | 409 | private RigidBody rigidBody; |
410 | |||
233 | public Axiom.Math.Vector2 RigidBodyHorizontalPosition | 411 | public Axiom.Math.Vector2 RigidBodyHorizontalPosition |
234 | { | 412 | { |
235 | get | 413 | get |
@@ -245,31 +423,46 @@ namespace OpenSim.Region.Physics.BulletXPlugin | |||
245 | public BulletXCharacter(BulletXScene parent_scene, PhysicsVector pos, PhysicsVector velocity, | 423 | public BulletXCharacter(BulletXScene parent_scene, PhysicsVector pos, PhysicsVector velocity, |
246 | PhysicsVector size, PhysicsVector acceleration, AxiomQuaternion orientation) | 424 | PhysicsVector size, PhysicsVector acceleration, AxiomQuaternion orientation) |
247 | { | 425 | { |
426 | //This fields will be removed. They're temporal | ||
427 | float _sizeX = 0.5f; | ||
428 | float _sizeY = 0.5f; | ||
429 | float _sizeZ = 1.6f; | ||
430 | //. | ||
248 | _position = pos; | 431 | _position = pos; |
249 | _velocity = velocity; | 432 | _velocity = velocity; |
250 | _size = size; | 433 | _size = size; |
434 | //--- | ||
435 | _size.X = _sizeX; | ||
436 | _size.Y = _sizeY; | ||
437 | _size.Z = _sizeZ; | ||
438 | //. | ||
251 | _acceleration = acceleration; | 439 | _acceleration = acceleration; |
252 | _orientation = orientation; | 440 | _orientation = orientation; |
253 | float _mass = 50.0f; //This depends of avatar's dimensions | 441 | float _mass = 50.0f; //This depends of avatar's dimensions |
254 | Matrix _startTransform = Matrix.Identity; | 442 | //For RigidBody Constructor. The next values might change |
255 | _startTransform.Translation = BulletXConversions.PhysicsVectorToXnaVector3(pos); | ||
256 | Matrix _centerOfMassOffset = Matrix.Identity; | ||
257 | CollisionShape _collisionShape = new BoxShape(new MonoXnaCompactMaths.Vector3(0.5f, 0.5f, 1.60f)); | ||
258 | DefaultMotionState _motionState = new DefaultMotionState(_startTransform, _centerOfMassOffset); | ||
259 | MonoXnaCompactMaths.Vector3 _localInertia = new MonoXnaCompactMaths.Vector3(); | ||
260 | _collisionShape.CalculateLocalInertia(_mass, out _localInertia); | ||
261 | //Always when mass > 0 | ||
262 | |||
263 | //The next values might change | ||
264 | float _linearDamping = 0.0f; | 443 | float _linearDamping = 0.0f; |
265 | float _angularDamping = 0.0f; | 444 | float _angularDamping = 0.0f; |
266 | float _friction = 0.5f; | 445 | float _friction = 0.5f; |
267 | float _restitution = 0.0f; | 446 | float _restitution = 0.0f; |
268 | 447 | Matrix _startTransform = Matrix.Identity; | |
269 | rigidBody = new RigidBody(_mass, _motionState, _collisionShape, _localInertia, _linearDamping, _angularDamping, _friction, _restitution); | 448 | Matrix _centerOfMassOffset = Matrix.Identity; |
270 | rigidBody.ActivationState = ActivationState.DisableDeactivation; | 449 | lock (BulletXScene.BulletXLock) |
271 | 450 | { | |
272 | parent_scene.ddWorld.AddRigidBody(rigidBody); | 451 | _startTransform.Translation = BulletXMaths.PhysicsVectorToXnaVector3(pos); |
452 | //CollisionShape _collisionShape = new BoxShape(new MonoXnaCompactMaths.Vector3(1.0f, 1.0f, 1.60f)); | ||
453 | //For now, like ODE, collisionShape = sphere of radious = 1.0 | ||
454 | CollisionShape _collisionShape = new SphereShape(1.0f); | ||
455 | DefaultMotionState _motionState = new DefaultMotionState(_startTransform, _centerOfMassOffset); | ||
456 | MonoXnaCompactMaths.Vector3 _localInertia = new MonoXnaCompactMaths.Vector3(); | ||
457 | _collisionShape.CalculateLocalInertia(_mass, out _localInertia); //Always when mass > 0 | ||
458 | rigidBody = new RigidBody(_mass, _motionState, _collisionShape, _localInertia, _linearDamping, _angularDamping, _friction, _restitution); | ||
459 | rigidBody.ActivationState = ActivationState.DisableDeactivation; | ||
460 | //It's seems that there are a bug with rigidBody constructor and its CenterOfMassPosition | ||
461 | MonoXnaCompactMaths.Vector3 _vDebugTranslation; | ||
462 | _vDebugTranslation = _startTransform.Translation - rigidBody.CenterOfMassPosition; | ||
463 | rigidBody.Translate(_vDebugTranslation); | ||
464 | parent_scene.ddWorld.AddRigidBody(rigidBody); | ||
465 | } | ||
273 | } | 466 | } |
274 | public override PhysicsVector Position | 467 | public override PhysicsVector Position |
275 | { | 468 | { |
@@ -279,7 +472,11 @@ namespace OpenSim.Region.Physics.BulletXPlugin | |||
279 | } | 472 | } |
280 | set | 473 | set |
281 | { | 474 | { |
282 | _position = value; | 475 | lock (BulletXScene.BulletXLock) |
476 | { | ||
477 | _position = value; | ||
478 | Translate(); | ||
479 | } | ||
283 | } | 480 | } |
284 | } | 481 | } |
285 | public override PhysicsVector Velocity | 482 | public override PhysicsVector Velocity |
@@ -290,7 +487,11 @@ namespace OpenSim.Region.Physics.BulletXPlugin | |||
290 | } | 487 | } |
291 | set | 488 | set |
292 | { | 489 | { |
293 | _velocity = value; | 490 | lock (BulletXScene.BulletXLock) |
491 | { | ||
492 | _velocity = value; | ||
493 | Speed(); | ||
494 | } | ||
294 | } | 495 | } |
295 | } | 496 | } |
296 | public override PhysicsVector Size | 497 | public override PhysicsVector Size |
@@ -301,7 +502,10 @@ namespace OpenSim.Region.Physics.BulletXPlugin | |||
301 | } | 502 | } |
302 | set | 503 | set |
303 | { | 504 | { |
304 | _size = value; | 505 | lock (BulletXScene.BulletXLock) |
506 | { | ||
507 | _size = value; | ||
508 | } | ||
305 | } | 509 | } |
306 | } | 510 | } |
307 | public override PhysicsVector Acceleration | 511 | public override PhysicsVector Acceleration |
@@ -319,7 +523,10 @@ namespace OpenSim.Region.Physics.BulletXPlugin | |||
319 | } | 523 | } |
320 | set | 524 | set |
321 | { | 525 | { |
322 | _orientation = value; | 526 | lock (BulletXScene.BulletXLock) |
527 | { | ||
528 | _orientation = value; | ||
529 | } | ||
323 | } | 530 | } |
324 | } | 531 | } |
325 | public override bool Flying | 532 | public override bool Flying |
@@ -335,7 +542,10 @@ namespace OpenSim.Region.Physics.BulletXPlugin | |||
335 | } | 542 | } |
336 | public void SetAcceleration(PhysicsVector accel) | 543 | public void SetAcceleration(PhysicsVector accel) |
337 | { | 544 | { |
338 | _acceleration = accel; | 545 | lock (BulletXScene.BulletXLock) |
546 | { | ||
547 | _acceleration = accel; | ||
548 | } | ||
339 | } | 549 | } |
340 | public override bool Kinematic | 550 | public override bool Kinematic |
341 | { | 551 | { |
@@ -356,70 +566,96 @@ namespace OpenSim.Region.Physics.BulletXPlugin | |||
356 | { | 566 | { |
357 | 567 | ||
358 | } | 568 | } |
359 | public void Move(float timeStep) | 569 | internal void Move(float timeStep) |
360 | { | 570 | { |
361 | MonoXnaCompactMaths.Vector3 vec = new MonoXnaCompactMaths.Vector3(); | 571 | MonoXnaCompactMaths.Vector3 vec = new MonoXnaCompactMaths.Vector3(); |
362 | //if (this._velocity.X == 0.0f) | 572 | //At this point it's supossed that: |
363 | // vec.X = this.rigidBody.LinearVelocity.X; //current velocity | 573 | //_velocity == rigidBody.LinearVelocity |
364 | //else | 574 | vec.X = this._velocity.X; |
365 | vec.X = this._velocity.X; //overrides current velocity | 575 | vec.Y = this._velocity.Y; |
366 | 576 | vec.Z = this._velocity.Z; | |
367 | //if (this._velocity.Y == 0.0f) | ||
368 | // vec.Y = this.rigidBody.LinearVelocity.Y; //current velocity | ||
369 | //else | ||
370 | vec.Y = this._velocity.Y; //overrides current velocity | ||
371 | |||
372 | float nextZVelocity; | ||
373 | //if (this._velocity.Z == 0.0f) | ||
374 | // nextZVelocity = this.rigidBody.LinearVelocity.Z; //current velocity | ||
375 | //else | ||
376 | nextZVelocity = this._velocity.Z; //overrides current velocity | ||
377 | 577 | ||
378 | if (flying) | 578 | if (flying) |
379 | { | 579 | { |
380 | //Antigravity with movement | 580 | //Antigravity with movement |
381 | if (this._position.Z <= BulletXScene.HeightLevel0) | 581 | if (this._position.Z <= BulletXScene.HeightLevel0) |
382 | { | 582 | { |
383 | vec.Z = nextZVelocity + BulletXScene.Gravity * timeStep; | 583 | vec.Z += BulletXScene.Gravity * timeStep; |
384 | } | 584 | } |
385 | //Lowgravity with movement | 585 | //Lowgravity with movement |
386 | else if((this._position.Z > BulletXScene.HeightLevel0) | 586 | else if ((this._position.Z > BulletXScene.HeightLevel0) |
387 | && (this._position.Z <= BulletXScene.HeightLevel1)) | 587 | && (this._position.Z <= BulletXScene.HeightLevel1)) |
388 | { | 588 | { |
389 | vec.Z = nextZVelocity + BulletXScene.Gravity * timeStep * (1.0f - BulletXScene.LowGravityFactor); | 589 | vec.Z += BulletXScene.Gravity * timeStep * (1.0f - BulletXScene.LowGravityFactor); |
390 | } | 590 | } |
391 | //Lowgravity with... | 591 | //Lowgravity with... |
392 | else if (this._position.Z > BulletXScene.HeightLevel1) | 592 | else if (this._position.Z > BulletXScene.HeightLevel1) |
393 | { | 593 | { |
394 | if(nextZVelocity > 0) //no movement | 594 | if (vec.Z > 0) //no movement |
395 | vec.Z = BulletXScene.Gravity * timeStep * (1.0f - BulletXScene.LowGravityFactor); | 595 | vec.Z = BulletXScene.Gravity * timeStep * (1.0f - BulletXScene.LowGravityFactor); |
396 | else | 596 | else |
397 | vec.Z = nextZVelocity + BulletXScene.Gravity * timeStep * (1.0f - BulletXScene.LowGravityFactor); | 597 | vec.Z += BulletXScene.Gravity * timeStep * (1.0f - BulletXScene.LowGravityFactor); |
398 | 598 | ||
399 | } | 599 | } |
400 | } | 600 | } |
401 | else | ||
402 | { | ||
403 | vec.Z = nextZVelocity; | ||
404 | } | ||
405 | rigidBody.LinearVelocity = vec; | 601 | rigidBody.LinearVelocity = vec; |
406 | } | 602 | } |
407 | public void UpdatePosition() | ||
408 | { | ||
409 | this._position = BulletXConversions.XnaVector3ToPhysicsVector(rigidBody.CenterOfMassPosition); | ||
410 | } | ||
411 | //This validation is very basic | 603 | //This validation is very basic |
412 | internal void ValidateHeight(float heighmapPositionValue) | 604 | internal void ValidateHeight(float heighmapPositionValue) |
413 | { | 605 | { |
414 | if (rigidBody.CenterOfMassPosition.Z < heighmapPositionValue) | 606 | if (rigidBody.CenterOfMassPosition.Z < heighmapPositionValue + _size.Z / 2.0f) |
415 | { | 607 | { |
416 | Matrix m = rigidBody.WorldTransform; | 608 | Matrix m = rigidBody.WorldTransform; |
417 | MonoXnaCompactMaths.Vector3 v3 = m.Translation; | 609 | MonoXnaCompactMaths.Vector3 v3 = m.Translation; |
418 | v3.Z = heighmapPositionValue; | 610 | v3.Z = heighmapPositionValue + _size.Z / 2.0f; |
419 | m.Translation = v3; | 611 | m.Translation = v3; |
420 | rigidBody.WorldTransform = m; | 612 | rigidBody.WorldTransform = m; |
613 | //When an Avie touch the ground it's vertical velocity it's reduced to ZERO | ||
614 | Speed(new PhysicsVector(this.rigidBody.LinearVelocity.X, this.rigidBody.LinearVelocity.Y, 0.0f)); | ||
421 | } | 615 | } |
422 | } | 616 | } |
617 | internal void UpdateKinetics() | ||
618 | { | ||
619 | this._position = BulletXMaths.XnaVector3ToPhysicsVector(rigidBody.CenterOfMassPosition); | ||
620 | this._velocity = BulletXMaths.XnaVector3ToPhysicsVector(rigidBody.LinearVelocity); | ||
621 | //Orientation it seems that it will be the default. | ||
622 | ReOrient(); | ||
623 | } | ||
624 | |||
625 | #region Methods for updating values of RigidBody | ||
626 | private void Translate() | ||
627 | { | ||
628 | Translate(this._position); | ||
629 | } | ||
630 | private void Translate(PhysicsVector _newPos) | ||
631 | { | ||
632 | MonoXnaCompactMaths.Vector3 _translation; | ||
633 | _translation = BulletXMaths.PhysicsVectorToXnaVector3(_newPos) - rigidBody.CenterOfMassPosition; | ||
634 | rigidBody.Translate(_translation); | ||
635 | } | ||
636 | private void Speed() | ||
637 | { | ||
638 | Speed(this._velocity); | ||
639 | } | ||
640 | private void Speed(PhysicsVector _newSpeed) | ||
641 | { | ||
642 | MonoXnaCompactMaths.Vector3 _speed; | ||
643 | _speed = BulletXMaths.PhysicsVectorToXnaVector3(_newSpeed); | ||
644 | rigidBody.LinearVelocity = _speed; | ||
645 | } | ||
646 | private void ReOrient() | ||
647 | { | ||
648 | ReOrient(this._orientation); | ||
649 | } | ||
650 | private void ReOrient(AxiomQuaternion _newOrient) | ||
651 | { | ||
652 | MonoXnaCompactMaths.Quaternion _newOrientation; | ||
653 | _newOrientation = BulletXMaths.AxiomQuaternionToXnaQuaternion(_newOrient); | ||
654 | Matrix _comTransform = rigidBody.CenterOfMassTransform; | ||
655 | BulletXMaths.SetRotation(ref _comTransform, _newOrientation); | ||
656 | rigidBody.CenterOfMassTransform = _comTransform; | ||
657 | } | ||
658 | #endregion | ||
423 | } | 659 | } |
424 | /// <summary> | 660 | /// <summary> |
425 | /// PhysicsActor Prim Class for BulletX | 661 | /// PhysicsActor Prim Class for BulletX |
@@ -431,7 +667,20 @@ namespace OpenSim.Region.Physics.BulletXPlugin | |||
431 | private PhysicsVector _size; | 667 | private PhysicsVector _size; |
432 | private PhysicsVector _acceleration; | 668 | private PhysicsVector _acceleration; |
433 | private AxiomQuaternion _orientation; | 669 | private AxiomQuaternion _orientation; |
670 | //Density it will depends of material. | ||
671 | //For now all prims have the same density, all prims are made of water. Be water my friend! :D | ||
672 | private const float _density = 1000.0f; | ||
673 | private RigidBody rigidBody; | ||
674 | //_physical value will be linked with the prim object value | ||
675 | private Boolean _physical = false; | ||
434 | 676 | ||
677 | public Axiom.Math.Vector2 RigidBodyHorizontalPosition | ||
678 | { | ||
679 | get | ||
680 | { | ||
681 | return new Axiom.Math.Vector2(this.rigidBody.CenterOfMassPosition.X, this.rigidBody.CenterOfMassPosition.Y); | ||
682 | } | ||
683 | } | ||
435 | public BulletXPrim(BulletXScene parent_scene, PhysicsVector pos, PhysicsVector size, AxiomQuaternion rotation) | 684 | public BulletXPrim(BulletXScene parent_scene, PhysicsVector pos, PhysicsVector size, AxiomQuaternion rotation) |
436 | : this(parent_scene, pos, new PhysicsVector(), size, new PhysicsVector(), rotation) | 685 | : this(parent_scene, pos, new PhysicsVector(), size, new PhysicsVector(), rotation) |
437 | { | 686 | { |
@@ -442,19 +691,51 @@ namespace OpenSim.Region.Physics.BulletXPlugin | |||
442 | _position = pos; | 691 | _position = pos; |
443 | _velocity = velocity; | 692 | _velocity = velocity; |
444 | _size = size; | 693 | _size = size; |
694 | if ((size.X == 0) || (size.Y == 0) || (size.Z == 0)) throw new Exception("Size 0"); | ||
695 | |||
445 | _acceleration = aceleration; | 696 | _acceleration = aceleration; |
446 | _orientation = rotation; | 697 | //Because a bug, orientation will be fixed to AxiomQuaternion.Identity |
698 | _orientation = AxiomQuaternion.Identity; | ||
699 | //_orientation = rotation; | ||
700 | //--- | ||
701 | //For RigidBody Constructor. The next values might change | ||
702 | float _linearDamping = 0.0f; | ||
703 | float _angularDamping = 0.0f; | ||
704 | float _friction = 0.5f; | ||
705 | float _restitution = 0.0f; | ||
706 | Matrix _startTransform = Matrix.Identity; | ||
707 | Matrix _centerOfMassOffset = Matrix.Identity; | ||
708 | lock (BulletXScene.BulletXLock) | ||
709 | { | ||
710 | _startTransform.Translation = BulletXMaths.PhysicsVectorToXnaVector3(pos); | ||
711 | //For now all prims are boxes | ||
712 | CollisionShape _collisionShape = new BoxShape(BulletXMaths.PhysicsVectorToXnaVector3(_size) / 2.0f); | ||
713 | DefaultMotionState _motionState = new DefaultMotionState(_startTransform, _centerOfMassOffset); | ||
714 | MonoXnaCompactMaths.Vector3 _localInertia = new MonoXnaCompactMaths.Vector3(); | ||
715 | _collisionShape.CalculateLocalInertia(Mass, out _localInertia); //Always when mass > 0 | ||
716 | rigidBody = new RigidBody(Mass, _motionState, _collisionShape, _localInertia, _linearDamping, _angularDamping, _friction, _restitution); | ||
717 | rigidBody.ActivationState = ActivationState.DisableDeactivation; | ||
718 | //It's seems that there are a bug with rigidBody constructor and its CenterOfMassPosition | ||
719 | MonoXnaCompactMaths.Vector3 _vDebugTranslation; | ||
720 | _vDebugTranslation = _startTransform.Translation - rigidBody.CenterOfMassPosition; | ||
721 | rigidBody.Translate(_vDebugTranslation); | ||
722 | //--- | ||
723 | parent_scene.ddWorld.AddRigidBody(rigidBody); | ||
724 | } | ||
447 | } | 725 | } |
448 | public override PhysicsVector Position | 726 | public override PhysicsVector Position |
449 | { | 727 | { |
450 | get | 728 | get |
451 | { | 729 | { |
452 | return _position; | 730 | return _position; |
453 | |||
454 | } | 731 | } |
455 | set | 732 | set |
456 | { | 733 | { |
457 | _position = value; | 734 | lock (BulletXScene.BulletXLock) |
735 | { | ||
736 | _position = value; | ||
737 | Translate(); | ||
738 | } | ||
458 | } | 739 | } |
459 | } | 740 | } |
460 | public override PhysicsVector Velocity | 741 | public override PhysicsVector Velocity |
@@ -465,7 +746,11 @@ namespace OpenSim.Region.Physics.BulletXPlugin | |||
465 | } | 746 | } |
466 | set | 747 | set |
467 | { | 748 | { |
468 | _velocity = value; | 749 | lock (BulletXScene.BulletXLock) |
750 | { | ||
751 | _velocity = value; | ||
752 | Speed(); | ||
753 | } | ||
469 | } | 754 | } |
470 | } | 755 | } |
471 | public override PhysicsVector Size | 756 | public override PhysicsVector Size |
@@ -476,7 +761,11 @@ namespace OpenSim.Region.Physics.BulletXPlugin | |||
476 | } | 761 | } |
477 | set | 762 | set |
478 | { | 763 | { |
479 | _size = value; | 764 | lock (BulletXScene.BulletXLock) |
765 | { | ||
766 | _size = value; | ||
767 | ReSize(); | ||
768 | } | ||
480 | } | 769 | } |
481 | } | 770 | } |
482 | public override PhysicsVector Acceleration | 771 | public override PhysicsVector Acceleration |
@@ -494,7 +783,19 @@ namespace OpenSim.Region.Physics.BulletXPlugin | |||
494 | } | 783 | } |
495 | set | 784 | set |
496 | { | 785 | { |
497 | _orientation = value; | 786 | lock (BulletXScene.BulletXLock) |
787 | { | ||
788 | _orientation = value; | ||
789 | ReOrient(); | ||
790 | } | ||
791 | } | ||
792 | } | ||
793 | public float Mass | ||
794 | { | ||
795 | get | ||
796 | { | ||
797 | //For now all prims are boxes | ||
798 | return _density * _size.X * _size.Y * _size.Z; | ||
498 | } | 799 | } |
499 | } | 800 | } |
500 | public override bool Flying | 801 | public override bool Flying |
@@ -508,9 +809,23 @@ namespace OpenSim.Region.Physics.BulletXPlugin | |||
508 | 809 | ||
509 | } | 810 | } |
510 | } | 811 | } |
812 | public Boolean Physical | ||
813 | { | ||
814 | get | ||
815 | { | ||
816 | return _physical; | ||
817 | } | ||
818 | set | ||
819 | { | ||
820 | _physical = value; | ||
821 | } | ||
822 | } | ||
511 | public void SetAcceleration(PhysicsVector accel) | 823 | public void SetAcceleration(PhysicsVector accel) |
512 | { | 824 | { |
513 | _acceleration = accel; | 825 | lock (BulletXScene.BulletXLock) |
826 | { | ||
827 | _acceleration = accel; | ||
828 | } | ||
514 | } | 829 | } |
515 | public override bool Kinematic | 830 | public override bool Kinematic |
516 | { | 831 | { |
@@ -532,6 +847,86 @@ namespace OpenSim.Region.Physics.BulletXPlugin | |||
532 | { | 847 | { |
533 | 848 | ||
534 | } | 849 | } |
850 | internal void ValidateHeight(float heighmapPositionValue) | ||
851 | { | ||
852 | if (rigidBody.CenterOfMassPosition.Z < heighmapPositionValue + _size.Z / 2.0f) | ||
853 | { | ||
854 | Matrix m = rigidBody.WorldTransform; | ||
855 | MonoXnaCompactMaths.Vector3 v3 = m.Translation; | ||
856 | v3.Z = heighmapPositionValue + _size.Z / 2.0f; | ||
857 | m.Translation = v3; | ||
858 | rigidBody.WorldTransform = m; | ||
859 | //When a Prim touch the ground it's vertical velocity it's reduced to ZERO | ||
860 | Speed(new PhysicsVector(this.rigidBody.LinearVelocity.X, this.rigidBody.LinearVelocity.Y, 0.0f)); | ||
861 | } | ||
862 | } | ||
863 | internal void UpdateKinetics() | ||
864 | { | ||
865 | if (_physical) //Updates properties. Prim updates its properties physically | ||
866 | { | ||
867 | this._position = BulletXMaths.XnaVector3ToPhysicsVector(rigidBody.CenterOfMassPosition); | ||
868 | this._velocity = BulletXMaths.XnaVector3ToPhysicsVector(rigidBody.LinearVelocity); | ||
869 | //Orientation is not implemented yet in MonoXnaCompactMaths | ||
870 | //this._orientation = BulletXMaths.XnaQuaternionToAxiomQuaternion(rigidBody.Orientation); < Good | ||
871 | //ReOrient(); | ||
872 | //--- | ||
873 | ReOrient(); | ||
874 | } | ||
875 | else //Doesn't updates properties. That's a cancel | ||
876 | { | ||
877 | Translate(); | ||
878 | Speed(); | ||
879 | //Orientation is not implemented yet in MonoXnaCompactMaths | ||
880 | //ReOrient(); | ||
881 | ReOrient(); | ||
882 | } | ||
883 | } | ||
884 | |||
885 | #region Methods for updating values of RigidBody | ||
886 | private void Translate() | ||
887 | { | ||
888 | Translate(this._position); | ||
889 | } | ||
890 | private void Translate(PhysicsVector _newPos) | ||
891 | { | ||
892 | MonoXnaCompactMaths.Vector3 _translation; | ||
893 | _translation = BulletXMaths.PhysicsVectorToXnaVector3(_newPos) - rigidBody.CenterOfMassPosition; | ||
894 | rigidBody.Translate(_translation); | ||
895 | } | ||
896 | private void Speed() | ||
897 | { | ||
898 | Speed(this._velocity); | ||
899 | } | ||
900 | private void Speed(PhysicsVector _newSpeed) | ||
901 | { | ||
902 | MonoXnaCompactMaths.Vector3 _speed; | ||
903 | _speed = BulletXMaths.PhysicsVectorToXnaVector3(_newSpeed); | ||
904 | rigidBody.LinearVelocity = _speed; | ||
905 | } | ||
906 | private void ReSize() | ||
907 | { | ||
908 | ReSize(this._size); | ||
909 | } | ||
910 | private void ReSize(PhysicsVector _newSize) | ||
911 | { | ||
912 | MonoXnaCompactMaths.Vector3 _newsize; | ||
913 | _newsize = BulletXMaths.PhysicsVectorToXnaVector3(_newSize); | ||
914 | //For now all prims are Boxes | ||
915 | rigidBody.CollisionShape = new BoxShape(BulletXMaths.PhysicsVectorToXnaVector3(_newSize) / 2.0f); | ||
916 | } | ||
917 | private void ReOrient() | ||
918 | { | ||
919 | ReOrient(this._orientation); | ||
920 | } | ||
921 | private void ReOrient(AxiomQuaternion _newOrient) | ||
922 | { | ||
923 | MonoXnaCompactMaths.Quaternion _newOrientation; | ||
924 | _newOrientation = BulletXMaths.AxiomQuaternionToXnaQuaternion(_newOrient); | ||
925 | Matrix _comTransform = rigidBody.CenterOfMassTransform; | ||
926 | BulletXMaths.SetRotation(ref _comTransform, _newOrientation); | ||
927 | rigidBody.CenterOfMassTransform = _comTransform; | ||
928 | } | ||
929 | #endregion | ||
930 | |||
535 | } | 931 | } |
536 | } | 932 | } |
537 | |||