aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim
diff options
context:
space:
mode:
authorRobert Adams2013-03-31 09:12:18 -0700
committerRobert Adams2013-03-31 22:19:41 -0700
commit2c581cae2a77628704ae7ae2f9f0f0a87cbb0072 (patch)
tree2095b9afd1a0c984119fcac98e3dfd94ab99aabb /OpenSim
parentExport permission, part two. Setting export perms for textures and clothing w... (diff)
downloadopensim-SC-2c581cae2a77628704ae7ae2f9f0f0a87cbb0072.zip
opensim-SC-2c581cae2a77628704ae7ae2f9f0f0a87cbb0072.tar.gz
opensim-SC-2c581cae2a77628704ae7ae2f9f0f0a87cbb0072.tar.bz2
opensim-SC-2c581cae2a77628704ae7ae2f9f0f0a87cbb0072.tar.xz
BulletSim: Add physical 'actors' that operate on the physical object.
Add first 'actor' for locked axis.
Diffstat (limited to 'OpenSim')
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSActorLockAxis.cs168
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSActors.cs123
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs11
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs83
4 files changed, 311 insertions, 74 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSActorLockAxis.cs b/OpenSim/Region/Physics/BulletSPlugin/BSActorLockAxis.cs
new file mode 100755
index 0000000..b4af126
--- /dev/null
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSActorLockAxis.cs
@@ -0,0 +1,168 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyrightD
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
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
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
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Linq;
31using System.Text;
32
33using OMV = OpenMetaverse;
34
35namespace OpenSim.Region.Physics.BulletSPlugin
36{
37public class BSActorLockAxis : BSActor
38{
39 bool TryExperimentalLockAxisCode = false;
40 BSConstraint LockAxisConstraint = null;
41
42 public BSActorLockAxis(BSScene physicsScene, BSPhysObject pObj, string actorName)
43 : base(physicsScene, pObj,actorName)
44 {
45 LockAxisConstraint = null;
46 }
47
48 // BSActor.isActive
49 public override bool isActive
50 {
51 get { return Enabled && Prim.IsPhysicallyActive; }
52 }
53
54 // Release any connections and resources used by the actor.
55 // BSActor.Release()
56 public override void Release()
57 {
58 RemoveAxisLockConstraint();
59 }
60
61 // Called when physical parameters (properties set in Bullet) need to be re-applied.
62 // Called at taint-time.
63 // BSActor.Refresh()
64 public override void Refresh()
65 {
66 // If all the axis are free, we don't need to exist
67 if (Prim.LockedAxis == Prim.LockedAxisFree)
68 {
69 Prim.PhysicalActors.RemoveAndRelease(ActorName);
70 return;
71 }
72 // If the object is physically active, add the axis locking constraint
73 if (Enabled
74 && Prim.IsPhysicallyActive
75 && TryExperimentalLockAxisCode
76 && Prim.LockedAxis != Prim.LockedAxisFree)
77 {
78 if (LockAxisConstraint != null)
79 AddAxisLockConstraint();
80 }
81 else
82 {
83 RemoveAxisLockConstraint();
84 }
85 }
86
87 // The object's physical representation is being rebuilt so pick up any physical dependencies (constraints, ...).
88 // Register a prestep action to restore physical requirements before the next simulation step.
89 // Called at taint-time.
90 // BSActor.RemoveBodyDependencies()
91 public override void RemoveBodyDependencies()
92 {
93 if (LockAxisConstraint != null)
94 {
95 // If a constraint is set up, remove it from the physical scene
96 RemoveAxisLockConstraint();
97 // Schedule a call before the next simulation step to restore the constraint.
98 PhysicsScene.PostTaintObject(Prim.LockedAxisActorName, Prim.LocalID, delegate()
99 {
100 Refresh();
101 });
102 }
103 }
104
105 private void AddAxisLockConstraint()
106 {
107 // Lock that axis by creating a 6DOF constraint that has one end in the world and
108 // the other in the object.
109 // http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?p=20817
110 // http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?p=26380
111
112 // Remove any existing axis constraint (just to be sure)
113 RemoveAxisLockConstraint();
114
115 BSConstraint6Dof axisConstrainer = new BSConstraint6Dof(PhysicsScene.World, Prim.PhysBody,
116 OMV.Vector3.Zero, OMV.Quaternion.Inverse(Prim.RawOrientation),
117 true /* useLinearReferenceFrameB */, true /* disableCollisionsBetweenLinkedBodies */);
118 LockAxisConstraint = axisConstrainer;
119 PhysicsScene.Constraints.AddConstraint(LockAxisConstraint);
120
121 // The constraint is tied to the world and oriented to the prim.
122
123 // Free to move linearly
124 OMV.Vector3 linearLow = OMV.Vector3.Zero;
125 OMV.Vector3 linearHigh = PhysicsScene.TerrainManager.DefaultRegionSize;
126 axisConstrainer.SetLinearLimits(linearLow, linearHigh);
127
128 // Angular with some axis locked
129 float f2PI = (float)Math.PI * 2f;
130 OMV.Vector3 angularLow = new OMV.Vector3(-f2PI, -f2PI, -f2PI);
131 OMV.Vector3 angularHigh = new OMV.Vector3(f2PI, f2PI, f2PI);
132 if (Prim.LockedAxis.X != 1f)
133 {
134 angularLow.X = 0f;
135 angularHigh.X = 0f;
136 }
137 if (Prim.LockedAxis.Y != 1f)
138 {
139 angularLow.Y = 0f;
140 angularHigh.Y = 0f;
141 }
142 if (Prim.LockedAxis.Z != 1f)
143 {
144 angularLow.Z = 0f;
145 angularHigh.Z = 0f;
146 }
147 axisConstrainer.SetAngularLimits(angularLow, angularHigh);
148
149 PhysicsScene.DetailLog("{0},BSPrim.LockAngularMotion,create,linLow={1},linHi={2},angLow={3},angHi={4}",
150 Prim.LocalID, linearLow, linearHigh, angularLow, angularHigh);
151
152 // Constants from one of the posts mentioned above and used in Bullet's ConstraintDemo.
153 axisConstrainer.TranslationalLimitMotor(true /* enable */, 5.0f, 0.1f);
154
155 axisConstrainer.RecomputeConstraintVariables(Prim.RawMass);
156 }
157
158 private void RemoveAxisLockConstraint()
159 {
160 if (LockAxisConstraint != null)
161 {
162 PhysicsScene.Constraints.RemoveAndDestroyConstraint(LockAxisConstraint);
163 LockAxisConstraint = null;
164 PhysicsScene.DetailLog("{0},BSPrim.CleanUpLockAxisPhysicals,destroyingConstraint", Prim.LocalID);
165 }
166 }
167}
168}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSActors.cs b/OpenSim/Region/Physics/BulletSPlugin/BSActors.cs
new file mode 100755
index 0000000..b9b5ce1
--- /dev/null
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSActors.cs
@@ -0,0 +1,123 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyrightD
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
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
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
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27using System;
28using System.Collections.Generic;
29using System.Text;
30
31namespace OpenSim.Region.Physics.BulletSPlugin
32{
33public class BSActorCollection
34{
35 private BSScene PhysicsScene { get; set; }
36 private Dictionary<string, BSActor> m_actors;
37
38 public BSActorCollection(BSScene physicsScene)
39 {
40 PhysicsScene = physicsScene;
41 m_actors = new Dictionary<string, BSActor>();
42 }
43 public void Add(string name, BSActor actor)
44 {
45 m_actors[name] = actor;
46 }
47 public bool RemoveAndRelease(string name)
48 {
49 bool ret = false;
50 if (m_actors.ContainsKey(name))
51 {
52 BSActor beingRemoved = m_actors[name];
53 beingRemoved.Release();
54 m_actors.Remove(name);
55 ret = true;
56 }
57 return ret;
58 }
59 public void Clear()
60 {
61 Release();
62 m_actors.Clear();
63 }
64 public bool HasActor(string name)
65 {
66 return m_actors.ContainsKey(name);
67 }
68 public void ForEachActor(Action<BSActor> act)
69 {
70 foreach (KeyValuePair<string, BSActor> kvp in m_actors)
71 act(kvp.Value);
72 }
73
74 public void Release()
75 {
76 ForEachActor(a => a.Release());
77 }
78 public void Refresh()
79 {
80 ForEachActor(a => a.Refresh());
81 }
82 public void RemoveBodyDependencies()
83 {
84 ForEachActor(a => a.RemoveBodyDependencies());
85 }
86}
87
88// =============================================================================
89public abstract class BSActor
90{
91 protected BSScene PhysicsScene { get; private set; }
92 protected BSPhysObject Prim { get; private set; }
93 protected bool Enabled { get; set; }
94 public string ActorName { get; private set; }
95
96 public BSActor(BSScene physicsScene, BSPhysObject pObj, string actorName)
97 {
98 PhysicsScene = physicsScene;
99 Prim = pObj;
100 ActorName = actorName;
101 Enabled = true;
102 }
103
104 // Return 'true' if activily updating the prim
105 public virtual bool isActive
106 {
107 get { return Enabled; }
108 }
109 // Turn the actor on an off.
110 public virtual void Enable(bool setEnabled)
111 {
112 Enabled = setEnabled;
113 }
114 // Release any connections and resources used by the actor.
115 public abstract void Release();
116 // Called when physical parameters (properties set in Bullet) need to be re-applied.
117 public abstract void Refresh();
118 // The object's physical representation is being rebuilt so pick up any physical dependencies (constraints, ...).
119 // Register a prestep action to restore physical requirements before the next simulation step.
120 public abstract void RemoveBodyDependencies();
121
122}
123}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
index 6bb88c7..cba2646 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
@@ -78,6 +78,9 @@ public abstract class BSPhysObject : PhysicsActor
78 Name = name; // PhysicsActor also has the name of the object. Someday consolidate. 78 Name = name; // PhysicsActor also has the name of the object. Someday consolidate.
79 TypeName = typeName; 79 TypeName = typeName;
80 80
81 // The collection of things that push me around
82 PhysicalActors = new BSActorCollection(PhysicsScene);
83
81 // Initialize variables kept in base. 84 // Initialize variables kept in base.
82 GravModifier = 1.0f; 85 GravModifier = 1.0f;
83 Gravity = new OMV.Vector3(0f, 0f, BSParam.Gravity); 86 Gravity = new OMV.Vector3(0f, 0f, BSParam.Gravity);
@@ -109,6 +112,10 @@ public abstract class BSPhysObject : PhysicsActor
109 { 112 {
110 UnRegisterAllPreStepActions(); 113 UnRegisterAllPreStepActions();
111 UnRegisterAllPostStepActions(); 114 UnRegisterAllPostStepActions();
115 PhysicsScene.TaintedObject("BSPhysObject.Destroy", delegate()
116 {
117 PhysicalActors.Release();
118 });
112 } 119 }
113 120
114 public BSScene PhysicsScene { get; protected set; } 121 public BSScene PhysicsScene { get; protected set; }
@@ -230,6 +237,7 @@ public abstract class BSPhysObject : PhysicsActor
230 237
231 public OMV.Vector3 LockedAxis { get; set; } // zero means locked. one means free. 238 public OMV.Vector3 LockedAxis { get; set; } // zero means locked. one means free.
232 public readonly OMV.Vector3 LockedAxisFree = new OMV.Vector3(1f, 1f, 1f); // All axis are free 239 public readonly OMV.Vector3 LockedAxisFree = new OMV.Vector3(1f, 1f, 1f); // All axis are free
240 public readonly String LockedAxisActorName = "BSPrim.LockedAxis";
233 241
234 #region Collisions 242 #region Collisions
235 243
@@ -413,6 +421,9 @@ public abstract class BSPhysObject : PhysicsActor
413 #endregion // Collisions 421 #endregion // Collisions
414 422
415 #region Per Simulation Step actions 423 #region Per Simulation Step actions
424
425 public BSActorCollection PhysicalActors;
426
416 // There are some actions that must be performed for a physical object before each simulation step. 427 // There are some actions that must be performed for a physical object before each simulation step.
417 // These actions are optional so, rather than scanning all the physical objects and asking them 428 // These actions are optional so, rather than scanning all the physical objects and asking them
418 // if they have anything to do, a physical object registers for an event call before the step is performed. 429 // if they have anything to do, a physical object registers for an event call before the step is performed.
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
index 6a5461a..68a6c41 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
@@ -126,7 +126,7 @@ public class BSPrim : BSPhysObject
126 // Undo any vehicle properties 126 // Undo any vehicle properties
127 this.VehicleType = (int)Vehicle.TYPE_NONE; 127 this.VehicleType = (int)Vehicle.TYPE_NONE;
128 128
129 PhysicsScene.TaintedObject("BSPrim.destroy", delegate() 129 PhysicsScene.TaintedObject("BSPrim.Destroy", delegate()
130 { 130 {
131 DetailLog("{0},BSPrim.Destroy,taint,", LocalID); 131 DetailLog("{0},BSPrim.Destroy,taint,", LocalID);
132 // If there are physical body and shape, release my use of same. 132 // If there are physical body and shape, release my use of same.
@@ -257,98 +257,31 @@ public class BSPrim : BSPhysObject
257 }); 257 });
258 } 258 }
259 259
260 bool TryExperimentalLockAxisCode = false;
261 BSConstraint LockAxisConstraint = null;
262 public override void LockAngularMotion(OMV.Vector3 axis) 260 public override void LockAngularMotion(OMV.Vector3 axis)
263 { 261 {
264 DetailLog("{0},BSPrim.LockAngularMotion,call,axis={1}", LocalID, axis); 262 DetailLog("{0},BSPrim.LockAngularMotion,call,axis={1}", LocalID, axis);
265 263
266 // "1" means free, "0" means locked 264 // "1" means free, "0" means locked
267 OMV.Vector3 locking = new OMV.Vector3(1f, 1f, 1f); 265 OMV.Vector3 locking = LockedAxisFree;
268 if (axis.X != 1) locking.X = 0f; 266 if (axis.X != 1) locking.X = 0f;
269 if (axis.Y != 1) locking.Y = 0f; 267 if (axis.Y != 1) locking.Y = 0f;
270 if (axis.Z != 1) locking.Z = 0f; 268 if (axis.Z != 1) locking.Z = 0f;
271 LockedAxis = locking; 269 LockedAxis = locking;
272 270
273 if (TryExperimentalLockAxisCode && LockedAxis != LockedAxisFree) 271 if (LockedAxis != LockedAxisFree)
274 { 272 {
275 // Lock that axis by creating a 6DOF constraint that has one end in the world and
276 // the other in the object.
277 // http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?p=20817
278 // http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?p=26380
279
280 PhysicsScene.TaintedObject("BSPrim.LockAngularMotion", delegate() 273 PhysicsScene.TaintedObject("BSPrim.LockAngularMotion", delegate()
281 { 274 {
282 CleanUpLockAxisPhysicals(true /* inTaintTime */); 275 // If there is not already an axis locker, make one
283 276 if (!PhysicalActors.HasActor(LockedAxisActorName))
284 BSConstraint6Dof axisConstrainer = new BSConstraint6Dof(PhysicsScene.World, PhysBody,
285 OMV.Vector3.Zero, OMV.Quaternion.Inverse(RawOrientation),
286 true /* useLinearReferenceFrameB */, true /* disableCollisionsBetweenLinkedBodies */);
287 LockAxisConstraint = axisConstrainer;
288 PhysicsScene.Constraints.AddConstraint(LockAxisConstraint);
289
290 // The constraint is tied to the world and oriented to the prim.
291
292 // Free to move linearly
293 OMV.Vector3 linearLow = OMV.Vector3.Zero;
294 OMV.Vector3 linearHigh = PhysicsScene.TerrainManager.DefaultRegionSize;
295 axisConstrainer.SetLinearLimits(linearLow, linearHigh);
296
297 // Angular with some axis locked
298 float f2PI = (float)Math.PI * 2f;
299 OMV.Vector3 angularLow = new OMV.Vector3(-f2PI, -f2PI, -f2PI);
300 OMV.Vector3 angularHigh = new OMV.Vector3(f2PI, f2PI, f2PI);
301 if (LockedAxis.X != 1f)
302 {
303 angularLow.X = 0f;
304 angularHigh.X = 0f;
305 }
306 if (LockedAxis.Y != 1f)
307 {
308 angularLow.Y = 0f;
309 angularHigh.Y = 0f;
310 }
311 if (LockedAxis.Z != 1f)
312 { 277 {
313 angularLow.Z = 0f; 278 PhysicalActors.Add(LockedAxisActorName, new BSActorLockAxis(PhysicsScene, this, LockedAxisActorName));
314 angularHigh.Z = 0f;
315 } 279 }
316 axisConstrainer.SetAngularLimits(angularLow, angularHigh); 280 UpdatePhysicalParameters();
317
318 DetailLog("{0},BSPrim.LockAngularMotion,create,linLow={1},linHi={2},angLow={3},angHi={4}",
319 LocalID, linearLow, linearHigh, angularLow, angularHigh);
320
321 // Constants from one of the posts mentioned above and used in Bullet's ConstraintDemo.
322 axisConstrainer.TranslationalLimitMotor(true /* enable */, 5.0f, 0.1f);
323
324 axisConstrainer.RecomputeConstraintVariables(RawMass);
325 }); 281 });
326 } 282 }
327 else
328 {
329 // Everything seems unlocked
330 CleanUpLockAxisPhysicals(false /* inTaintTime */);
331 }
332
333 return; 283 return;
334 } 284 }
335 // Get rid of any constraint built for LockAxis
336 // Most often the constraint is removed when the constraint collection is cleaned for this prim.
337 private void CleanUpLockAxisPhysicals(bool inTaintTime)
338 {
339 if (LockAxisConstraint != null)
340 {
341 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.CleanUpLockAxisPhysicals", delegate()
342 {
343 if (LockAxisConstraint != null)
344 {
345 PhysicsScene.Constraints.RemoveAndDestroyConstraint(LockAxisConstraint);
346 LockAxisConstraint = null;
347 DetailLog("{0},BSPrim.CleanUpLockAxisPhysicals,destroyingConstraint", LocalID);
348 }
349 });
350 }
351 }
352 285
353 public override OMV.Vector3 RawPosition 286 public override OMV.Vector3 RawPosition
354 { 287 {
@@ -916,6 +849,7 @@ public class BSPrim : BSPhysObject
916 849
917 // Update vehicle specific parameters (after MakeDynamic() so can change physical parameters) 850 // Update vehicle specific parameters (after MakeDynamic() so can change physical parameters)
918 VehicleController.Refresh(); 851 VehicleController.Refresh();
852 PhysicalActors.Refresh();
919 853
920 // Arrange for collision events if the simulator wants them 854 // Arrange for collision events if the simulator wants them
921 EnableCollisions(SubscribedEvents()); 855 EnableCollisions(SubscribedEvents());
@@ -1753,6 +1687,7 @@ public class BSPrim : BSPhysObject
1753 protected virtual void RemoveBodyDependencies() 1687 protected virtual void RemoveBodyDependencies()
1754 { 1688 {
1755 VehicleController.RemoveBodyDependencies(this); 1689 VehicleController.RemoveBodyDependencies(this);
1690 PhysicalActors.RemoveBodyDependencies();
1756 } 1691 }
1757 1692
1758 // The physics engine says that properties have updated. Update same and inform 1693 // The physics engine says that properties have updated. Update same and inform