diff options
author | Robert Adams | 2013-04-07 08:27:49 -0700 |
---|---|---|
committer | Robert Adams | 2013-04-08 06:27:43 -0700 |
commit | fe16dc09da3f2736fad5a9e792f5f81098b5f9a1 (patch) | |
tree | 14df85296a103e7326726ccfb9a017bc9ecb669f | |
parent | Optimize the number of Simian calls to get the initial presence (diff) | |
download | opensim-SC-fe16dc09da3f2736fad5a9e792f5f81098b5f9a1.zip opensim-SC-fe16dc09da3f2736fad5a9e792f5f81098b5f9a1.tar.gz opensim-SC-fe16dc09da3f2736fad5a9e792f5f81098b5f9a1.tar.bz2 opensim-SC-fe16dc09da3f2736fad5a9e792f5f81098b5f9a1.tar.xz |
BulletSim: complete movement of physical object action code out of the
physical object and into actors for setForce, setTorque, hover, lock
axis and avatar move.
Diffstat (limited to '')
-rwxr-xr-x | OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs | 287 | ||||
-rwxr-xr-x | OpenSim/Region/Physics/BulletSPlugin/BSActorHover.cs | 176 | ||||
-rwxr-xr-x | OpenSim/Region/Physics/BulletSPlugin/BSActorLockAxis.cs | 4 | ||||
-rwxr-xr-x | OpenSim/Region/Physics/BulletSPlugin/BSActorMoveToTarget.cs | 156 | ||||
-rwxr-xr-x | OpenSim/Region/Physics/BulletSPlugin/BSActorSetForce.cs | 137 | ||||
-rwxr-xr-x | OpenSim/Region/Physics/BulletSPlugin/BSActorSetTorque.cs | 138 | ||||
-rwxr-xr-x | OpenSim/Region/Physics/BulletSPlugin/BSActors.cs | 12 | ||||
-rw-r--r-- | OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs | 268 | ||||
-rwxr-xr-x | OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs | 226 | ||||
-rw-r--r-- | OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 307 | ||||
-rwxr-xr-x | OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt | 3 |
11 files changed, 1078 insertions, 636 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs b/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs new file mode 100755 index 0000000..634a898 --- /dev/null +++ b/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs | |||
@@ -0,0 +1,287 @@ | |||
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 | |||
28 | using System; | ||
29 | using System.Collections.Generic; | ||
30 | using System.Linq; | ||
31 | using System.Text; | ||
32 | |||
33 | using OpenSim.Region.Physics.Manager; | ||
34 | |||
35 | using OMV = OpenMetaverse; | ||
36 | |||
37 | namespace OpenSim.Region.Physics.BulletSPlugin | ||
38 | { | ||
39 | public class BSActorAvatarMove : BSActor | ||
40 | { | ||
41 | BSVMotor m_velocityMotor; | ||
42 | |||
43 | public BSActorAvatarMove(BSScene physicsScene, BSPhysObject pObj, string actorName) | ||
44 | : base(physicsScene, pObj, actorName) | ||
45 | { | ||
46 | m_velocityMotor = null; | ||
47 | m_physicsScene.DetailLog("{0},BSActorAvatarMove,constructor", m_controllingPrim.LocalID); | ||
48 | } | ||
49 | |||
50 | // BSActor.isActive | ||
51 | public override bool isActive | ||
52 | { | ||
53 | get { return Enabled && m_controllingPrim.IsPhysicallyActive; } | ||
54 | } | ||
55 | |||
56 | // Release any connections and resources used by the actor. | ||
57 | // BSActor.Dispose() | ||
58 | public override void Dispose() | ||
59 | { | ||
60 | Enabled = false; | ||
61 | } | ||
62 | |||
63 | // Called when physical parameters (properties set in Bullet) need to be re-applied. | ||
64 | // Called at taint-time. | ||
65 | // BSActor.Refresh() | ||
66 | public override void Refresh() | ||
67 | { | ||
68 | m_physicsScene.DetailLog("{0},BSActorAvatarMove,refresh", m_controllingPrim.LocalID); | ||
69 | |||
70 | // If not active any more, get rid of me (shouldn't ever happen, but just to be safe) | ||
71 | if (m_controllingPrim.RawForce == OMV.Vector3.Zero) | ||
72 | { | ||
73 | m_physicsScene.DetailLog("{0},BSActorAvatarMove,refresh,notAvatarMove,removing={1}", m_controllingPrim.LocalID, ActorName); | ||
74 | m_controllingPrim.PhysicalActors.RemoveAndRelease(ActorName); | ||
75 | return; | ||
76 | } | ||
77 | |||
78 | // If the object is physically active, add the hoverer prestep action | ||
79 | if (isActive) | ||
80 | { | ||
81 | ActivateAvatarMove(); | ||
82 | } | ||
83 | else | ||
84 | { | ||
85 | DeactivateAvatarMove(); | ||
86 | } | ||
87 | } | ||
88 | |||
89 | // The object's physical representation is being rebuilt so pick up any physical dependencies (constraints, ...). | ||
90 | // Register a prestep action to restore physical requirements before the next simulation step. | ||
91 | // Called at taint-time. | ||
92 | // BSActor.RemoveBodyDependencies() | ||
93 | public override void RemoveBodyDependencies() | ||
94 | { | ||
95 | // Nothing to do for the hoverer since it is all software at pre-step action time. | ||
96 | } | ||
97 | |||
98 | public void SetVelocityAndTarget(OMV.Vector3 vel, OMV.Vector3 targ, bool inTaintTime) | ||
99 | { | ||
100 | m_physicsScene.TaintedObject(inTaintTime, "BSActorAvatarMove.setVelocityAndTarget", delegate() | ||
101 | { | ||
102 | m_velocityMotor.Reset(); | ||
103 | m_velocityMotor.SetTarget(targ); | ||
104 | m_velocityMotor.SetCurrent(vel); | ||
105 | m_velocityMotor.Enabled = true; | ||
106 | }); | ||
107 | } | ||
108 | |||
109 | // If a hover motor has not been created, create one and start the hovering. | ||
110 | private void ActivateAvatarMove() | ||
111 | { | ||
112 | if (m_velocityMotor == null) | ||
113 | { | ||
114 | // Infinite decay and timescale values so motor only changes current to target values. | ||
115 | m_velocityMotor = new BSVMotor("BSCharacter.Velocity", | ||
116 | 0.2f, // time scale | ||
117 | BSMotor.Infinite, // decay time scale | ||
118 | BSMotor.InfiniteVector, // friction timescale | ||
119 | 1f // efficiency | ||
120 | ); | ||
121 | // _velocityMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG so motor will output detail log messages. | ||
122 | |||
123 | m_physicsScene.BeforeStep += Mover; | ||
124 | } | ||
125 | } | ||
126 | |||
127 | private void DeactivateAvatarMove() | ||
128 | { | ||
129 | if (m_velocityMotor != null) | ||
130 | { | ||
131 | m_physicsScene.BeforeStep -= Mover; | ||
132 | m_velocityMotor = null; | ||
133 | } | ||
134 | } | ||
135 | |||
136 | // Called just before the simulation step. Update the vertical position for hoverness. | ||
137 | private void Mover(float timeStep) | ||
138 | { | ||
139 | // Don't do movement while the object is selected. | ||
140 | if (!isActive) | ||
141 | return; | ||
142 | |||
143 | // TODO: Decide if the step parameters should be changed depending on the avatar's | ||
144 | // state (flying, colliding, ...). There is code in ODE to do this. | ||
145 | |||
146 | // COMMENTARY: when the user is making the avatar walk, except for falling, the velocity | ||
147 | // specified for the avatar is the one that should be used. For falling, if the avatar | ||
148 | // is not flying and is not colliding then it is presumed to be falling and the Z | ||
149 | // component is not fooled with (thus allowing gravity to do its thing). | ||
150 | // When the avatar is standing, though, the user has specified a velocity of zero and | ||
151 | // the avatar should be standing. But if the avatar is pushed by something in the world | ||
152 | // (raising elevator platform, moving vehicle, ...) the avatar should be allowed to | ||
153 | // move. Thus, the velocity cannot be forced to zero. The problem is that small velocity | ||
154 | // errors can creap in and the avatar will slowly float off in some direction. | ||
155 | // So, the problem is that, when an avatar is standing, we cannot tell creaping error | ||
156 | // from real pushing. | ||
157 | // The code below uses whether the collider is static or moving to decide whether to zero motion. | ||
158 | |||
159 | m_velocityMotor.Step(timeStep); | ||
160 | m_controllingPrim.IsStationary = false; | ||
161 | |||
162 | // If we're not supposed to be moving, make sure things are zero. | ||
163 | if (m_velocityMotor.ErrorIsZero() && m_velocityMotor.TargetValue == OMV.Vector3.Zero) | ||
164 | { | ||
165 | // The avatar shouldn't be moving | ||
166 | m_velocityMotor.Zero(); | ||
167 | |||
168 | if (m_controllingPrim.IsColliding) | ||
169 | { | ||
170 | // If we are colliding with a stationary object, presume we're standing and don't move around | ||
171 | if (!m_controllingPrim.ColliderIsMoving) | ||
172 | { | ||
173 | m_physicsScene.DetailLog("{0},BSCharacter.MoveMotor,collidingWithStationary,zeroingMotion", m_controllingPrim.LocalID); | ||
174 | m_controllingPrim.IsStationary = true; | ||
175 | m_controllingPrim.ZeroMotion(true /* inTaintTime */); | ||
176 | } | ||
177 | |||
178 | // Standing has more friction on the ground | ||
179 | if (m_controllingPrim.Friction != BSParam.AvatarStandingFriction) | ||
180 | { | ||
181 | m_controllingPrim.Friction = BSParam.AvatarStandingFriction; | ||
182 | m_physicsScene.PE.SetFriction(m_controllingPrim.PhysBody, m_controllingPrim.Friction); | ||
183 | } | ||
184 | } | ||
185 | else | ||
186 | { | ||
187 | if (m_controllingPrim.Flying) | ||
188 | { | ||
189 | // Flying and not collising and velocity nearly zero. | ||
190 | m_controllingPrim.ZeroMotion(true /* inTaintTime */); | ||
191 | } | ||
192 | } | ||
193 | |||
194 | m_physicsScene.DetailLog("{0},BSCharacter.MoveMotor,taint,stopping,target={1},colliding={2}", | ||
195 | m_controllingPrim.LocalID, m_velocityMotor.TargetValue, m_controllingPrim.IsColliding); | ||
196 | } | ||
197 | else | ||
198 | { | ||
199 | // Supposed to be moving. | ||
200 | OMV.Vector3 stepVelocity = m_velocityMotor.CurrentValue; | ||
201 | |||
202 | if (m_controllingPrim.Friction != BSParam.AvatarFriction) | ||
203 | { | ||
204 | // Probably starting up walking. Set friction to moving friction. | ||
205 | m_controllingPrim.Friction = BSParam.AvatarFriction; | ||
206 | m_physicsScene.PE.SetFriction(m_controllingPrim.PhysBody, m_controllingPrim.Friction); | ||
207 | } | ||
208 | |||
209 | // If falling, we keep the world's downward vector no matter what the other axis specify. | ||
210 | // The check for RawVelocity.Z < 0 makes jumping work (temporary upward force). | ||
211 | if (!m_controllingPrim.Flying && !m_controllingPrim.IsColliding) | ||
212 | { | ||
213 | if (m_controllingPrim.RawVelocity.Z < 0) | ||
214 | stepVelocity.Z = m_controllingPrim.RawVelocity.Z; | ||
215 | // DetailLog("{0},BSCharacter.MoveMotor,taint,overrideStepZWithWorldZ,stepVel={1}", LocalID, stepVelocity); | ||
216 | } | ||
217 | |||
218 | // 'stepVelocity' is now the speed we'd like the avatar to move in. Turn that into an instantanous force. | ||
219 | OMV.Vector3 moveForce = (stepVelocity - m_controllingPrim.RawVelocity) * m_controllingPrim.Mass; | ||
220 | |||
221 | // Should we check for move force being small and forcing velocity to zero? | ||
222 | |||
223 | // Add special movement force to allow avatars to walk up stepped surfaces. | ||
224 | moveForce += WalkUpStairs(); | ||
225 | |||
226 | m_physicsScene.DetailLog("{0},BSCharacter.MoveMotor,move,stepVel={1},vel={2},mass={3},moveForce={4}", | ||
227 | m_controllingPrim.LocalID, stepVelocity, m_controllingPrim.RawVelocity, m_controllingPrim.Mass, moveForce); | ||
228 | m_physicsScene.PE.ApplyCentralImpulse(m_controllingPrim.PhysBody, moveForce); | ||
229 | } | ||
230 | } | ||
231 | |||
232 | // Decide if the character is colliding with a low object and compute a force to pop the | ||
233 | // avatar up so it can walk up and over the low objects. | ||
234 | private OMV.Vector3 WalkUpStairs() | ||
235 | { | ||
236 | OMV.Vector3 ret = OMV.Vector3.Zero; | ||
237 | |||
238 | // This test is done if moving forward, not flying and is colliding with something. | ||
239 | // DetailLog("{0},BSCharacter.WalkUpStairs,IsColliding={1},flying={2},targSpeed={3},collisions={4}", | ||
240 | // LocalID, IsColliding, Flying, TargetSpeed, CollisionsLastTick.Count); | ||
241 | if (m_controllingPrim.IsColliding && !m_controllingPrim.Flying && m_controllingPrim.TargetVelocitySpeed > 0.1f /* && ForwardSpeed < 0.1f */) | ||
242 | { | ||
243 | // The range near the character's feet where we will consider stairs | ||
244 | float nearFeetHeightMin = m_controllingPrim.RawPosition.Z - (m_controllingPrim.Size.Z / 2f) + 0.05f; | ||
245 | float nearFeetHeightMax = nearFeetHeightMin + BSParam.AvatarStepHeight; | ||
246 | |||
247 | // Look for a collision point that is near the character's feet and is oriented the same as the charactor is | ||
248 | foreach (KeyValuePair<uint, ContactPoint> kvp in m_controllingPrim.CollisionsLastTick.m_objCollisionList) | ||
249 | { | ||
250 | // Don't care about collisions with the terrain | ||
251 | if (kvp.Key > m_physicsScene.TerrainManager.HighestTerrainID) | ||
252 | { | ||
253 | OMV.Vector3 touchPosition = kvp.Value.Position; | ||
254 | // DetailLog("{0},BSCharacter.WalkUpStairs,min={1},max={2},touch={3}", | ||
255 | // LocalID, nearFeetHeightMin, nearFeetHeightMax, touchPosition); | ||
256 | if (touchPosition.Z >= nearFeetHeightMin && touchPosition.Z <= nearFeetHeightMax) | ||
257 | { | ||
258 | // This contact is within the 'near the feet' range. | ||
259 | // The normal should be our contact point to the object so it is pointing away | ||
260 | // thus the difference between our facing orientation and the normal should be small. | ||
261 | OMV.Vector3 directionFacing = OMV.Vector3.UnitX * m_controllingPrim.RawOrientation; | ||
262 | OMV.Vector3 touchNormal = OMV.Vector3.Normalize(kvp.Value.SurfaceNormal); | ||
263 | float diff = Math.Abs(OMV.Vector3.Distance(directionFacing, touchNormal)); | ||
264 | if (diff < BSParam.AvatarStepApproachFactor) | ||
265 | { | ||
266 | // Found the stairs contact point. Push up a little to raise the character. | ||
267 | float upForce = (touchPosition.Z - nearFeetHeightMin) * m_controllingPrim.Mass * BSParam.AvatarStepForceFactor; | ||
268 | ret = new OMV.Vector3(0f, 0f, upForce); | ||
269 | |||
270 | // Also move the avatar up for the new height | ||
271 | OMV.Vector3 displacement = new OMV.Vector3(0f, 0f, BSParam.AvatarStepHeight / 2f); | ||
272 | m_controllingPrim.ForcePosition = m_controllingPrim.RawPosition + displacement; | ||
273 | } | ||
274 | m_physicsScene.DetailLog("{0},BSCharacter.WalkUpStairs,touchPos={1},nearFeetMin={2},faceDir={3},norm={4},diff={5},ret={6}", | ||
275 | m_controllingPrim.LocalID, touchPosition, nearFeetHeightMin, directionFacing, touchNormal, diff, ret); | ||
276 | } | ||
277 | } | ||
278 | } | ||
279 | } | ||
280 | |||
281 | return ret; | ||
282 | } | ||
283 | |||
284 | } | ||
285 | } | ||
286 | |||
287 | |||
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSActorHover.cs b/OpenSim/Region/Physics/BulletSPlugin/BSActorHover.cs new file mode 100755 index 0000000..8dd3700 --- /dev/null +++ b/OpenSim/Region/Physics/BulletSPlugin/BSActorHover.cs | |||
@@ -0,0 +1,176 @@ | |||
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 | |||
28 | using System; | ||
29 | using System.Collections.Generic; | ||
30 | using System.Linq; | ||
31 | using System.Text; | ||
32 | |||
33 | using OpenSim.Region.Physics.Manager; | ||
34 | |||
35 | using OMV = OpenMetaverse; | ||
36 | |||
37 | namespace OpenSim.Region.Physics.BulletSPlugin | ||
38 | { | ||
39 | public class BSActorHover : BSActor | ||
40 | { | ||
41 | private BSFMotor m_hoverMotor; | ||
42 | |||
43 | public BSActorHover(BSScene physicsScene, BSPhysObject pObj, string actorName) | ||
44 | : base(physicsScene, pObj, actorName) | ||
45 | { | ||
46 | m_hoverMotor = null; | ||
47 | m_physicsScene.DetailLog("{0},BSActorHover,constructor", m_controllingPrim.LocalID); | ||
48 | } | ||
49 | |||
50 | // BSActor.isActive | ||
51 | public override bool isActive | ||
52 | { | ||
53 | get { return Enabled && m_controllingPrim.IsPhysicallyActive; } | ||
54 | } | ||
55 | |||
56 | // Release any connections and resources used by the actor. | ||
57 | // BSActor.Dispose() | ||
58 | public override void Dispose() | ||
59 | { | ||
60 | Enabled = false; | ||
61 | } | ||
62 | |||
63 | // Called when physical parameters (properties set in Bullet) need to be re-applied. | ||
64 | // Called at taint-time. | ||
65 | // BSActor.Refresh() | ||
66 | public override void Refresh() | ||
67 | { | ||
68 | m_physicsScene.DetailLog("{0},BSActorHover,refresh", m_controllingPrim.LocalID); | ||
69 | |||
70 | // If not active any more, get rid of me (shouldn't ever happen, but just to be safe) | ||
71 | if (!m_controllingPrim.HoverActive) | ||
72 | { | ||
73 | m_physicsScene.DetailLog("{0},BSActorHover,refresh,notHovering,removing={1}", m_controllingPrim.LocalID, ActorName); | ||
74 | m_controllingPrim.PhysicalActors.RemoveAndRelease(ActorName); | ||
75 | return; | ||
76 | } | ||
77 | |||
78 | // If the object is physically active, add the hoverer prestep action | ||
79 | if (isActive) | ||
80 | { | ||
81 | ActivateHover(); | ||
82 | } | ||
83 | else | ||
84 | { | ||
85 | DeactivateHover(); | ||
86 | } | ||
87 | } | ||
88 | |||
89 | // The object's physical representation is being rebuilt so pick up any physical dependencies (constraints, ...). | ||
90 | // Register a prestep action to restore physical requirements before the next simulation step. | ||
91 | // Called at taint-time. | ||
92 | // BSActor.RemoveBodyDependencies() | ||
93 | public override void RemoveBodyDependencies() | ||
94 | { | ||
95 | // Nothing to do for the hoverer since it is all software at pre-step action time. | ||
96 | } | ||
97 | |||
98 | // If a hover motor has not been created, create one and start the hovering. | ||
99 | private void ActivateHover() | ||
100 | { | ||
101 | if (m_hoverMotor == null) | ||
102 | { | ||
103 | // Turning the target on | ||
104 | m_hoverMotor = new BSFMotor("BSActorHover", | ||
105 | m_controllingPrim.HoverTau, // timeScale | ||
106 | BSMotor.Infinite, // decay time scale | ||
107 | BSMotor.Infinite, // friction timescale | ||
108 | 1f // efficiency | ||
109 | ); | ||
110 | m_hoverMotor.SetTarget(ComputeCurrentHoverHeight()); | ||
111 | m_hoverMotor.SetCurrent(m_controllingPrim.RawPosition.Z); | ||
112 | m_hoverMotor.PhysicsScene = m_physicsScene; // DEBUG DEBUG so motor will output detail log messages. | ||
113 | |||
114 | m_physicsScene.BeforeStep += Hoverer; | ||
115 | } | ||
116 | } | ||
117 | |||
118 | private void DeactivateHover() | ||
119 | { | ||
120 | if (m_hoverMotor != null) | ||
121 | { | ||
122 | m_physicsScene.BeforeStep -= Hoverer; | ||
123 | m_hoverMotor = null; | ||
124 | } | ||
125 | } | ||
126 | |||
127 | // Called just before the simulation step. Update the vertical position for hoverness. | ||
128 | private void Hoverer(float timeStep) | ||
129 | { | ||
130 | // Don't do hovering while the object is selected. | ||
131 | if (!isActive) | ||
132 | return; | ||
133 | |||
134 | m_hoverMotor.SetCurrent(m_controllingPrim.RawPosition.Z); | ||
135 | m_hoverMotor.SetTarget(ComputeCurrentHoverHeight()); | ||
136 | float targetHeight = m_hoverMotor.Step(timeStep); | ||
137 | |||
138 | // 'targetHeight' is where we'd like the Z of the prim to be at this moment. | ||
139 | // Compute the amount of force to push us there. | ||
140 | float moveForce = (targetHeight - m_controllingPrim.RawPosition.Z) * m_controllingPrim.RawMass; | ||
141 | // Undo anything the object thinks it's doing at the moment | ||
142 | moveForce = -m_controllingPrim.RawVelocity.Z * m_controllingPrim.Mass; | ||
143 | |||
144 | m_physicsScene.PE.ApplyCentralImpulse(m_controllingPrim.PhysBody, new OMV.Vector3(0f, 0f, moveForce)); | ||
145 | m_physicsScene.DetailLog("{0},BSPrim.Hover,move,targHt={1},moveForce={2},mass={3}", | ||
146 | m_controllingPrim.LocalID, targetHeight, moveForce, m_controllingPrim.RawMass); | ||
147 | } | ||
148 | |||
149 | // Based on current position, determine what we should be hovering at now. | ||
150 | // Must recompute often. What if we walked offa cliff> | ||
151 | private float ComputeCurrentHoverHeight() | ||
152 | { | ||
153 | float ret = m_controllingPrim.HoverHeight; | ||
154 | float groundHeight = m_physicsScene.TerrainManager.GetTerrainHeightAtXYZ(m_controllingPrim.RawPosition); | ||
155 | |||
156 | switch (m_controllingPrim.HoverType) | ||
157 | { | ||
158 | case PIDHoverType.Ground: | ||
159 | ret = groundHeight + m_controllingPrim.HoverHeight; | ||
160 | break; | ||
161 | case PIDHoverType.GroundAndWater: | ||
162 | float waterHeight = m_physicsScene.TerrainManager.GetWaterLevelAtXYZ(m_controllingPrim.RawPosition); | ||
163 | if (groundHeight > waterHeight) | ||
164 | { | ||
165 | ret = groundHeight + m_controllingPrim.HoverHeight; | ||
166 | } | ||
167 | else | ||
168 | { | ||
169 | ret = waterHeight + m_controllingPrim.HoverHeight; | ||
170 | } | ||
171 | break; | ||
172 | } | ||
173 | return ret; | ||
174 | } | ||
175 | } | ||
176 | } | ||
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSActorLockAxis.cs b/OpenSim/Region/Physics/BulletSPlugin/BSActorLockAxis.cs index 7219617..c40a499 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSActorLockAxis.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSActorLockAxis.cs | |||
@@ -40,7 +40,7 @@ public class BSActorLockAxis : BSActor | |||
40 | BSConstraint LockAxisConstraint = null; | 40 | BSConstraint LockAxisConstraint = null; |
41 | 41 | ||
42 | public BSActorLockAxis(BSScene physicsScene, BSPhysObject pObj, string actorName) | 42 | public BSActorLockAxis(BSScene physicsScene, BSPhysObject pObj, string actorName) |
43 | : base(physicsScene, pObj,actorName) | 43 | : base(physicsScene, pObj, actorName) |
44 | { | 44 | { |
45 | m_physicsScene.DetailLog("{0},BSActorLockAxis,constructor", m_controllingPrim.LocalID); | 45 | m_physicsScene.DetailLog("{0},BSActorLockAxis,constructor", m_controllingPrim.LocalID); |
46 | LockAxisConstraint = null; | 46 | LockAxisConstraint = null; |
@@ -99,7 +99,7 @@ public class BSActorLockAxis : BSActor | |||
99 | // If a constraint is set up, remove it from the physical scene | 99 | // If a constraint is set up, remove it from the physical scene |
100 | RemoveAxisLockConstraint(); | 100 | RemoveAxisLockConstraint(); |
101 | // Schedule a call before the next simulation step to restore the constraint. | 101 | // Schedule a call before the next simulation step to restore the constraint. |
102 | m_physicsScene.PostTaintObject(m_controllingPrim.LockedAxisActorName, m_controllingPrim.LocalID, delegate() | 102 | m_physicsScene.PostTaintObject("BSActorLockAxis:" + ActorName, m_controllingPrim.LocalID, delegate() |
103 | { | 103 | { |
104 | Refresh(); | 104 | Refresh(); |
105 | }); | 105 | }); |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSActorMoveToTarget.cs b/OpenSim/Region/Physics/BulletSPlugin/BSActorMoveToTarget.cs new file mode 100755 index 0000000..3517ef2 --- /dev/null +++ b/OpenSim/Region/Physics/BulletSPlugin/BSActorMoveToTarget.cs | |||
@@ -0,0 +1,156 @@ | |||
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 | |||
28 | using System; | ||
29 | using System.Collections.Generic; | ||
30 | using System.Linq; | ||
31 | using System.Text; | ||
32 | |||
33 | using OpenSim.Region.Physics.Manager; | ||
34 | |||
35 | using OMV = OpenMetaverse; | ||
36 | |||
37 | namespace OpenSim.Region.Physics.BulletSPlugin | ||
38 | { | ||
39 | public class BSActorMoveToTarget : BSActor | ||
40 | { | ||
41 | private BSVMotor m_targetMotor; | ||
42 | |||
43 | public BSActorMoveToTarget(BSScene physicsScene, BSPhysObject pObj, string actorName) | ||
44 | : base(physicsScene, pObj, actorName) | ||
45 | { | ||
46 | m_targetMotor = null; | ||
47 | m_physicsScene.DetailLog("{0},BSActorMoveToTarget,constructor", m_controllingPrim.LocalID); | ||
48 | } | ||
49 | |||
50 | // BSActor.isActive | ||
51 | public override bool isActive | ||
52 | { | ||
53 | get { return Enabled && m_controllingPrim.IsPhysicallyActive; } | ||
54 | } | ||
55 | |||
56 | // Release any connections and resources used by the actor. | ||
57 | // BSActor.Dispose() | ||
58 | public override void Dispose() | ||
59 | { | ||
60 | Enabled = false; | ||
61 | } | ||
62 | |||
63 | // Called when physical parameters (properties set in Bullet) need to be re-applied. | ||
64 | // Called at taint-time. | ||
65 | // BSActor.Refresh() | ||
66 | public override void Refresh() | ||
67 | { | ||
68 | m_physicsScene.DetailLog("{0},BSActorMoveToTarget,refresh", m_controllingPrim.LocalID); | ||
69 | |||
70 | // If not active any more, get rid of me (shouldn't ever happen, but just to be safe) | ||
71 | if (!m_controllingPrim.HoverActive) | ||
72 | { | ||
73 | m_physicsScene.DetailLog("{0},BSActorMoveToTarget,refresh,notMoveToTarget,removing={1}", m_controllingPrim.LocalID, ActorName); | ||
74 | m_controllingPrim.PhysicalActors.RemoveAndRelease(ActorName); | ||
75 | return; | ||
76 | } | ||
77 | |||
78 | // If the object is physically active, add the hoverer prestep action | ||
79 | if (isActive) | ||
80 | { | ||
81 | ActivateMoveToTarget(); | ||
82 | } | ||
83 | else | ||
84 | { | ||
85 | DeactivateMoveToTarget(); | ||
86 | } | ||
87 | } | ||
88 | |||
89 | // The object's physical representation is being rebuilt so pick up any physical dependencies (constraints, ...). | ||
90 | // Register a prestep action to restore physical requirements before the next simulation step. | ||
91 | // Called at taint-time. | ||
92 | // BSActor.RemoveBodyDependencies() | ||
93 | public override void RemoveBodyDependencies() | ||
94 | { | ||
95 | // Nothing to do for the hoverer since it is all software at pre-step action time. | ||
96 | } | ||
97 | |||
98 | // If a hover motor has not been created, create one and start the hovering. | ||
99 | private void ActivateMoveToTarget() | ||
100 | { | ||
101 | if (m_targetMotor == null) | ||
102 | { | ||
103 | // We're taking over after this. | ||
104 | m_controllingPrim.ZeroMotion(true); | ||
105 | |||
106 | m_targetMotor = new BSVMotor("BSPrim.PIDTarget", | ||
107 | m_controllingPrim.MoveToTargetTau, // timeScale | ||
108 | BSMotor.Infinite, // decay time scale | ||
109 | BSMotor.InfiniteVector, // friction timescale | ||
110 | 1f // efficiency | ||
111 | ); | ||
112 | m_targetMotor.PhysicsScene = m_physicsScene; // DEBUG DEBUG so motor will output detail log messages. | ||
113 | m_targetMotor.SetTarget(m_controllingPrim.MoveToTargetTarget); | ||
114 | m_targetMotor.SetCurrent(m_controllingPrim.RawPosition); | ||
115 | |||
116 | m_physicsScene.BeforeStep += Mover; | ||
117 | } | ||
118 | } | ||
119 | |||
120 | private void DeactivateMoveToTarget() | ||
121 | { | ||
122 | if (m_targetMotor != null) | ||
123 | { | ||
124 | m_physicsScene.BeforeStep -= Mover; | ||
125 | m_targetMotor = null; | ||
126 | } | ||
127 | } | ||
128 | |||
129 | // Called just before the simulation step. Update the vertical position for hoverness. | ||
130 | private void Mover(float timeStep) | ||
131 | { | ||
132 | // Don't do hovering while the object is selected. | ||
133 | if (!isActive) | ||
134 | return; | ||
135 | |||
136 | OMV.Vector3 origPosition = m_controllingPrim.RawPosition; // DEBUG DEBUG (for printout below) | ||
137 | |||
138 | // 'movePosition' is where we'd like the prim to be at this moment. | ||
139 | OMV.Vector3 movePosition = m_controllingPrim.RawPosition + m_targetMotor.Step(timeStep); | ||
140 | |||
141 | // If we are very close to our target, turn off the movement motor. | ||
142 | if (m_targetMotor.ErrorIsZero()) | ||
143 | { | ||
144 | m_physicsScene.DetailLog("{0},BSPrim.PIDTarget,zeroMovement,movePos={1},pos={2},mass={3}", | ||
145 | m_controllingPrim.LocalID, movePosition, m_controllingPrim.RawPosition, m_controllingPrim.Mass); | ||
146 | m_controllingPrim.ForcePosition = m_targetMotor.TargetValue; | ||
147 | m_targetMotor.Enabled = false; | ||
148 | } | ||
149 | else | ||
150 | { | ||
151 | m_controllingPrim.ForcePosition = movePosition; | ||
152 | } | ||
153 | m_physicsScene.DetailLog("{0},BSPrim.PIDTarget,move,fromPos={1},movePos={2}", m_controllingPrim.LocalID, origPosition, movePosition); | ||
154 | } | ||
155 | } | ||
156 | } | ||
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSActorSetForce.cs b/OpenSim/Region/Physics/BulletSPlugin/BSActorSetForce.cs new file mode 100755 index 0000000..d942490 --- /dev/null +++ b/OpenSim/Region/Physics/BulletSPlugin/BSActorSetForce.cs | |||
@@ -0,0 +1,137 @@ | |||
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 | |||
28 | using System; | ||
29 | using System.Collections.Generic; | ||
30 | using System.Linq; | ||
31 | using System.Text; | ||
32 | |||
33 | using OpenSim.Region.Physics.Manager; | ||
34 | |||
35 | using OMV = OpenMetaverse; | ||
36 | |||
37 | namespace OpenSim.Region.Physics.BulletSPlugin | ||
38 | { | ||
39 | public class BSActorSetForce : BSActor | ||
40 | { | ||
41 | BSFMotor m_forceMotor; | ||
42 | |||
43 | public BSActorSetForce(BSScene physicsScene, BSPhysObject pObj, string actorName) | ||
44 | : base(physicsScene, pObj, actorName) | ||
45 | { | ||
46 | m_forceMotor = null; | ||
47 | m_physicsScene.DetailLog("{0},BSActorSetForce,constructor", m_controllingPrim.LocalID); | ||
48 | } | ||
49 | |||
50 | // BSActor.isActive | ||
51 | public override bool isActive | ||
52 | { | ||
53 | get { return Enabled && m_controllingPrim.IsPhysicallyActive; } | ||
54 | } | ||
55 | |||
56 | // Release any connections and resources used by the actor. | ||
57 | // BSActor.Dispose() | ||
58 | public override void Dispose() | ||
59 | { | ||
60 | Enabled = false; | ||
61 | } | ||
62 | |||
63 | // Called when physical parameters (properties set in Bullet) need to be re-applied. | ||
64 | // Called at taint-time. | ||
65 | // BSActor.Refresh() | ||
66 | public override void Refresh() | ||
67 | { | ||
68 | m_physicsScene.DetailLog("{0},BSActorSetForce,refresh", m_controllingPrim.LocalID); | ||
69 | |||
70 | // If not active any more, get rid of me (shouldn't ever happen, but just to be safe) | ||
71 | if (m_controllingPrim.RawForce == OMV.Vector3.Zero) | ||
72 | { | ||
73 | m_physicsScene.DetailLog("{0},BSActorSetForce,refresh,notSetForce,removing={1}", m_controllingPrim.LocalID, ActorName); | ||
74 | m_controllingPrim.PhysicalActors.RemoveAndRelease(ActorName); | ||
75 | return; | ||
76 | } | ||
77 | |||
78 | // If the object is physically active, add the hoverer prestep action | ||
79 | if (isActive) | ||
80 | { | ||
81 | ActivateSetForce(); | ||
82 | } | ||
83 | else | ||
84 | { | ||
85 | DeactivateSetForce(); | ||
86 | } | ||
87 | } | ||
88 | |||
89 | // The object's physical representation is being rebuilt so pick up any physical dependencies (constraints, ...). | ||
90 | // Register a prestep action to restore physical requirements before the next simulation step. | ||
91 | // Called at taint-time. | ||
92 | // BSActor.RemoveBodyDependencies() | ||
93 | public override void RemoveBodyDependencies() | ||
94 | { | ||
95 | // Nothing to do for the hoverer since it is all software at pre-step action time. | ||
96 | } | ||
97 | |||
98 | // If a hover motor has not been created, create one and start the hovering. | ||
99 | private void ActivateSetForce() | ||
100 | { | ||
101 | if (m_forceMotor == null) | ||
102 | { | ||
103 | // A fake motor that might be used someday | ||
104 | m_forceMotor = new BSFMotor("setForce", 1f, 1f, 1f, 1f); | ||
105 | |||
106 | m_physicsScene.BeforeStep += Mover; | ||
107 | } | ||
108 | } | ||
109 | |||
110 | private void DeactivateSetForce() | ||
111 | { | ||
112 | if (m_forceMotor != null) | ||
113 | { | ||
114 | m_physicsScene.BeforeStep -= Mover; | ||
115 | m_forceMotor = null; | ||
116 | } | ||
117 | } | ||
118 | |||
119 | // Called just before the simulation step. Update the vertical position for hoverness. | ||
120 | private void Mover(float timeStep) | ||
121 | { | ||
122 | // Don't do force while the object is selected. | ||
123 | if (!isActive) | ||
124 | return; | ||
125 | |||
126 | m_physicsScene.DetailLog("{0},BSActorSetForce,preStep,force={1}", m_controllingPrim.LocalID, m_controllingPrim.RawForce); | ||
127 | if (m_controllingPrim.PhysBody.HasPhysicalBody) | ||
128 | { | ||
129 | m_physicsScene.PE.ApplyCentralForce(m_controllingPrim.PhysBody, m_controllingPrim.RawForce); | ||
130 | m_controllingPrim.ActivateIfPhysical(false); | ||
131 | } | ||
132 | |||
133 | // TODO: | ||
134 | } | ||
135 | } | ||
136 | } | ||
137 | |||
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSActorSetTorque.cs b/OpenSim/Region/Physics/BulletSPlugin/BSActorSetTorque.cs new file mode 100755 index 0000000..e0f719f --- /dev/null +++ b/OpenSim/Region/Physics/BulletSPlugin/BSActorSetTorque.cs | |||
@@ -0,0 +1,138 @@ | |||
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 | |||
28 | using System; | ||
29 | using System.Collections.Generic; | ||
30 | using System.Linq; | ||
31 | using System.Text; | ||
32 | |||
33 | using OpenSim.Region.Physics.Manager; | ||
34 | |||
35 | using OMV = OpenMetaverse; | ||
36 | |||
37 | namespace OpenSim.Region.Physics.BulletSPlugin | ||
38 | { | ||
39 | public class BSActorSetTorque : BSActor | ||
40 | { | ||
41 | BSFMotor m_torqueMotor; | ||
42 | |||
43 | public BSActorSetTorque(BSScene physicsScene, BSPhysObject pObj, string actorName) | ||
44 | : base(physicsScene, pObj, actorName) | ||
45 | { | ||
46 | m_torqueMotor = null; | ||
47 | m_physicsScene.DetailLog("{0},BSActorSetTorque,constructor", m_controllingPrim.LocalID); | ||
48 | } | ||
49 | |||
50 | // BSActor.isActive | ||
51 | public override bool isActive | ||
52 | { | ||
53 | get { return Enabled && m_controllingPrim.IsPhysicallyActive; } | ||
54 | } | ||
55 | |||
56 | // Release any connections and resources used by the actor. | ||
57 | // BSActor.Dispose() | ||
58 | public override void Dispose() | ||
59 | { | ||
60 | Enabled = false; | ||
61 | } | ||
62 | |||
63 | // Called when physical parameters (properties set in Bullet) need to be re-applied. | ||
64 | // Called at taint-time. | ||
65 | // BSActor.Refresh() | ||
66 | public override void Refresh() | ||
67 | { | ||
68 | m_physicsScene.DetailLog("{0},BSActorSetTorque,refresh", m_controllingPrim.LocalID); | ||
69 | |||
70 | // If not active any more, get rid of me (shouldn't ever happen, but just to be safe) | ||
71 | if (m_controllingPrim.RawTorque == OMV.Vector3.Zero) | ||
72 | { | ||
73 | m_physicsScene.DetailLog("{0},BSActorSetTorque,refresh,notSetTorque,removing={1}", m_controllingPrim.LocalID, ActorName); | ||
74 | m_controllingPrim.PhysicalActors.RemoveAndRelease(ActorName); | ||
75 | return; | ||
76 | } | ||
77 | |||
78 | // If the object is physically active, add the hoverer prestep action | ||
79 | if (isActive) | ||
80 | { | ||
81 | ActivateSetTorque(); | ||
82 | } | ||
83 | else | ||
84 | { | ||
85 | DeactivateSetTorque(); | ||
86 | } | ||
87 | } | ||
88 | |||
89 | // The object's physical representation is being rebuilt so pick up any physical dependencies (constraints, ...). | ||
90 | // Register a prestep action to restore physical requirements before the next simulation step. | ||
91 | // Called at taint-time. | ||
92 | // BSActor.RemoveBodyDependencies() | ||
93 | public override void RemoveBodyDependencies() | ||
94 | { | ||
95 | // Nothing to do for the hoverer since it is all software at pre-step action time. | ||
96 | } | ||
97 | |||
98 | // If a hover motor has not been created, create one and start the hovering. | ||
99 | private void ActivateSetTorque() | ||
100 | { | ||
101 | if (m_torqueMotor == null) | ||
102 | { | ||
103 | // A fake motor that might be used someday | ||
104 | m_torqueMotor = new BSFMotor("setTorque", 1f, 1f, 1f, 1f); | ||
105 | |||
106 | m_physicsScene.BeforeStep += Mover; | ||
107 | } | ||
108 | } | ||
109 | |||
110 | private void DeactivateSetTorque() | ||
111 | { | ||
112 | if (m_torqueMotor != null) | ||
113 | { | ||
114 | m_physicsScene.BeforeStep -= Mover; | ||
115 | m_torqueMotor = null; | ||
116 | } | ||
117 | } | ||
118 | |||
119 | // Called just before the simulation step. Update the vertical position for hoverness. | ||
120 | private void Mover(float timeStep) | ||
121 | { | ||
122 | // Don't do force while the object is selected. | ||
123 | if (!isActive) | ||
124 | return; | ||
125 | |||
126 | m_physicsScene.DetailLog("{0},BSActorSetTorque,preStep,force={1}", m_controllingPrim.LocalID, m_controllingPrim.RawTorque); | ||
127 | if (m_controllingPrim.PhysBody.HasPhysicalBody) | ||
128 | { | ||
129 | m_controllingPrim.AddAngularForce(m_controllingPrim.RawTorque, false, true); | ||
130 | m_controllingPrim.ActivateIfPhysical(false); | ||
131 | } | ||
132 | |||
133 | // TODO: | ||
134 | } | ||
135 | } | ||
136 | } | ||
137 | |||
138 | |||
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSActors.cs b/OpenSim/Region/Physics/BulletSPlugin/BSActors.cs index 5a19ba4..fb4d452 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSActors.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSActors.cs | |||
@@ -32,12 +32,12 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
32 | { | 32 | { |
33 | public class BSActorCollection | 33 | public class BSActorCollection |
34 | { | 34 | { |
35 | private BSScene PhysicsScene { get; set; } | 35 | private BSScene m_physicsScene { get; set; } |
36 | private Dictionary<string, BSActor> m_actors; | 36 | private Dictionary<string, BSActor> m_actors; |
37 | 37 | ||
38 | public BSActorCollection(BSScene physicsScene) | 38 | public BSActorCollection(BSScene physicsScene) |
39 | { | 39 | { |
40 | PhysicsScene = physicsScene; | 40 | m_physicsScene = physicsScene; |
41 | m_actors = new Dictionary<string, BSActor>(); | 41 | m_actors = new Dictionary<string, BSActor>(); |
42 | } | 42 | } |
43 | public void Add(string name, BSActor actor) | 43 | public void Add(string name, BSActor actor) |
@@ -61,6 +61,10 @@ public class BSActorCollection | |||
61 | Release(); | 61 | Release(); |
62 | m_actors.Clear(); | 62 | m_actors.Clear(); |
63 | } | 63 | } |
64 | public void Dispose() | ||
65 | { | ||
66 | Clear(); | ||
67 | } | ||
64 | public bool HasActor(string name) | 68 | public bool HasActor(string name) |
65 | { | 69 | { |
66 | return m_actors.ContainsKey(name); | 70 | return m_actors.ContainsKey(name); |
@@ -71,6 +75,10 @@ public class BSActorCollection | |||
71 | act(kvp.Value); | 75 | act(kvp.Value); |
72 | } | 76 | } |
73 | 77 | ||
78 | public void Enable(bool enabl) | ||
79 | { | ||
80 | ForEachActor(a => a.Enable(enabl)); | ||
81 | } | ||
74 | public void Release() | 82 | public void Release() |
75 | { | 83 | { |
76 | ForEachActor(a => a.Dispose()); | 84 | ForEachActor(a => a.Dispose()); |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index 25be416..09c9b16 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs | |||
@@ -46,9 +46,6 @@ public sealed class BSCharacter : BSPhysObject | |||
46 | private OMV.Vector3 _position; | 46 | private OMV.Vector3 _position; |
47 | private float _mass; | 47 | private float _mass; |
48 | private float _avatarVolume; | 48 | private float _avatarVolume; |
49 | private OMV.Vector3 _force; | ||
50 | private OMV.Vector3 _velocity; | ||
51 | private OMV.Vector3 _torque; | ||
52 | private float _collisionScore; | 49 | private float _collisionScore; |
53 | private OMV.Vector3 _acceleration; | 50 | private OMV.Vector3 _acceleration; |
54 | private OMV.Quaternion _orientation; | 51 | private OMV.Quaternion _orientation; |
@@ -61,17 +58,13 @@ public sealed class BSCharacter : BSPhysObject | |||
61 | private OMV.Vector3 _rotationalVelocity; | 58 | private OMV.Vector3 _rotationalVelocity; |
62 | private bool _kinematic; | 59 | private bool _kinematic; |
63 | private float _buoyancy; | 60 | private float _buoyancy; |
64 | private bool _isStationaryStanding; // true is standing on a stationary object | ||
65 | 61 | ||
66 | private BSVMotor _velocityMotor; | 62 | private BSActorAvatarMove m_moveActor; |
63 | private const string AvatarMoveActorName = "BSCharacter.AvatarMove"; | ||
67 | 64 | ||
68 | private OMV.Vector3 _PIDTarget; | 65 | private OMV.Vector3 _PIDTarget; |
69 | private bool _usePID; | 66 | private bool _usePID; |
70 | private float _PIDTau; | 67 | private float _PIDTau; |
71 | private bool _useHoverPID; | ||
72 | private float _PIDHoverHeight; | ||
73 | private PIDHoverType _PIDHoverType; | ||
74 | private float _PIDHoverTao; | ||
75 | 68 | ||
76 | public BSCharacter(uint localID, String avName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 size, bool isFlying) | 69 | public BSCharacter(uint localID, String avName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 size, bool isFlying) |
77 | : base(parent_scene, localID, avName, "BSCharacter") | 70 | : base(parent_scene, localID, avName, "BSCharacter") |
@@ -81,11 +74,10 @@ public sealed class BSCharacter : BSPhysObject | |||
81 | 74 | ||
82 | _flying = isFlying; | 75 | _flying = isFlying; |
83 | _orientation = OMV.Quaternion.Identity; | 76 | _orientation = OMV.Quaternion.Identity; |
84 | _velocity = OMV.Vector3.Zero; | 77 | RawVelocity = OMV.Vector3.Zero; |
85 | _buoyancy = ComputeBuoyancyFromFlying(isFlying); | 78 | _buoyancy = ComputeBuoyancyFromFlying(isFlying); |
86 | Friction = BSParam.AvatarStandingFriction; | 79 | Friction = BSParam.AvatarStandingFriction; |
87 | Density = BSParam.AvatarDensity / BSParam.DensityScaleFactor; | 80 | Density = BSParam.AvatarDensity / BSParam.DensityScaleFactor; |
88 | _isStationaryStanding = false; | ||
89 | 81 | ||
90 | // Old versions of ScenePresence passed only the height. If width and/or depth are zero, | 82 | // Old versions of ScenePresence passed only the height. If width and/or depth are zero, |
91 | // replace with the default values. | 83 | // replace with the default values. |
@@ -99,7 +91,12 @@ public sealed class BSCharacter : BSPhysObject | |||
99 | // set _avatarVolume and _mass based on capsule size, _density and Scale | 91 | // set _avatarVolume and _mass based on capsule size, _density and Scale |
100 | ComputeAvatarVolumeAndMass(); | 92 | ComputeAvatarVolumeAndMass(); |
101 | 93 | ||
102 | SetupMovementMotor(); | 94 | // The avatar's movement is controlled by this motor that speeds up and slows down |
95 | // the avatar seeking to reach the motor's target speed. | ||
96 | // This motor runs as a prestep action for the avatar so it will keep the avatar | ||
97 | // standing as well as moving. Destruction of the avatar will destroy the pre-step action. | ||
98 | m_moveActor = new BSActorAvatarMove(PhysicsScene, this, AvatarMoveActorName); | ||
99 | PhysicalActors.Add(AvatarMoveActorName, m_moveActor); | ||
103 | 100 | ||
104 | DetailLog("{0},BSCharacter.create,call,size={1},scale={2},density={3},volume={4},mass={5}", | 101 | DetailLog("{0},BSCharacter.create,call,size={1},scale={2},density={3},volume={4},mass={5}", |
105 | LocalID, _size, Scale, Density, _avatarVolume, RawMass); | 102 | LocalID, _size, Scale, Density, _avatarVolume, RawMass); |
@@ -139,10 +136,10 @@ public sealed class BSCharacter : BSPhysObject | |||
139 | ForcePosition = _position; | 136 | ForcePosition = _position; |
140 | 137 | ||
141 | // Set the velocity | 138 | // Set the velocity |
142 | _velocityMotor.Reset(); | 139 | if (m_moveActor != null) |
143 | _velocityMotor.SetTarget(_velocity); | 140 | m_moveActor.SetVelocityAndTarget(RawVelocity, RawVelocity, false); |
144 | _velocityMotor.SetCurrent(_velocity); | 141 | |
145 | ForceVelocity = _velocity; | 142 | ForceVelocity = RawVelocity; |
146 | 143 | ||
147 | // This will enable or disable the flying buoyancy of the avatar. | 144 | // This will enable or disable the flying buoyancy of the avatar. |
148 | // Needs to be reset especially when an avatar is recreated after crossing a region boundry. | 145 | // Needs to be reset especially when an avatar is recreated after crossing a region boundry. |
@@ -176,162 +173,6 @@ public sealed class BSCharacter : BSPhysObject | |||
176 | PhysBody.ApplyCollisionMask(PhysicsScene); | 173 | PhysBody.ApplyCollisionMask(PhysicsScene); |
177 | } | 174 | } |
178 | 175 | ||
179 | // The avatar's movement is controlled by this motor that speeds up and slows down | ||
180 | // the avatar seeking to reach the motor's target speed. | ||
181 | // This motor runs as a prestep action for the avatar so it will keep the avatar | ||
182 | // standing as well as moving. Destruction of the avatar will destroy the pre-step action. | ||
183 | private void SetupMovementMotor() | ||
184 | { | ||
185 | // Infinite decay and timescale values so motor only changes current to target values. | ||
186 | _velocityMotor = new BSVMotor("BSCharacter.Velocity", | ||
187 | 0.2f, // time scale | ||
188 | BSMotor.Infinite, // decay time scale | ||
189 | BSMotor.InfiniteVector, // friction timescale | ||
190 | 1f // efficiency | ||
191 | ); | ||
192 | // _velocityMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG so motor will output detail log messages. | ||
193 | |||
194 | RegisterPreStepAction("BSCharactor.Movement", LocalID, delegate(float timeStep) | ||
195 | { | ||
196 | // TODO: Decide if the step parameters should be changed depending on the avatar's | ||
197 | // state (flying, colliding, ...). There is code in ODE to do this. | ||
198 | |||
199 | // COMMENTARY: when the user is making the avatar walk, except for falling, the velocity | ||
200 | // specified for the avatar is the one that should be used. For falling, if the avatar | ||
201 | // is not flying and is not colliding then it is presumed to be falling and the Z | ||
202 | // component is not fooled with (thus allowing gravity to do its thing). | ||
203 | // When the avatar is standing, though, the user has specified a velocity of zero and | ||
204 | // the avatar should be standing. But if the avatar is pushed by something in the world | ||
205 | // (raising elevator platform, moving vehicle, ...) the avatar should be allowed to | ||
206 | // move. Thus, the velocity cannot be forced to zero. The problem is that small velocity | ||
207 | // errors can creap in and the avatar will slowly float off in some direction. | ||
208 | // So, the problem is that, when an avatar is standing, we cannot tell creaping error | ||
209 | // from real pushing. | ||
210 | // The code below uses whether the collider is static or moving to decide whether to zero motion. | ||
211 | |||
212 | _velocityMotor.Step(timeStep); | ||
213 | _isStationaryStanding = false; | ||
214 | |||
215 | // If we're not supposed to be moving, make sure things are zero. | ||
216 | if (_velocityMotor.ErrorIsZero() && _velocityMotor.TargetValue == OMV.Vector3.Zero) | ||
217 | { | ||
218 | // The avatar shouldn't be moving | ||
219 | _velocityMotor.Zero(); | ||
220 | |||
221 | if (IsColliding) | ||
222 | { | ||
223 | // If we are colliding with a stationary object, presume we're standing and don't move around | ||
224 | if (!ColliderIsMoving) | ||
225 | { | ||
226 | DetailLog("{0},BSCharacter.MoveMotor,collidingWithStationary,zeroingMotion", LocalID); | ||
227 | _isStationaryStanding = true; | ||
228 | ZeroMotion(true /* inTaintTime */); | ||
229 | } | ||
230 | |||
231 | // Standing has more friction on the ground | ||
232 | if (Friction != BSParam.AvatarStandingFriction) | ||
233 | { | ||
234 | Friction = BSParam.AvatarStandingFriction; | ||
235 | PhysicsScene.PE.SetFriction(PhysBody, Friction); | ||
236 | } | ||
237 | } | ||
238 | else | ||
239 | { | ||
240 | if (Flying) | ||
241 | { | ||
242 | // Flying and not collising and velocity nearly zero. | ||
243 | ZeroMotion(true /* inTaintTime */); | ||
244 | } | ||
245 | } | ||
246 | |||
247 | DetailLog("{0},BSCharacter.MoveMotor,taint,stopping,target={1},colliding={2}", LocalID, _velocityMotor.TargetValue, IsColliding); | ||
248 | } | ||
249 | else | ||
250 | { | ||
251 | // Supposed to be moving. | ||
252 | OMV.Vector3 stepVelocity = _velocityMotor.CurrentValue; | ||
253 | |||
254 | if (Friction != BSParam.AvatarFriction) | ||
255 | { | ||
256 | // Probably starting up walking. Set friction to moving friction. | ||
257 | Friction = BSParam.AvatarFriction; | ||
258 | PhysicsScene.PE.SetFriction(PhysBody, Friction); | ||
259 | } | ||
260 | |||
261 | // If falling, we keep the world's downward vector no matter what the other axis specify. | ||
262 | // The check for _velocity.Z < 0 makes jumping work (temporary upward force). | ||
263 | if (!Flying && !IsColliding) | ||
264 | { | ||
265 | if (_velocity.Z < 0) | ||
266 | stepVelocity.Z = _velocity.Z; | ||
267 | // DetailLog("{0},BSCharacter.MoveMotor,taint,overrideStepZWithWorldZ,stepVel={1}", LocalID, stepVelocity); | ||
268 | } | ||
269 | |||
270 | // 'stepVelocity' is now the speed we'd like the avatar to move in. Turn that into an instantanous force. | ||
271 | OMV.Vector3 moveForce = (stepVelocity - _velocity) * Mass; | ||
272 | |||
273 | // Should we check for move force being small and forcing velocity to zero? | ||
274 | |||
275 | // Add special movement force to allow avatars to walk up stepped surfaces. | ||
276 | moveForce += WalkUpStairs(); | ||
277 | |||
278 | DetailLog("{0},BSCharacter.MoveMotor,move,stepVel={1},vel={2},mass={3},moveForce={4}", LocalID, stepVelocity, _velocity, Mass, moveForce); | ||
279 | PhysicsScene.PE.ApplyCentralImpulse(PhysBody, moveForce); | ||
280 | } | ||
281 | }); | ||
282 | } | ||
283 | |||
284 | // Decide if the character is colliding with a low object and compute a force to pop the | ||
285 | // avatar up so it can walk up and over the low objects. | ||
286 | private OMV.Vector3 WalkUpStairs() | ||
287 | { | ||
288 | OMV.Vector3 ret = OMV.Vector3.Zero; | ||
289 | |||
290 | // This test is done if moving forward, not flying and is colliding with something. | ||
291 | // DetailLog("{0},BSCharacter.WalkUpStairs,IsColliding={1},flying={2},targSpeed={3},collisions={4}", | ||
292 | // LocalID, IsColliding, Flying, TargetSpeed, CollisionsLastTick.Count); | ||
293 | if (IsColliding && !Flying && TargetVelocitySpeed > 0.1f /* && ForwardSpeed < 0.1f */) | ||
294 | { | ||
295 | // The range near the character's feet where we will consider stairs | ||
296 | float nearFeetHeightMin = RawPosition.Z - (Size.Z / 2f) + 0.05f; | ||
297 | float nearFeetHeightMax = nearFeetHeightMin + BSParam.AvatarStepHeight; | ||
298 | |||
299 | // Look for a collision point that is near the character's feet and is oriented the same as the charactor is | ||
300 | foreach (KeyValuePair<uint, ContactPoint> kvp in CollisionsLastTick.m_objCollisionList) | ||
301 | { | ||
302 | // Don't care about collisions with the terrain | ||
303 | if (kvp.Key > PhysicsScene.TerrainManager.HighestTerrainID) | ||
304 | { | ||
305 | OMV.Vector3 touchPosition = kvp.Value.Position; | ||
306 | // DetailLog("{0},BSCharacter.WalkUpStairs,min={1},max={2},touch={3}", | ||
307 | // LocalID, nearFeetHeightMin, nearFeetHeightMax, touchPosition); | ||
308 | if (touchPosition.Z >= nearFeetHeightMin && touchPosition.Z <= nearFeetHeightMax) | ||
309 | { | ||
310 | // This contact is within the 'near the feet' range. | ||
311 | // The normal should be our contact point to the object so it is pointing away | ||
312 | // thus the difference between our facing orientation and the normal should be small. | ||
313 | OMV.Vector3 directionFacing = OMV.Vector3.UnitX * RawOrientation; | ||
314 | OMV.Vector3 touchNormal = OMV.Vector3.Normalize(kvp.Value.SurfaceNormal); | ||
315 | float diff = Math.Abs(OMV.Vector3.Distance(directionFacing, touchNormal)); | ||
316 | if (diff < BSParam.AvatarStepApproachFactor) | ||
317 | { | ||
318 | // Found the stairs contact point. Push up a little to raise the character. | ||
319 | float upForce = (touchPosition.Z - nearFeetHeightMin) * Mass * BSParam.AvatarStepForceFactor; | ||
320 | ret = new OMV.Vector3(0f, 0f, upForce); | ||
321 | |||
322 | // Also move the avatar up for the new height | ||
323 | OMV.Vector3 displacement = new OMV.Vector3(0f, 0f, BSParam.AvatarStepHeight / 2f); | ||
324 | ForcePosition = RawPosition + displacement; | ||
325 | } | ||
326 | DetailLog("{0},BSCharacter.WalkUpStairs,touchPos={1},nearFeetMin={2},faceDir={3},norm={4},diff={5},ret={6}", | ||
327 | LocalID, touchPosition, nearFeetHeightMin, directionFacing, touchNormal, diff, ret); | ||
328 | } | ||
329 | } | ||
330 | } | ||
331 | } | ||
332 | |||
333 | return ret; | ||
334 | } | ||
335 | 176 | ||
336 | public override void RequestPhysicsterseUpdate() | 177 | public override void RequestPhysicsterseUpdate() |
337 | { | 178 | { |
@@ -403,7 +244,7 @@ public sealed class BSCharacter : BSPhysObject | |||
403 | // Called at taint time! | 244 | // Called at taint time! |
404 | public override void ZeroMotion(bool inTaintTime) | 245 | public override void ZeroMotion(bool inTaintTime) |
405 | { | 246 | { |
406 | _velocity = OMV.Vector3.Zero; | 247 | RawVelocity = OMV.Vector3.Zero; |
407 | _acceleration = OMV.Vector3.Zero; | 248 | _acceleration = OMV.Vector3.Zero; |
408 | _rotationalVelocity = OMV.Vector3.Zero; | 249 | _rotationalVelocity = OMV.Vector3.Zero; |
409 | 250 | ||
@@ -542,15 +383,15 @@ public sealed class BSCharacter : BSPhysObject | |||
542 | } | 383 | } |
543 | 384 | ||
544 | public override OMV.Vector3 Force { | 385 | public override OMV.Vector3 Force { |
545 | get { return _force; } | 386 | get { return RawForce; } |
546 | set { | 387 | set { |
547 | _force = value; | 388 | RawForce = value; |
548 | // m_log.DebugFormat("{0}: Force = {1}", LogHeader, _force); | 389 | // m_log.DebugFormat("{0}: Force = {1}", LogHeader, _force); |
549 | PhysicsScene.TaintedObject("BSCharacter.SetForce", delegate() | 390 | PhysicsScene.TaintedObject("BSCharacter.SetForce", delegate() |
550 | { | 391 | { |
551 | DetailLog("{0},BSCharacter.setForce,taint,force={1}", LocalID, _force); | 392 | DetailLog("{0},BSCharacter.setForce,taint,force={1}", LocalID, RawForce); |
552 | if (PhysBody.HasPhysicalBody) | 393 | if (PhysBody.HasPhysicalBody) |
553 | PhysicsScene.PE.SetObjectForce(PhysBody, _force); | 394 | PhysicsScene.PE.SetObjectForce(PhysBody, RawForce); |
554 | }); | 395 | }); |
555 | } | 396 | } |
556 | } | 397 | } |
@@ -573,7 +414,7 @@ public sealed class BSCharacter : BSPhysObject | |||
573 | { | 414 | { |
574 | get | 415 | get |
575 | { | 416 | { |
576 | return m_targetVelocity; | 417 | return base.m_targetVelocity; |
577 | } | 418 | } |
578 | set | 419 | set |
579 | { | 420 | { |
@@ -583,51 +424,39 @@ public sealed class BSCharacter : BSPhysObject | |||
583 | if (_setAlwaysRun) | 424 | if (_setAlwaysRun) |
584 | targetVel *= new OMV.Vector3(BSParam.AvatarAlwaysRunFactor, BSParam.AvatarAlwaysRunFactor, 0f); | 425 | targetVel *= new OMV.Vector3(BSParam.AvatarAlwaysRunFactor, BSParam.AvatarAlwaysRunFactor, 0f); |
585 | 426 | ||
586 | PhysicsScene.TaintedObject("BSCharacter.setTargetVelocity", delegate() | 427 | if (m_moveActor != null) |
587 | { | 428 | m_moveActor.SetVelocityAndTarget(RawVelocity, targetVel, false /* inTaintTime */); |
588 | _velocityMotor.Reset(); | ||
589 | _velocityMotor.SetTarget(targetVel); | ||
590 | _velocityMotor.SetCurrent(_velocity); | ||
591 | _velocityMotor.Enabled = true; | ||
592 | }); | ||
593 | } | 429 | } |
594 | } | 430 | } |
595 | public override OMV.Vector3 RawVelocity | ||
596 | { | ||
597 | get { return _velocity; } | ||
598 | set { _velocity = value; } | ||
599 | } | ||
600 | // Directly setting velocity means this is what the user really wants now. | 431 | // Directly setting velocity means this is what the user really wants now. |
601 | public override OMV.Vector3 Velocity { | 432 | public override OMV.Vector3 Velocity { |
602 | get { return _velocity; } | 433 | get { return RawVelocity; } |
603 | set { | 434 | set { |
604 | _velocity = value; | 435 | RawVelocity = value; |
605 | // m_log.DebugFormat("{0}: set velocity = {1}", LogHeader, _velocity); | 436 | // m_log.DebugFormat("{0}: set velocity = {1}", LogHeader, RawVelocity); |
606 | PhysicsScene.TaintedObject("BSCharacter.setVelocity", delegate() | 437 | PhysicsScene.TaintedObject("BSCharacter.setVelocity", delegate() |
607 | { | 438 | { |
608 | _velocityMotor.Reset(); | 439 | if (m_moveActor != null) |
609 | _velocityMotor.SetCurrent(_velocity); | 440 | m_moveActor.SetVelocityAndTarget(RawVelocity, RawVelocity, true /* inTaintTime */); |
610 | _velocityMotor.SetTarget(_velocity); | ||
611 | _velocityMotor.Enabled = false; | ||
612 | 441 | ||
613 | DetailLog("{0},BSCharacter.setVelocity,taint,vel={1}", LocalID, _velocity); | 442 | DetailLog("{0},BSCharacter.setVelocity,taint,vel={1}", LocalID, RawVelocity); |
614 | ForceVelocity = _velocity; | 443 | ForceVelocity = RawVelocity; |
615 | }); | 444 | }); |
616 | } | 445 | } |
617 | } | 446 | } |
618 | public override OMV.Vector3 ForceVelocity { | 447 | public override OMV.Vector3 ForceVelocity { |
619 | get { return _velocity; } | 448 | get { return RawVelocity; } |
620 | set { | 449 | set { |
621 | PhysicsScene.AssertInTaintTime("BSCharacter.ForceVelocity"); | 450 | PhysicsScene.AssertInTaintTime("BSCharacter.ForceVelocity"); |
622 | 451 | ||
623 | _velocity = value; | 452 | RawVelocity = value; |
624 | PhysicsScene.PE.SetLinearVelocity(PhysBody, _velocity); | 453 | PhysicsScene.PE.SetLinearVelocity(PhysBody, RawVelocity); |
625 | PhysicsScene.PE.Activate(PhysBody, true); | 454 | PhysicsScene.PE.Activate(PhysBody, true); |
626 | } | 455 | } |
627 | } | 456 | } |
628 | public override OMV.Vector3 Torque { | 457 | public override OMV.Vector3 Torque { |
629 | get { return _torque; } | 458 | get { return RawTorque; } |
630 | set { _torque = value; | 459 | set { RawTorque = value; |
631 | } | 460 | } |
632 | } | 461 | } |
633 | public override float CollisionScore { | 462 | public override float CollisionScore { |
@@ -783,27 +612,6 @@ public sealed class BSCharacter : BSPhysObject | |||
783 | set { _PIDTau = value; } | 612 | set { _PIDTau = value; } |
784 | } | 613 | } |
785 | 614 | ||
786 | // Used for llSetHoverHeight and maybe vehicle height | ||
787 | // Hover Height will override MoveTo target's Z | ||
788 | public override bool PIDHoverActive { | ||
789 | set { _useHoverPID = value; } | ||
790 | } | ||
791 | public override float PIDHoverHeight { | ||
792 | set { _PIDHoverHeight = value; } | ||
793 | } | ||
794 | public override PIDHoverType PIDHoverType { | ||
795 | set { _PIDHoverType = value; } | ||
796 | } | ||
797 | public override float PIDHoverTau { | ||
798 | set { _PIDHoverTao = value; } | ||
799 | } | ||
800 | |||
801 | // For RotLookAt | ||
802 | public override OMV.Quaternion APIDTarget { set { return; } } | ||
803 | public override bool APIDActive { set { return; } } | ||
804 | public override float APIDStrength { set { return; } } | ||
805 | public override float APIDDamping { set { return; } } | ||
806 | |||
807 | public override void AddForce(OMV.Vector3 force, bool pushforce) | 615 | public override void AddForce(OMV.Vector3 force, bool pushforce) |
808 | { | 616 | { |
809 | // Since this force is being applied in only one step, make this a force per second. | 617 | // Since this force is being applied in only one step, make this a force per second. |
@@ -833,7 +641,7 @@ public sealed class BSCharacter : BSPhysObject | |||
833 | } | 641 | } |
834 | } | 642 | } |
835 | 643 | ||
836 | public override void AddAngularForce(OMV.Vector3 force, bool pushforce) { | 644 | public override void AddAngularForce(OMV.Vector3 force, bool pushforce, bool inTaintTime) { |
837 | } | 645 | } |
838 | public override void SetMomentum(OMV.Vector3 momentum) { | 646 | public override void SetMomentum(OMV.Vector3 momentum) { |
839 | } | 647 | } |
@@ -887,7 +695,7 @@ public sealed class BSCharacter : BSPhysObject | |||
887 | public override void UpdateProperties(EntityProperties entprop) | 695 | public override void UpdateProperties(EntityProperties entprop) |
888 | { | 696 | { |
889 | // Don't change position if standing on a stationary object. | 697 | // Don't change position if standing on a stationary object. |
890 | if (!_isStationaryStanding) | 698 | if (!IsStationary) |
891 | _position = entprop.Position; | 699 | _position = entprop.Position; |
892 | 700 | ||
893 | _orientation = entprop.Rotation; | 701 | _orientation = entprop.Rotation; |
@@ -896,8 +704,8 @@ public sealed class BSCharacter : BSPhysObject | |||
896 | // and will send agent updates to the clients if velocity changes by more than | 704 | // and will send agent updates to the clients if velocity changes by more than |
897 | // 0.001m/s. Bullet introduces a lot of jitter in the velocity which causes many | 705 | // 0.001m/s. Bullet introduces a lot of jitter in the velocity which causes many |
898 | // extra updates. | 706 | // extra updates. |
899 | if (!entprop.Velocity.ApproxEquals(_velocity, 0.1f)) | 707 | if (!entprop.Velocity.ApproxEquals(RawVelocity, 0.1f)) |
900 | _velocity = entprop.Velocity; | 708 | RawVelocity = entprop.Velocity; |
901 | 709 | ||
902 | _acceleration = entprop.Acceleration; | 710 | _acceleration = entprop.Acceleration; |
903 | _rotationalVelocity = entprop.RotationalVelocity; | 711 | _rotationalVelocity = entprop.RotationalVelocity; |
@@ -920,7 +728,7 @@ public sealed class BSCharacter : BSPhysObject | |||
920 | // base.RequestPhysicsterseUpdate(); | 728 | // base.RequestPhysicsterseUpdate(); |
921 | 729 | ||
922 | DetailLog("{0},BSCharacter.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}", | 730 | DetailLog("{0},BSCharacter.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}", |
923 | LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity); | 731 | LocalID, _position, _orientation, RawVelocity, _acceleration, _rotationalVelocity); |
924 | } | 732 | } |
925 | } | 733 | } |
926 | } | 734 | } |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs index 98ea833..644bc7e 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs | |||
@@ -43,7 +43,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
43 | * VariableName: used by the simulator and performs taint operations, etc | 43 | * VariableName: used by the simulator and performs taint operations, etc |
44 | * RawVariableName: direct reference to the BulletSim storage for the variable value | 44 | * RawVariableName: direct reference to the BulletSim storage for the variable value |
45 | * ForceVariableName: direct reference (store and fetch) to the value in the physics engine. | 45 | * ForceVariableName: direct reference (store and fetch) to the value in the physics engine. |
46 | * The last two (and certainly the last one) should be referenced only in taint-time. | 46 | * The last one should only be referenced in taint-time. |
47 | */ | 47 | */ |
48 | 48 | ||
49 | /* | 49 | /* |
@@ -84,6 +84,7 @@ public abstract class BSPhysObject : PhysicsActor | |||
84 | // Initialize variables kept in base. | 84 | // Initialize variables kept in base. |
85 | GravModifier = 1.0f; | 85 | GravModifier = 1.0f; |
86 | Gravity = new OMV.Vector3(0f, 0f, BSParam.Gravity); | 86 | Gravity = new OMV.Vector3(0f, 0f, BSParam.Gravity); |
87 | HoverActive = false; | ||
87 | 88 | ||
88 | // We don't have any physical representation yet. | 89 | // We don't have any physical representation yet. |
89 | PhysBody = new BulletBody(localID); | 90 | PhysBody = new BulletBody(localID); |
@@ -110,11 +111,10 @@ public abstract class BSPhysObject : PhysicsActor | |||
110 | // Tell the object to clean up. | 111 | // Tell the object to clean up. |
111 | public virtual void Destroy() | 112 | public virtual void Destroy() |
112 | { | 113 | { |
113 | UnRegisterAllPreStepActions(); | 114 | PhysicalActors.Enable(false); |
114 | UnRegisterAllPostStepActions(); | ||
115 | PhysicsScene.TaintedObject("BSPhysObject.Destroy", delegate() | 115 | PhysicsScene.TaintedObject("BSPhysObject.Destroy", delegate() |
116 | { | 116 | { |
117 | PhysicalActors.Release(); | 117 | PhysicalActors.Dispose(); |
118 | }); | 118 | }); |
119 | } | 119 | } |
120 | 120 | ||
@@ -203,15 +203,48 @@ public abstract class BSPhysObject : PhysicsActor | |||
203 | public abstract OMV.Quaternion RawOrientation { get; set; } | 203 | public abstract OMV.Quaternion RawOrientation { get; set; } |
204 | public abstract OMV.Quaternion ForceOrientation { get; set; } | 204 | public abstract OMV.Quaternion ForceOrientation { get; set; } |
205 | 205 | ||
206 | public abstract OMV.Vector3 RawVelocity { get; set; } | 206 | public OMV.Vector3 RawVelocity { get; set; } |
207 | public abstract OMV.Vector3 ForceVelocity { get; set; } | 207 | public abstract OMV.Vector3 ForceVelocity { get; set; } |
208 | 208 | ||
209 | public OMV.Vector3 RawForce { get; set; } | ||
210 | public OMV.Vector3 RawTorque { get; set; } | ||
211 | public override void AddAngularForce(OMV.Vector3 force, bool pushforce) | ||
212 | { | ||
213 | AddAngularForce(force, pushforce, false); | ||
214 | } | ||
215 | public abstract void AddAngularForce(OMV.Vector3 force, bool pushforce, bool inTaintTime); | ||
216 | |||
209 | public abstract OMV.Vector3 ForceRotationalVelocity { get; set; } | 217 | public abstract OMV.Vector3 ForceRotationalVelocity { get; set; } |
210 | 218 | ||
211 | public abstract float ForceBuoyancy { get; set; } | 219 | public abstract float ForceBuoyancy { get; set; } |
212 | 220 | ||
213 | public virtual bool ForceBodyShapeRebuild(bool inTaintTime) { return false; } | 221 | public virtual bool ForceBodyShapeRebuild(bool inTaintTime) { return false; } |
214 | 222 | ||
223 | public override bool PIDActive { set { MoveToTargetActive = value; } } | ||
224 | public override OMV.Vector3 PIDTarget { set { MoveToTargetTarget = value; } } | ||
225 | public override float PIDTau { set { MoveToTargetTau = value; } } | ||
226 | |||
227 | public bool MoveToTargetActive { get; set; } | ||
228 | public OMV.Vector3 MoveToTargetTarget { get; set; } | ||
229 | public float MoveToTargetTau { get; set; } | ||
230 | |||
231 | // Used for llSetHoverHeight and maybe vehicle height. Hover Height will override MoveTo target's Z | ||
232 | public override bool PIDHoverActive { set { HoverActive = value; } } | ||
233 | public override float PIDHoverHeight { set { HoverHeight = value; } } | ||
234 | public override PIDHoverType PIDHoverType { set { HoverType = value; } } | ||
235 | public override float PIDHoverTau { set { HoverTau = value; } } | ||
236 | |||
237 | public bool HoverActive { get; set; } | ||
238 | public float HoverHeight { get; set; } | ||
239 | public PIDHoverType HoverType { get; set; } | ||
240 | public float HoverTau { get; set; } | ||
241 | |||
242 | // For RotLookAt | ||
243 | public override OMV.Quaternion APIDTarget { set { return; } } | ||
244 | public override bool APIDActive { set { return; } } | ||
245 | public override float APIDStrength { set { return; } } | ||
246 | public override float APIDDamping { set { return; } } | ||
247 | |||
215 | // The current velocity forward | 248 | // The current velocity forward |
216 | public virtual float ForwardSpeed | 249 | public virtual float ForwardSpeed |
217 | { | 250 | { |
@@ -237,7 +270,44 @@ public abstract class BSPhysObject : PhysicsActor | |||
237 | 270 | ||
238 | public OMV.Vector3 LockedAxis { get; set; } // zero means locked. one means free. | 271 | public OMV.Vector3 LockedAxis { get; set; } // zero means locked. one means free. |
239 | public readonly OMV.Vector3 LockedAxisFree = new OMV.Vector3(1f, 1f, 1f); // All axis are free | 272 | public readonly OMV.Vector3 LockedAxisFree = new OMV.Vector3(1f, 1f, 1f); // All axis are free |
240 | public readonly String LockedAxisActorName = "BSPrim.LockedAxis"; | 273 | |
274 | // Enable physical actions. Bullet will keep sleeping non-moving physical objects so | ||
275 | // they need waking up when parameters are changed. | ||
276 | // Called in taint-time!! | ||
277 | public void ActivateIfPhysical(bool forceIt) | ||
278 | { | ||
279 | if (IsPhysical && PhysBody.HasPhysicalBody) | ||
280 | PhysicsScene.PE.Activate(PhysBody, forceIt); | ||
281 | } | ||
282 | |||
283 | // 'actors' act on the physical object to change or constrain its motion. These can range from | ||
284 | // hovering to complex vehicle motion. | ||
285 | public delegate BSActor CreateActor(); | ||
286 | public void CreateRemoveActor(bool createRemove, string actorName, bool inTaintTime, CreateActor creator) | ||
287 | { | ||
288 | if (createRemove) | ||
289 | { | ||
290 | PhysicsScene.TaintedObject(inTaintTime, "BSPrim.CreateRemoveActor:" + actorName, delegate() | ||
291 | { | ||
292 | if (!PhysicalActors.HasActor(actorName)) | ||
293 | { | ||
294 | DetailLog("{0},BSPrim.CreateRemoveActor,taint,registerActor,a={1}", LocalID, actorName); | ||
295 | PhysicalActors.Add(actorName, creator()); | ||
296 | } | ||
297 | }); | ||
298 | } | ||
299 | else | ||
300 | { | ||
301 | PhysicsScene.TaintedObject(inTaintTime, "BSPrim.CreateRemoveActor:" + actorName, delegate() | ||
302 | { | ||
303 | if (PhysicalActors.HasActor(actorName)) | ||
304 | { | ||
305 | DetailLog("{0},BSPrim.CreateRemoveActor,taint,unregisterActor,a={1}", LocalID, actorName); | ||
306 | PhysicalActors.RemoveAndRelease(actorName); | ||
307 | } | ||
308 | }); | ||
309 | } | ||
310 | } | ||
241 | 311 | ||
242 | #region Collisions | 312 | #region Collisions |
243 | 313 | ||
@@ -255,7 +325,9 @@ public abstract class BSPhysObject : PhysicsActor | |||
255 | protected CollisionFlags CurrentCollisionFlags { get; set; } | 325 | protected CollisionFlags CurrentCollisionFlags { get; set; } |
256 | // On a collision, check the collider and remember if the last collider was moving | 326 | // On a collision, check the collider and remember if the last collider was moving |
257 | // Used to modify the standing of avatars (avatars on stationary things stand still) | 327 | // Used to modify the standing of avatars (avatars on stationary things stand still) |
258 | protected bool ColliderIsMoving; | 328 | public bool ColliderIsMoving; |
329 | // Used by BSCharacter to manage standing (and not slipping) | ||
330 | public bool IsStationary; | ||
259 | 331 | ||
260 | // Count of collisions for this object | 332 | // Count of collisions for this object |
261 | protected long CollisionAccumulation { get; set; } | 333 | protected long CollisionAccumulation { get; set; } |
@@ -293,7 +365,7 @@ public abstract class BSPhysObject : PhysicsActor | |||
293 | protected CollisionEventUpdate CollisionCollection; | 365 | protected CollisionEventUpdate CollisionCollection; |
294 | // Remember collisions from last tick for fancy collision based actions | 366 | // Remember collisions from last tick for fancy collision based actions |
295 | // (like a BSCharacter walking up stairs). | 367 | // (like a BSCharacter walking up stairs). |
296 | protected CollisionEventUpdate CollisionsLastTick; | 368 | public CollisionEventUpdate CollisionsLastTick; |
297 | 369 | ||
298 | // The simulation step is telling this object about a collision. | 370 | // The simulation step is telling this object about a collision. |
299 | // Return 'true' if a collision was processed and should be sent up. | 371 | // Return 'true' if a collision was processed and should be sent up. |
@@ -424,104 +496,6 @@ public abstract class BSPhysObject : PhysicsActor | |||
424 | 496 | ||
425 | public BSActorCollection PhysicalActors; | 497 | public BSActorCollection PhysicalActors; |
426 | 498 | ||
427 | // There are some actions that must be performed for a physical object before each simulation step. | ||
428 | // These actions are optional so, rather than scanning all the physical objects and asking them | ||
429 | // if they have anything to do, a physical object registers for an event call before the step is performed. | ||
430 | // This bookkeeping makes it easy to add, remove and clean up after all these registrations. | ||
431 | private Dictionary<string, BSScene.PreStepAction> RegisteredPrestepActions = new Dictionary<string, BSScene.PreStepAction>(); | ||
432 | private Dictionary<string, BSScene.PostStepAction> RegisteredPoststepActions = new Dictionary<string, BSScene.PostStepAction>(); | ||
433 | protected void RegisterPreStepAction(string op, uint id, BSScene.PreStepAction actn) | ||
434 | { | ||
435 | string identifier = op + "-" + id.ToString(); | ||
436 | |||
437 | lock (RegisteredPrestepActions) | ||
438 | { | ||
439 | // Clean out any existing action | ||
440 | UnRegisterPreStepAction(op, id); | ||
441 | RegisteredPrestepActions[identifier] = actn; | ||
442 | PhysicsScene.BeforeStep += actn; | ||
443 | } | ||
444 | DetailLog("{0},BSPhysObject.RegisterPreStepAction,id={1}", LocalID, identifier); | ||
445 | } | ||
446 | |||
447 | // Unregister a pre step action. Safe to call if the action has not been registered. | ||
448 | // Returns 'true' if an action was actually removed | ||
449 | protected bool UnRegisterPreStepAction(string op, uint id) | ||
450 | { | ||
451 | string identifier = op + "-" + id.ToString(); | ||
452 | bool removed = false; | ||
453 | lock (RegisteredPrestepActions) | ||
454 | { | ||
455 | if (RegisteredPrestepActions.ContainsKey(identifier)) | ||
456 | { | ||
457 | PhysicsScene.BeforeStep -= RegisteredPrestepActions[identifier]; | ||
458 | RegisteredPrestepActions.Remove(identifier); | ||
459 | removed = true; | ||
460 | } | ||
461 | } | ||
462 | DetailLog("{0},BSPhysObject.UnRegisterPreStepAction,id={1},removed={2}", LocalID, identifier, removed); | ||
463 | return removed; | ||
464 | } | ||
465 | |||
466 | protected void UnRegisterAllPreStepActions() | ||
467 | { | ||
468 | lock (RegisteredPrestepActions) | ||
469 | { | ||
470 | foreach (KeyValuePair<string, BSScene.PreStepAction> kvp in RegisteredPrestepActions) | ||
471 | { | ||
472 | PhysicsScene.BeforeStep -= kvp.Value; | ||
473 | } | ||
474 | RegisteredPrestepActions.Clear(); | ||
475 | } | ||
476 | DetailLog("{0},BSPhysObject.UnRegisterAllPreStepActions,", LocalID); | ||
477 | } | ||
478 | |||
479 | protected void RegisterPostStepAction(string op, uint id, BSScene.PostStepAction actn) | ||
480 | { | ||
481 | string identifier = op + "-" + id.ToString(); | ||
482 | |||
483 | lock (RegisteredPoststepActions) | ||
484 | { | ||
485 | // Clean out any existing action | ||
486 | UnRegisterPostStepAction(op, id); | ||
487 | RegisteredPoststepActions[identifier] = actn; | ||
488 | PhysicsScene.AfterStep += actn; | ||
489 | } | ||
490 | DetailLog("{0},BSPhysObject.RegisterPostStepAction,id={1}", LocalID, identifier); | ||
491 | } | ||
492 | |||
493 | // Unregister a pre step action. Safe to call if the action has not been registered. | ||
494 | // Returns 'true' if an action was actually removed. | ||
495 | protected bool UnRegisterPostStepAction(string op, uint id) | ||
496 | { | ||
497 | string identifier = op + "-" + id.ToString(); | ||
498 | bool removed = false; | ||
499 | lock (RegisteredPoststepActions) | ||
500 | { | ||
501 | if (RegisteredPoststepActions.ContainsKey(identifier)) | ||
502 | { | ||
503 | PhysicsScene.AfterStep -= RegisteredPoststepActions[identifier]; | ||
504 | RegisteredPoststepActions.Remove(identifier); | ||
505 | removed = true; | ||
506 | } | ||
507 | } | ||
508 | DetailLog("{0},BSPhysObject.UnRegisterPostStepAction,id={1},removed={2}", LocalID, identifier, removed); | ||
509 | return removed; | ||
510 | } | ||
511 | |||
512 | protected void UnRegisterAllPostStepActions() | ||
513 | { | ||
514 | lock (RegisteredPoststepActions) | ||
515 | { | ||
516 | foreach (KeyValuePair<string, BSScene.PostStepAction> kvp in RegisteredPoststepActions) | ||
517 | { | ||
518 | PhysicsScene.AfterStep -= kvp.Value; | ||
519 | } | ||
520 | RegisteredPoststepActions.Clear(); | ||
521 | } | ||
522 | DetailLog("{0},BSPhysObject.UnRegisterAllPostStepActions,", LocalID); | ||
523 | } | ||
524 | |||
525 | // When an update to the physical properties happens, this event is fired to let | 499 | // When an update to the physical properties happens, this event is fired to let |
526 | // different actors to modify the update before it is passed around | 500 | // different actors to modify the update before it is passed around |
527 | public delegate void PreUpdatePropertyAction(ref EntityProperties entprop); | 501 | public delegate void PreUpdatePropertyAction(ref EntityProperties entprop); |
@@ -533,46 +507,6 @@ public abstract class BSPhysObject : PhysicsActor | |||
533 | actions(ref entprop); | 507 | actions(ref entprop); |
534 | } | 508 | } |
535 | 509 | ||
536 | private Dictionary<string, PreUpdatePropertyAction> RegisteredPreUpdatePropertyActions = new Dictionary<string, PreUpdatePropertyAction>(); | ||
537 | public void RegisterPreUpdatePropertyAction(string identifier, PreUpdatePropertyAction actn) | ||
538 | { | ||
539 | lock (RegisteredPreUpdatePropertyActions) | ||
540 | { | ||
541 | // Clean out any existing action | ||
542 | UnRegisterPreUpdatePropertyAction(identifier); | ||
543 | RegisteredPreUpdatePropertyActions[identifier] = actn; | ||
544 | OnPreUpdateProperty += actn; | ||
545 | } | ||
546 | DetailLog("{0},BSPhysObject.RegisterPreUpdatePropertyAction,id={1}", LocalID, identifier); | ||
547 | } | ||
548 | public bool UnRegisterPreUpdatePropertyAction(string identifier) | ||
549 | { | ||
550 | bool removed = false; | ||
551 | lock (RegisteredPreUpdatePropertyActions) | ||
552 | { | ||
553 | if (RegisteredPreUpdatePropertyActions.ContainsKey(identifier)) | ||
554 | { | ||
555 | OnPreUpdateProperty -= RegisteredPreUpdatePropertyActions[identifier]; | ||
556 | RegisteredPreUpdatePropertyActions.Remove(identifier); | ||
557 | removed = true; | ||
558 | } | ||
559 | } | ||
560 | DetailLog("{0},BSPhysObject.UnRegisterPreUpdatePropertyAction,id={1},removed={2}", LocalID, identifier, removed); | ||
561 | return removed; | ||
562 | } | ||
563 | public void UnRegisterAllPreUpdatePropertyActions() | ||
564 | { | ||
565 | lock (RegisteredPreUpdatePropertyActions) | ||
566 | { | ||
567 | foreach (KeyValuePair<string, PreUpdatePropertyAction> kvp in RegisteredPreUpdatePropertyActions) | ||
568 | { | ||
569 | OnPreUpdateProperty -= kvp.Value; | ||
570 | } | ||
571 | RegisteredPreUpdatePropertyActions.Clear(); | ||
572 | } | ||
573 | DetailLog("{0},BSPhysObject.UnRegisterAllPreUpdatePropertyAction,", LocalID); | ||
574 | } | ||
575 | |||
576 | #endregion // Per Simulation Step actions | 510 | #endregion // Per Simulation Step actions |
577 | 511 | ||
578 | // High performance detailed logging routine used by the physical objects. | 512 | // High performance detailed logging routine used by the physical objects. |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index e56276a..71fea59 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | |||
@@ -55,9 +55,6 @@ public class BSPrim : BSPhysObject | |||
55 | private OMV.Vector3 _position; | 55 | private OMV.Vector3 _position; |
56 | 56 | ||
57 | private float _mass; // the mass of this object | 57 | private float _mass; // the mass of this object |
58 | private OMV.Vector3 _force; | ||
59 | private OMV.Vector3 _velocity; | ||
60 | private OMV.Vector3 _torque; | ||
61 | private OMV.Vector3 _acceleration; | 58 | private OMV.Vector3 _acceleration; |
62 | private OMV.Quaternion _orientation; | 59 | private OMV.Quaternion _orientation; |
63 | private int _physicsActorType; | 60 | private int _physicsActorType; |
@@ -73,16 +70,13 @@ public class BSPrim : BSPhysObject | |||
73 | private int CrossingFailures { get; set; } | 70 | private int CrossingFailures { get; set; } |
74 | 71 | ||
75 | public BSDynamics VehicleActor; | 72 | public BSDynamics VehicleActor; |
76 | public string VehicleActorName = "BasicVehicle"; | 73 | public const string VehicleActorName = "BasicVehicle"; |
77 | 74 | ||
78 | private BSVMotor _targetMotor; | 75 | public const string HoverActorName = "HoverActor"; |
79 | private OMV.Vector3 _PIDTarget; | 76 | public const String LockedAxisActorName = "BSPrim.LockedAxis"; |
80 | private float _PIDTau; | 77 | public const string MoveToTargetActorName = "MoveToTargetActor"; |
81 | 78 | public const string SetForceActorName = "SetForceActor"; | |
82 | private BSFMotor _hoverMotor; | 79 | public const string SetTorqueActorName = "SetTorqueActor"; |
83 | private float _PIDHoverHeight; | ||
84 | private PIDHoverType _PIDHoverType; | ||
85 | private float _PIDHoverTau; | ||
86 | 80 | ||
87 | public BSPrim(uint localID, String primName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 size, | 81 | public BSPrim(uint localID, String primName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 size, |
88 | OMV.Quaternion rotation, PrimitiveBaseShape pbs, bool pisPhysical) | 82 | OMV.Quaternion rotation, PrimitiveBaseShape pbs, bool pisPhysical) |
@@ -95,7 +89,7 @@ public class BSPrim : BSPhysObject | |||
95 | Scale = size; // prims are the size the user wants them to be (different for BSCharactes). | 89 | Scale = size; // prims are the size the user wants them to be (different for BSCharactes). |
96 | _orientation = rotation; | 90 | _orientation = rotation; |
97 | _buoyancy = 0f; | 91 | _buoyancy = 0f; |
98 | _velocity = OMV.Vector3.Zero; | 92 | RawVelocity = OMV.Vector3.Zero; |
99 | _rotationalVelocity = OMV.Vector3.Zero; | 93 | _rotationalVelocity = OMV.Vector3.Zero; |
100 | BaseShape = pbs; | 94 | BaseShape = pbs; |
101 | _isPhysical = pisPhysical; | 95 | _isPhysical = pisPhysical; |
@@ -233,7 +227,7 @@ public class BSPrim : BSPhysObject | |||
233 | // Called at taint time! | 227 | // Called at taint time! |
234 | public override void ZeroMotion(bool inTaintTime) | 228 | public override void ZeroMotion(bool inTaintTime) |
235 | { | 229 | { |
236 | _velocity = OMV.Vector3.Zero; | 230 | RawVelocity = OMV.Vector3.Zero; |
237 | _acceleration = OMV.Vector3.Zero; | 231 | _acceleration = OMV.Vector3.Zero; |
238 | _rotationalVelocity = OMV.Vector3.Zero; | 232 | _rotationalVelocity = OMV.Vector3.Zero; |
239 | 233 | ||
@@ -270,19 +264,17 @@ public class BSPrim : BSPhysObject | |||
270 | if (axis.Z != 1) locking.Z = 0f; | 264 | if (axis.Z != 1) locking.Z = 0f; |
271 | LockedAxis = locking; | 265 | LockedAxis = locking; |
272 | 266 | ||
273 | if (LockedAxis != LockedAxisFree) | 267 | CreateRemoveActor(LockedAxis != LockedAxisFree /* creatActor */, LockedAxisActorName, false /* inTaintTime */, delegate() |
274 | { | 268 | { |
275 | PhysicsScene.TaintedObject("BSPrim.LockAngularMotion", delegate() | 269 | return new BSActorLockAxis(PhysicsScene, this, LockedAxisActorName); |
276 | { | 270 | }); |
277 | // If there is not already an axis locker, make one | 271 | |
278 | if (!PhysicalActors.HasActor(LockedAxisActorName)) | 272 | // Update parameters so the new actor's Refresh() action is called at the right time. |
279 | { | 273 | PhysicsScene.TaintedObject("BSPrim.LockAngularMotion", delegate() |
280 | DetailLog("{0},BSPrim.LockAngularMotion,taint,registeringLockAxisActor", LocalID); | 274 | { |
281 | PhysicalActors.Add(LockedAxisActorName, new BSActorLockAxis(PhysicsScene, this, LockedAxisActorName)); | 275 | UpdatePhysicalParameters(); |
282 | } | 276 | }); |
283 | UpdatePhysicalParameters(); | 277 | |
284 | }); | ||
285 | } | ||
286 | return; | 278 | return; |
287 | } | 279 | } |
288 | 280 | ||
@@ -407,9 +399,9 @@ public class BSPrim : BSPhysObject | |||
407 | ZeroMotion(inTaintTime); | 399 | ZeroMotion(inTaintTime); |
408 | ret = true; | 400 | ret = true; |
409 | } | 401 | } |
410 | if (_velocity.LengthSquared() > BSParam.MaxLinearVelocity) | 402 | if (RawVelocity.LengthSquared() > BSParam.MaxLinearVelocity) |
411 | { | 403 | { |
412 | _velocity = Util.ClampV(_velocity, BSParam.MaxLinearVelocity); | 404 | RawVelocity = Util.ClampV(RawVelocity, BSParam.MaxLinearVelocity); |
413 | ret = true; | 405 | ret = true; |
414 | } | 406 | } |
415 | if (_rotationalVelocity.LengthSquared() > BSParam.MaxAngularVelocitySquared) | 407 | if (_rotationalVelocity.LengthSquared() > BSParam.MaxAngularVelocitySquared) |
@@ -506,35 +498,13 @@ public class BSPrim : BSPhysObject | |||
506 | } | 498 | } |
507 | 499 | ||
508 | public override OMV.Vector3 Force { | 500 | public override OMV.Vector3 Force { |
509 | get { return _force; } | 501 | get { return RawForce; } |
510 | set { | 502 | set { |
511 | _force = value; | 503 | RawForce = value; |
512 | if (_force != OMV.Vector3.Zero) | 504 | CreateRemoveActor(RawForce == OMV.Vector3.Zero, SetForceActorName, false /* inTaintTime */, delegate() |
513 | { | ||
514 | // If the force is non-zero, it must be reapplied each tick because | ||
515 | // Bullet clears the forces applied last frame. | ||
516 | RegisterPreStepAction("BSPrim.setForce", LocalID, | ||
517 | delegate(float timeStep) | ||
518 | { | ||
519 | if (!IsPhysicallyActive || _force == OMV.Vector3.Zero) | ||
520 | { | ||
521 | UnRegisterPreStepAction("BSPrim.setForce", LocalID); | ||
522 | return; | ||
523 | } | ||
524 | |||
525 | DetailLog("{0},BSPrim.setForce,preStep,force={1}", LocalID, _force); | ||
526 | if (PhysBody.HasPhysicalBody) | ||
527 | { | ||
528 | PhysicsScene.PE.ApplyCentralForce(PhysBody, _force); | ||
529 | ActivateIfPhysical(false); | ||
530 | } | ||
531 | } | ||
532 | ); | ||
533 | } | ||
534 | else | ||
535 | { | 505 | { |
536 | UnRegisterPreStepAction("BSPrim.setForce", LocalID); | 506 | return new BSActorSetForce(PhysicsScene, this, SetForceActorName); |
537 | } | 507 | }); |
538 | } | 508 | } |
539 | } | 509 | } |
540 | 510 | ||
@@ -670,62 +640,39 @@ public class BSPrim : BSPhysObject | |||
670 | } | 640 | } |
671 | } | 641 | } |
672 | } | 642 | } |
673 | public override OMV.Vector3 RawVelocity | ||
674 | { | ||
675 | get { return _velocity; } | ||
676 | set { _velocity = value; } | ||
677 | } | ||
678 | public override OMV.Vector3 Velocity { | 643 | public override OMV.Vector3 Velocity { |
679 | get { return _velocity; } | 644 | get { return RawVelocity; } |
680 | set { | 645 | set { |
681 | _velocity = value; | 646 | RawVelocity = value; |
682 | PhysicsScene.TaintedObject("BSPrim.setVelocity", delegate() | 647 | PhysicsScene.TaintedObject("BSPrim.setVelocity", delegate() |
683 | { | 648 | { |
684 | // DetailLog("{0},BSPrim.SetVelocity,taint,vel={1}", LocalID, _velocity); | 649 | // DetailLog("{0},BSPrim.SetVelocity,taint,vel={1}", LocalID, RawVelocity); |
685 | ForceVelocity = _velocity; | 650 | ForceVelocity = RawVelocity; |
686 | }); | 651 | }); |
687 | } | 652 | } |
688 | } | 653 | } |
689 | public override OMV.Vector3 ForceVelocity { | 654 | public override OMV.Vector3 ForceVelocity { |
690 | get { return _velocity; } | 655 | get { return RawVelocity; } |
691 | set { | 656 | set { |
692 | PhysicsScene.AssertInTaintTime("BSPrim.ForceVelocity"); | 657 | PhysicsScene.AssertInTaintTime("BSPrim.ForceVelocity"); |
693 | 658 | ||
694 | _velocity = Util.ClampV(value, BSParam.MaxLinearVelocity); | 659 | RawVelocity = Util.ClampV(value, BSParam.MaxLinearVelocity); |
695 | if (PhysBody.HasPhysicalBody) | 660 | if (PhysBody.HasPhysicalBody) |
696 | { | 661 | { |
697 | DetailLog("{0},BSPrim.ForceVelocity,taint,vel={1}", LocalID, _velocity); | 662 | DetailLog("{0},BSPrim.ForceVelocity,taint,vel={1}", LocalID, RawVelocity); |
698 | PhysicsScene.PE.SetLinearVelocity(PhysBody, _velocity); | 663 | PhysicsScene.PE.SetLinearVelocity(PhysBody, RawVelocity); |
699 | ActivateIfPhysical(false); | 664 | ActivateIfPhysical(false); |
700 | } | 665 | } |
701 | } | 666 | } |
702 | } | 667 | } |
703 | public override OMV.Vector3 Torque { | 668 | public override OMV.Vector3 Torque { |
704 | get { return _torque; } | 669 | get { return RawTorque; } |
705 | set { | 670 | set { |
706 | _torque = value; | 671 | RawTorque = value; |
707 | if (_torque != OMV.Vector3.Zero) | 672 | CreateRemoveActor(RawTorque == OMV.Vector3.Zero, SetTorqueActorName, false /* inTaintTime */, delegate() |
708 | { | 673 | { |
709 | // If the torque is non-zero, it must be reapplied each tick because | 674 | return new BSActorSetTorque(PhysicsScene, this, SetTorqueActorName); |
710 | // Bullet clears the forces applied last frame. | 675 | }); |
711 | RegisterPreStepAction("BSPrim.setTorque", LocalID, | ||
712 | delegate(float timeStep) | ||
713 | { | ||
714 | if (!IsPhysicallyActive || _torque == OMV.Vector3.Zero) | ||
715 | { | ||
716 | UnRegisterPreStepAction("BSPrim.setTorque", LocalID); | ||
717 | return; | ||
718 | } | ||
719 | |||
720 | if (PhysBody.HasPhysicalBody) | ||
721 | AddAngularForce(_torque, false, true); | ||
722 | } | ||
723 | ); | ||
724 | } | ||
725 | else | ||
726 | { | ||
727 | UnRegisterPreStepAction("BSPrim.setTorque", LocalID); | ||
728 | } | ||
729 | // DetailLog("{0},BSPrim.SetTorque,call,torque={1}", LocalID, _torque); | 676 | // DetailLog("{0},BSPrim.SetTorque,call,torque={1}", LocalID, _torque); |
730 | } | 677 | } |
731 | } | 678 | } |
@@ -909,7 +856,7 @@ public class BSPrim : BSPhysObject | |||
909 | 856 | ||
910 | // For good measure, make sure the transform is set through to the motion state | 857 | // For good measure, make sure the transform is set through to the motion state |
911 | ForcePosition = _position; | 858 | ForcePosition = _position; |
912 | ForceVelocity = _velocity; | 859 | ForceVelocity = RawVelocity; |
913 | ForceRotationalVelocity = _rotationalVelocity; | 860 | ForceRotationalVelocity = _rotationalVelocity; |
914 | 861 | ||
915 | // A dynamic object has mass | 862 | // A dynamic object has mass |
@@ -966,15 +913,6 @@ public class BSPrim : BSPhysObject | |||
966 | } | 913 | } |
967 | } | 914 | } |
968 | 915 | ||
969 | // Enable physical actions. Bullet will keep sleeping non-moving physical objects so | ||
970 | // they need waking up when parameters are changed. | ||
971 | // Called in taint-time!! | ||
972 | private void ActivateIfPhysical(bool forceIt) | ||
973 | { | ||
974 | if (IsPhysical && PhysBody.HasPhysicalBody) | ||
975 | PhysicsScene.PE.Activate(PhysBody, forceIt); | ||
976 | } | ||
977 | |||
978 | // Turn on or off the flag controlling whether collision events are returned to the simulator. | 916 | // Turn on or off the flag controlling whether collision events are returned to the simulator. |
979 | private void EnableCollisions(bool wantsCollisionEvents) | 917 | private void EnableCollisions(bool wantsCollisionEvents) |
980 | { | 918 | { |
@@ -1096,78 +1034,13 @@ public class BSPrim : BSPhysObject | |||
1096 | } | 1034 | } |
1097 | } | 1035 | } |
1098 | 1036 | ||
1099 | // Used for MoveTo | ||
1100 | public override OMV.Vector3 PIDTarget { | ||
1101 | set | ||
1102 | { | ||
1103 | // TODO: add a sanity check -- don't move more than a region or something like that. | ||
1104 | _PIDTarget = value; | ||
1105 | } | ||
1106 | } | ||
1107 | public override float PIDTau { | ||
1108 | set { _PIDTau = value; } | ||
1109 | } | ||
1110 | public override bool PIDActive { | 1037 | public override bool PIDActive { |
1111 | set { | 1038 | set { |
1112 | if (value) | 1039 | base.MoveToTargetActive = value; |
1113 | { | 1040 | CreateRemoveActor(MoveToTargetActive, MoveToTargetActorName, false /* inTaintTime */, delegate() |
1114 | // We're taking over after this. | ||
1115 | ZeroMotion(true); | ||
1116 | |||
1117 | _targetMotor = new BSVMotor("BSPrim.PIDTarget", | ||
1118 | _PIDTau, // timeScale | ||
1119 | BSMotor.Infinite, // decay time scale | ||
1120 | BSMotor.InfiniteVector, // friction timescale | ||
1121 | 1f // efficiency | ||
1122 | ); | ||
1123 | _targetMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG so motor will output detail log messages. | ||
1124 | _targetMotor.SetTarget(_PIDTarget); | ||
1125 | _targetMotor.SetCurrent(RawPosition); | ||
1126 | /* | ||
1127 | _targetMotor = new BSPIDVMotor("BSPrim.PIDTarget"); | ||
1128 | _targetMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG so motor will output detail log messages. | ||
1129 | |||
1130 | _targetMotor.SetTarget(_PIDTarget); | ||
1131 | _targetMotor.SetCurrent(RawPosition); | ||
1132 | _targetMotor.TimeScale = _PIDTau; | ||
1133 | _targetMotor.Efficiency = 1f; | ||
1134 | */ | ||
1135 | |||
1136 | RegisterPreStepAction("BSPrim.PIDTarget", LocalID, delegate(float timeStep) | ||
1137 | { | ||
1138 | if (!IsPhysicallyActive) | ||
1139 | { | ||
1140 | UnRegisterPreStepAction("BSPrim.PIDTarget", LocalID); | ||
1141 | return; | ||
1142 | } | ||
1143 | |||
1144 | OMV.Vector3 origPosition = RawPosition; // DEBUG DEBUG (for printout below) | ||
1145 | |||
1146 | // 'movePosition' is where we'd like the prim to be at this moment. | ||
1147 | OMV.Vector3 movePosition = RawPosition + _targetMotor.Step(timeStep); | ||
1148 | |||
1149 | // If we are very close to our target, turn off the movement motor. | ||
1150 | if (_targetMotor.ErrorIsZero()) | ||
1151 | { | ||
1152 | DetailLog("{0},BSPrim.PIDTarget,zeroMovement,movePos={1},pos={2},mass={3}", | ||
1153 | LocalID, movePosition, RawPosition, Mass); | ||
1154 | ForcePosition = _targetMotor.TargetValue; | ||
1155 | _targetMotor.Enabled = false; | ||
1156 | } | ||
1157 | else | ||
1158 | { | ||
1159 | _position = movePosition; | ||
1160 | PositionSanityCheck(true /* intaintTime */); | ||
1161 | ForcePosition = _position; | ||
1162 | } | ||
1163 | DetailLog("{0},BSPrim.PIDTarget,move,fromPos={1},movePos={2}", LocalID, origPosition, movePosition); | ||
1164 | }); | ||
1165 | } | ||
1166 | else | ||
1167 | { | 1041 | { |
1168 | // Stop any targetting | 1042 | return new BSActorMoveToTarget(PhysicsScene, this, MoveToTargetActorName); |
1169 | UnRegisterPreStepAction("BSPrim.PIDTarget", LocalID); | 1043 | }); |
1170 | } | ||
1171 | } | 1044 | } |
1172 | } | 1045 | } |
1173 | 1046 | ||
@@ -1175,88 +1048,14 @@ public class BSPrim : BSPhysObject | |||
1175 | // Hover Height will override MoveTo target's Z | 1048 | // Hover Height will override MoveTo target's Z |
1176 | public override bool PIDHoverActive { | 1049 | public override bool PIDHoverActive { |
1177 | set { | 1050 | set { |
1178 | if (value) | 1051 | base.HoverActive = value; |
1179 | { | 1052 | CreateRemoveActor(HoverActive /* creatActor */, HoverActorName, false /* inTaintTime */, delegate() |
1180 | // Turning the target on | ||
1181 | _hoverMotor = new BSFMotor("BSPrim.Hover", | ||
1182 | _PIDHoverTau, // timeScale | ||
1183 | BSMotor.Infinite, // decay time scale | ||
1184 | BSMotor.Infinite, // friction timescale | ||
1185 | 1f // efficiency | ||
1186 | ); | ||
1187 | _hoverMotor.SetTarget(ComputeCurrentPIDHoverHeight()); | ||
1188 | _hoverMotor.SetCurrent(RawPosition.Z); | ||
1189 | _hoverMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG so motor will output detail log messages. | ||
1190 | |||
1191 | RegisterPreStepAction("BSPrim.Hover", LocalID, delegate(float timeStep) | ||
1192 | { | ||
1193 | // Don't do hovering while the object is selected. | ||
1194 | if (!IsPhysicallyActive) | ||
1195 | return; | ||
1196 | |||
1197 | _hoverMotor.SetCurrent(RawPosition.Z); | ||
1198 | _hoverMotor.SetTarget(ComputeCurrentPIDHoverHeight()); | ||
1199 | float targetHeight = _hoverMotor.Step(timeStep); | ||
1200 | |||
1201 | // 'targetHeight' is where we'd like the Z of the prim to be at this moment. | ||
1202 | // Compute the amount of force to push us there. | ||
1203 | float moveForce = (targetHeight - RawPosition.Z) * Mass; | ||
1204 | // Undo anything the object thinks it's doing at the moment | ||
1205 | moveForce = -RawVelocity.Z * Mass; | ||
1206 | |||
1207 | PhysicsScene.PE.ApplyCentralImpulse(PhysBody, new OMV.Vector3(0f, 0f, moveForce)); | ||
1208 | DetailLog("{0},BSPrim.Hover,move,targHt={1},moveForce={2},mass={3}", LocalID, targetHeight, moveForce, Mass); | ||
1209 | }); | ||
1210 | } | ||
1211 | else | ||
1212 | { | 1053 | { |
1213 | UnRegisterPreStepAction("BSPrim.Hover", LocalID); | 1054 | return new BSActorHover(PhysicsScene, this, HoverActorName); |
1214 | } | 1055 | }); |
1215 | } | ||
1216 | } | ||
1217 | public override float PIDHoverHeight { | ||
1218 | set { _PIDHoverHeight = value; } | ||
1219 | } | ||
1220 | public override PIDHoverType PIDHoverType { | ||
1221 | set { _PIDHoverType = value; } | ||
1222 | } | ||
1223 | public override float PIDHoverTau { | ||
1224 | set { _PIDHoverTau = value; } | ||
1225 | } | ||
1226 | // Based on current position, determine what we should be hovering at now. | ||
1227 | // Must recompute often. What if we walked offa cliff> | ||
1228 | private float ComputeCurrentPIDHoverHeight() | ||
1229 | { | ||
1230 | float ret = _PIDHoverHeight; | ||
1231 | float groundHeight = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(RawPosition); | ||
1232 | |||
1233 | switch (_PIDHoverType) | ||
1234 | { | ||
1235 | case PIDHoverType.Ground: | ||
1236 | ret = groundHeight + _PIDHoverHeight; | ||
1237 | break; | ||
1238 | case PIDHoverType.GroundAndWater: | ||
1239 | float waterHeight = PhysicsScene.TerrainManager.GetWaterLevelAtXYZ(RawPosition); | ||
1240 | if (groundHeight > waterHeight) | ||
1241 | { | ||
1242 | ret = groundHeight + _PIDHoverHeight; | ||
1243 | } | ||
1244 | else | ||
1245 | { | ||
1246 | ret = waterHeight + _PIDHoverHeight; | ||
1247 | } | ||
1248 | break; | ||
1249 | } | 1056 | } |
1250 | return ret; | ||
1251 | } | 1057 | } |
1252 | 1058 | ||
1253 | |||
1254 | // For RotLookAt | ||
1255 | public override OMV.Quaternion APIDTarget { set { return; } } | ||
1256 | public override bool APIDActive { set { return; } } | ||
1257 | public override float APIDStrength { set { return; } } | ||
1258 | public override float APIDDamping { set { return; } } | ||
1259 | |||
1260 | public override void AddForce(OMV.Vector3 force, bool pushforce) { | 1059 | public override void AddForce(OMV.Vector3 force, bool pushforce) { |
1261 | // Per documentation, max force is limited. | 1060 | // Per documentation, max force is limited. |
1262 | OMV.Vector3 addForce = Util.ClampV(force, BSParam.MaxAddForceMagnitude); | 1061 | OMV.Vector3 addForce = Util.ClampV(force, BSParam.MaxAddForceMagnitude); |
@@ -1324,10 +1123,8 @@ public class BSPrim : BSPhysObject | |||
1324 | } | 1123 | } |
1325 | } | 1124 | } |
1326 | 1125 | ||
1327 | public override void AddAngularForce(OMV.Vector3 force, bool pushforce) { | 1126 | // BSPhysObject.AddAngularForce() |
1328 | AddAngularForce(force, pushforce, false); | 1127 | public override void AddAngularForce(OMV.Vector3 force, bool pushforce, bool inTaintTime) |
1329 | } | ||
1330 | public void AddAngularForce(OMV.Vector3 force, bool pushforce, bool inTaintTime) | ||
1331 | { | 1128 | { |
1332 | if (force.IsFinite()) | 1129 | if (force.IsFinite()) |
1333 | { | 1130 | { |
@@ -1694,8 +1491,8 @@ public class BSPrim : BSPhysObject | |||
1694 | _orientation = entprop.Rotation; | 1491 | _orientation = entprop.Rotation; |
1695 | // DEBUG DEBUG DEBUG -- smooth velocity changes a bit. The simulator seems to be | 1492 | // DEBUG DEBUG DEBUG -- smooth velocity changes a bit. The simulator seems to be |
1696 | // very sensitive to velocity changes. | 1493 | // very sensitive to velocity changes. |
1697 | if (entprop.Velocity == OMV.Vector3.Zero || !entprop.Velocity.ApproxEquals(_velocity, BSParam.UpdateVelocityChangeThreshold)) | 1494 | if (entprop.Velocity == OMV.Vector3.Zero || !entprop.Velocity.ApproxEquals(RawVelocity, BSParam.UpdateVelocityChangeThreshold)) |
1698 | _velocity = entprop.Velocity; | 1495 | RawVelocity = entprop.Velocity; |
1699 | _acceleration = entprop.Acceleration; | 1496 | _acceleration = entprop.Acceleration; |
1700 | _rotationalVelocity = entprop.RotationalVelocity; | 1497 | _rotationalVelocity = entprop.RotationalVelocity; |
1701 | 1498 | ||
@@ -1705,7 +1502,7 @@ public class BSPrim : BSPhysObject | |||
1705 | if (PositionSanityCheck(true /* inTaintTime */ )) | 1502 | if (PositionSanityCheck(true /* inTaintTime */ )) |
1706 | { | 1503 | { |
1707 | entprop.Position = _position; | 1504 | entprop.Position = _position; |
1708 | entprop.Velocity = _velocity; | 1505 | entprop.Velocity = RawVelocity; |
1709 | entprop.RotationalVelocity = _rotationalVelocity; | 1506 | entprop.RotationalVelocity = _rotationalVelocity; |
1710 | entprop.Acceleration = _acceleration; | 1507 | entprop.Acceleration = _acceleration; |
1711 | } | 1508 | } |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt b/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt index 8a15abe..a0131c7 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt +++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt | |||
@@ -6,7 +6,6 @@ Enable vehicle border crossings (at least as poorly as ODE) | |||
6 | Terrain skirts | 6 | Terrain skirts |
7 | Avatar created in previous region and not new region when crossing border | 7 | Avatar created in previous region and not new region when crossing border |
8 | Vehicle recreated in new sim at small Z value (offset from root value?) (DONE) | 8 | Vehicle recreated in new sim at small Z value (offset from root value?) (DONE) |
9 | Lock axis | ||
10 | Deleting a linkset while standing on the root will leave the physical shape of the root behind. | 9 | Deleting a linkset while standing on the root will leave the physical shape of the root behind. |
11 | Not sure if it is because standing on it. Done with large prim linksets. | 10 | Not sure if it is because standing on it. Done with large prim linksets. |
12 | Linkset child rotations. | 11 | Linkset child rotations. |
@@ -344,3 +343,5 @@ Angular motion around Z moves the vehicle in world Z and not vehicle Z in ODE. | |||
344 | Verify that angular motion specified around Z moves in the vehicle coordinates. | 343 | Verify that angular motion specified around Z moves in the vehicle coordinates. |
345 | DONE 20130120: BulletSim properly applies force in vehicle relative coordinates. | 344 | DONE 20130120: BulletSim properly applies force in vehicle relative coordinates. |
346 | Nebadon vehicles turning funny in arena (DONE) | 345 | Nebadon vehicles turning funny in arena (DONE) |
346 | Lock axis (DONE 20130401) | ||
347 | |||