diff options
Diffstat (limited to 'OpenSim')
13 files changed, 1258 insertions, 828 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs b/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs new file mode 100755 index 0000000..8416740 --- /dev/null +++ b/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs | |||
@@ -0,0 +1,285 @@ | |||
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 the object is physically active, add the hoverer prestep action | ||
71 | if (isActive) | ||
72 | { | ||
73 | ActivateAvatarMove(); | ||
74 | } | ||
75 | else | ||
76 | { | ||
77 | DeactivateAvatarMove(); | ||
78 | } | ||
79 | } | ||
80 | |||
81 | // The object's physical representation is being rebuilt so pick up any physical dependencies (constraints, ...). | ||
82 | // Register a prestep action to restore physical requirements before the next simulation step. | ||
83 | // Called at taint-time. | ||
84 | // BSActor.RemoveBodyDependencies() | ||
85 | public override void RemoveBodyDependencies() | ||
86 | { | ||
87 | // Nothing to do for the hoverer since it is all software at pre-step action time. | ||
88 | } | ||
89 | |||
90 | // Usually called when target velocity changes to set the current velocity and the target | ||
91 | // into the movement motor. | ||
92 | public void SetVelocityAndTarget(OMV.Vector3 vel, OMV.Vector3 targ, bool inTaintTime) | ||
93 | { | ||
94 | m_physicsScene.TaintedObject(inTaintTime, "BSActorAvatarMove.setVelocityAndTarget", delegate() | ||
95 | { | ||
96 | if (m_velocityMotor != null) | ||
97 | { | ||
98 | m_velocityMotor.Reset(); | ||
99 | m_velocityMotor.SetTarget(targ); | ||
100 | m_velocityMotor.SetCurrent(vel); | ||
101 | m_velocityMotor.Enabled = true; | ||
102 | } | ||
103 | }); | ||
104 | } | ||
105 | |||
106 | // If a hover motor has not been created, create one and start the hovering. | ||
107 | private void ActivateAvatarMove() | ||
108 | { | ||
109 | if (m_velocityMotor == null) | ||
110 | { | ||
111 | // Infinite decay and timescale values so motor only changes current to target values. | ||
112 | m_velocityMotor = new BSVMotor("BSCharacter.Velocity", | ||
113 | 0.2f, // time scale | ||
114 | BSMotor.Infinite, // decay time scale | ||
115 | BSMotor.InfiniteVector, // friction timescale | ||
116 | 1f // efficiency | ||
117 | ); | ||
118 | // _velocityMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG so motor will output detail log messages. | ||
119 | SetVelocityAndTarget(m_controllingPrim.RawVelocity, m_controllingPrim.TargetVelocity, true /* inTaintTime */); | ||
120 | |||
121 | m_physicsScene.BeforeStep += Mover; | ||
122 | } | ||
123 | } | ||
124 | |||
125 | private void DeactivateAvatarMove() | ||
126 | { | ||
127 | if (m_velocityMotor != null) | ||
128 | { | ||
129 | m_physicsScene.BeforeStep -= Mover; | ||
130 | m_velocityMotor = null; | ||
131 | } | ||
132 | } | ||
133 | |||
134 | // Called just before the simulation step. Update the vertical position for hoverness. | ||
135 | private void Mover(float timeStep) | ||
136 | { | ||
137 | // Don't do movement while the object is selected. | ||
138 | if (!isActive) | ||
139 | return; | ||
140 | |||
141 | // TODO: Decide if the step parameters should be changed depending on the avatar's | ||
142 | // state (flying, colliding, ...). There is code in ODE to do this. | ||
143 | |||
144 | // COMMENTARY: when the user is making the avatar walk, except for falling, the velocity | ||
145 | // specified for the avatar is the one that should be used. For falling, if the avatar | ||
146 | // is not flying and is not colliding then it is presumed to be falling and the Z | ||
147 | // component is not fooled with (thus allowing gravity to do its thing). | ||
148 | // When the avatar is standing, though, the user has specified a velocity of zero and | ||
149 | // the avatar should be standing. But if the avatar is pushed by something in the world | ||
150 | // (raising elevator platform, moving vehicle, ...) the avatar should be allowed to | ||
151 | // move. Thus, the velocity cannot be forced to zero. The problem is that small velocity | ||
152 | // errors can creap in and the avatar will slowly float off in some direction. | ||
153 | // So, the problem is that, when an avatar is standing, we cannot tell creaping error | ||
154 | // from real pushing. | ||
155 | // The code below uses whether the collider is static or moving to decide whether to zero motion. | ||
156 | |||
157 | m_velocityMotor.Step(timeStep); | ||
158 | m_controllingPrim.IsStationary = false; | ||
159 | |||
160 | // If we're not supposed to be moving, make sure things are zero. | ||
161 | if (m_velocityMotor.ErrorIsZero() && m_velocityMotor.TargetValue == OMV.Vector3.Zero) | ||
162 | { | ||
163 | // The avatar shouldn't be moving | ||
164 | m_velocityMotor.Zero(); | ||
165 | |||
166 | if (m_controllingPrim.IsColliding) | ||
167 | { | ||
168 | // If we are colliding with a stationary object, presume we're standing and don't move around | ||
169 | if (!m_controllingPrim.ColliderIsMoving) | ||
170 | { | ||
171 | m_physicsScene.DetailLog("{0},BSCharacter.MoveMotor,collidingWithStationary,zeroingMotion", m_controllingPrim.LocalID); | ||
172 | m_controllingPrim.IsStationary = true; | ||
173 | m_controllingPrim.ZeroMotion(true /* inTaintTime */); | ||
174 | } | ||
175 | |||
176 | // Standing has more friction on the ground | ||
177 | if (m_controllingPrim.Friction != BSParam.AvatarStandingFriction) | ||
178 | { | ||
179 | m_controllingPrim.Friction = BSParam.AvatarStandingFriction; | ||
180 | m_physicsScene.PE.SetFriction(m_controllingPrim.PhysBody, m_controllingPrim.Friction); | ||
181 | } | ||
182 | } | ||
183 | else | ||
184 | { | ||
185 | if (m_controllingPrim.Flying) | ||
186 | { | ||
187 | // Flying and not collising and velocity nearly zero. | ||
188 | m_controllingPrim.ZeroMotion(true /* inTaintTime */); | ||
189 | } | ||
190 | } | ||
191 | |||
192 | m_physicsScene.DetailLog("{0},BSCharacter.MoveMotor,taint,stopping,target={1},colliding={2}", | ||
193 | m_controllingPrim.LocalID, m_velocityMotor.TargetValue, m_controllingPrim.IsColliding); | ||
194 | } | ||
195 | else | ||
196 | { | ||
197 | // Supposed to be moving. | ||
198 | OMV.Vector3 stepVelocity = m_velocityMotor.CurrentValue; | ||
199 | |||
200 | if (m_controllingPrim.Friction != BSParam.AvatarFriction) | ||
201 | { | ||
202 | // Probably starting up walking. Set friction to moving friction. | ||
203 | m_controllingPrim.Friction = BSParam.AvatarFriction; | ||
204 | m_physicsScene.PE.SetFriction(m_controllingPrim.PhysBody, m_controllingPrim.Friction); | ||
205 | } | ||
206 | |||
207 | // If falling, we keep the world's downward vector no matter what the other axis specify. | ||
208 | // The check for RawVelocity.Z < 0 makes jumping work (temporary upward force). | ||
209 | if (!m_controllingPrim.Flying && !m_controllingPrim.IsColliding) | ||
210 | { | ||
211 | if (m_controllingPrim.RawVelocity.Z < 0) | ||
212 | stepVelocity.Z = m_controllingPrim.RawVelocity.Z; | ||
213 | // DetailLog("{0},BSCharacter.MoveMotor,taint,overrideStepZWithWorldZ,stepVel={1}", LocalID, stepVelocity); | ||
214 | } | ||
215 | |||
216 | // 'stepVelocity' is now the speed we'd like the avatar to move in. Turn that into an instantanous force. | ||
217 | OMV.Vector3 moveForce = (stepVelocity - m_controllingPrim.RawVelocity) * m_controllingPrim.Mass; | ||
218 | |||
219 | // Should we check for move force being small and forcing velocity to zero? | ||
220 | |||
221 | // Add special movement force to allow avatars to walk up stepped surfaces. | ||
222 | moveForce += WalkUpStairs(); | ||
223 | |||
224 | m_physicsScene.DetailLog("{0},BSCharacter.MoveMotor,move,stepVel={1},vel={2},mass={3},moveForce={4}", | ||
225 | m_controllingPrim.LocalID, stepVelocity, m_controllingPrim.RawVelocity, m_controllingPrim.Mass, moveForce); | ||
226 | m_physicsScene.PE.ApplyCentralImpulse(m_controllingPrim.PhysBody, moveForce); | ||
227 | } | ||
228 | } | ||
229 | |||
230 | // Decide if the character is colliding with a low object and compute a force to pop the | ||
231 | // avatar up so it can walk up and over the low objects. | ||
232 | private OMV.Vector3 WalkUpStairs() | ||
233 | { | ||
234 | OMV.Vector3 ret = OMV.Vector3.Zero; | ||
235 | |||
236 | // This test is done if moving forward, not flying and is colliding with something. | ||
237 | // DetailLog("{0},BSCharacter.WalkUpStairs,IsColliding={1},flying={2},targSpeed={3},collisions={4}", | ||
238 | // LocalID, IsColliding, Flying, TargetSpeed, CollisionsLastTick.Count); | ||
239 | if (m_controllingPrim.IsColliding && !m_controllingPrim.Flying && m_controllingPrim.TargetVelocitySpeed > 0.1f /* && ForwardSpeed < 0.1f */) | ||
240 | { | ||
241 | // The range near the character's feet where we will consider stairs | ||
242 | float nearFeetHeightMin = m_controllingPrim.RawPosition.Z - (m_controllingPrim.Size.Z / 2f) + 0.05f; | ||
243 | float nearFeetHeightMax = nearFeetHeightMin + BSParam.AvatarStepHeight; | ||
244 | |||
245 | // Look for a collision point that is near the character's feet and is oriented the same as the charactor is | ||
246 | foreach (KeyValuePair<uint, ContactPoint> kvp in m_controllingPrim.CollisionsLastTick.m_objCollisionList) | ||
247 | { | ||
248 | // Don't care about collisions with the terrain | ||
249 | if (kvp.Key > m_physicsScene.TerrainManager.HighestTerrainID) | ||
250 | { | ||
251 | OMV.Vector3 touchPosition = kvp.Value.Position; | ||
252 | // DetailLog("{0},BSCharacter.WalkUpStairs,min={1},max={2},touch={3}", | ||
253 | // LocalID, nearFeetHeightMin, nearFeetHeightMax, touchPosition); | ||
254 | if (touchPosition.Z >= nearFeetHeightMin && touchPosition.Z <= nearFeetHeightMax) | ||
255 | { | ||
256 | // This contact is within the 'near the feet' range. | ||
257 | // The normal should be our contact point to the object so it is pointing away | ||
258 | // thus the difference between our facing orientation and the normal should be small. | ||
259 | OMV.Vector3 directionFacing = OMV.Vector3.UnitX * m_controllingPrim.RawOrientation; | ||
260 | OMV.Vector3 touchNormal = OMV.Vector3.Normalize(kvp.Value.SurfaceNormal); | ||
261 | float diff = Math.Abs(OMV.Vector3.Distance(directionFacing, touchNormal)); | ||
262 | if (diff < BSParam.AvatarStepApproachFactor) | ||
263 | { | ||
264 | // Found the stairs contact point. Push up a little to raise the character. | ||
265 | float upForce = (touchPosition.Z - nearFeetHeightMin) * m_controllingPrim.Mass * BSParam.AvatarStepForceFactor; | ||
266 | ret = new OMV.Vector3(0f, 0f, upForce); | ||
267 | |||
268 | // Also move the avatar up for the new height | ||
269 | OMV.Vector3 displacement = new OMV.Vector3(0f, 0f, BSParam.AvatarStepHeight / 2f); | ||
270 | m_controllingPrim.ForcePosition = m_controllingPrim.RawPosition + displacement; | ||
271 | } | ||
272 | m_physicsScene.DetailLog("{0},BSCharacter.WalkUpStairs,touchPos={1},nearFeetMin={2},faceDir={3},norm={4},diff={5},ret={6}", | ||
273 | m_controllingPrim.LocalID, touchPosition, nearFeetHeightMin, directionFacing, touchNormal, diff, ret); | ||
274 | } | ||
275 | } | ||
276 | } | ||
277 | } | ||
278 | |||
279 | return ret; | ||
280 | } | ||
281 | |||
282 | } | ||
283 | } | ||
284 | |||
285 | |||
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSActorHover.cs b/OpenSim/Region/Physics/BulletSPlugin/BSActorHover.cs new file mode 100755 index 0000000..e8310df --- /dev/null +++ b/OpenSim/Region/Physics/BulletSPlugin/BSActorHover.cs | |||
@@ -0,0 +1,174 @@ | |||
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, turn me off | ||
71 | if (!m_controllingPrim.HoverActive) | ||
72 | { | ||
73 | SetEnabled(false); | ||
74 | } | ||
75 | |||
76 | // If the object is physically active, add the hoverer prestep action | ||
77 | if (isActive) | ||
78 | { | ||
79 | ActivateHover(); | ||
80 | } | ||
81 | else | ||
82 | { | ||
83 | DeactivateHover(); | ||
84 | } | ||
85 | } | ||
86 | |||
87 | // The object's physical representation is being rebuilt so pick up any physical dependencies (constraints, ...). | ||
88 | // Register a prestep action to restore physical requirements before the next simulation step. | ||
89 | // Called at taint-time. | ||
90 | // BSActor.RemoveBodyDependencies() | ||
91 | public override void RemoveBodyDependencies() | ||
92 | { | ||
93 | // Nothing to do for the hoverer since it is all software at pre-step action time. | ||
94 | } | ||
95 | |||
96 | // If a hover motor has not been created, create one and start the hovering. | ||
97 | private void ActivateHover() | ||
98 | { | ||
99 | if (m_hoverMotor == null) | ||
100 | { | ||
101 | // Turning the target on | ||
102 | m_hoverMotor = new BSFMotor("BSActorHover", | ||
103 | m_controllingPrim.HoverTau, // timeScale | ||
104 | BSMotor.Infinite, // decay time scale | ||
105 | BSMotor.Infinite, // friction timescale | ||
106 | 1f // efficiency | ||
107 | ); | ||
108 | m_hoverMotor.SetTarget(ComputeCurrentHoverHeight()); | ||
109 | m_hoverMotor.SetCurrent(m_controllingPrim.RawPosition.Z); | ||
110 | m_hoverMotor.PhysicsScene = m_physicsScene; // DEBUG DEBUG so motor will output detail log messages. | ||
111 | |||
112 | m_physicsScene.BeforeStep += Hoverer; | ||
113 | } | ||
114 | } | ||
115 | |||
116 | private void DeactivateHover() | ||
117 | { | ||
118 | if (m_hoverMotor != null) | ||
119 | { | ||
120 | m_physicsScene.BeforeStep -= Hoverer; | ||
121 | m_hoverMotor = null; | ||
122 | } | ||
123 | } | ||
124 | |||
125 | // Called just before the simulation step. Update the vertical position for hoverness. | ||
126 | private void Hoverer(float timeStep) | ||
127 | { | ||
128 | // Don't do hovering while the object is selected. | ||
129 | if (!isActive) | ||
130 | return; | ||
131 | |||
132 | m_hoverMotor.SetCurrent(m_controllingPrim.RawPosition.Z); | ||
133 | m_hoverMotor.SetTarget(ComputeCurrentHoverHeight()); | ||
134 | float targetHeight = m_hoverMotor.Step(timeStep); | ||
135 | |||
136 | // 'targetHeight' is where we'd like the Z of the prim to be at this moment. | ||
137 | // Compute the amount of force to push us there. | ||
138 | float moveForce = (targetHeight - m_controllingPrim.RawPosition.Z) * m_controllingPrim.RawMass; | ||
139 | // Undo anything the object thinks it's doing at the moment | ||
140 | moveForce = -m_controllingPrim.RawVelocity.Z * m_controllingPrim.Mass; | ||
141 | |||
142 | m_physicsScene.PE.ApplyCentralImpulse(m_controllingPrim.PhysBody, new OMV.Vector3(0f, 0f, moveForce)); | ||
143 | m_physicsScene.DetailLog("{0},BSPrim.Hover,move,targHt={1},moveForce={2},mass={3}", | ||
144 | m_controllingPrim.LocalID, targetHeight, moveForce, m_controllingPrim.RawMass); | ||
145 | } | ||
146 | |||
147 | // Based on current position, determine what we should be hovering at now. | ||
148 | // Must recompute often. What if we walked offa cliff> | ||
149 | private float ComputeCurrentHoverHeight() | ||
150 | { | ||
151 | float ret = m_controllingPrim.HoverHeight; | ||
152 | float groundHeight = m_physicsScene.TerrainManager.GetTerrainHeightAtXYZ(m_controllingPrim.RawPosition); | ||
153 | |||
154 | switch (m_controllingPrim.HoverType) | ||
155 | { | ||
156 | case PIDHoverType.Ground: | ||
157 | ret = groundHeight + m_controllingPrim.HoverHeight; | ||
158 | break; | ||
159 | case PIDHoverType.GroundAndWater: | ||
160 | float waterHeight = m_physicsScene.TerrainManager.GetWaterLevelAtXYZ(m_controllingPrim.RawPosition); | ||
161 | if (groundHeight > waterHeight) | ||
162 | { | ||
163 | ret = groundHeight + m_controllingPrim.HoverHeight; | ||
164 | } | ||
165 | else | ||
166 | { | ||
167 | ret = waterHeight + m_controllingPrim.HoverHeight; | ||
168 | } | ||
169 | break; | ||
170 | } | ||
171 | return ret; | ||
172 | } | ||
173 | } | ||
174 | } | ||
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSActorLockAxis.cs b/OpenSim/Region/Physics/BulletSPlugin/BSActorLockAxis.cs index 7219617..09ee32b 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSActorLockAxis.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSActorLockAxis.cs | |||
@@ -36,11 +36,10 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
36 | { | 36 | { |
37 | public class BSActorLockAxis : BSActor | 37 | public class BSActorLockAxis : BSActor |
38 | { | 38 | { |
39 | bool TryExperimentalLockAxisCode = true; | ||
40 | BSConstraint LockAxisConstraint = null; | 39 | BSConstraint LockAxisConstraint = null; |
41 | 40 | ||
42 | public BSActorLockAxis(BSScene physicsScene, BSPhysObject pObj, string actorName) | 41 | public BSActorLockAxis(BSScene physicsScene, BSPhysObject pObj, string actorName) |
43 | : base(physicsScene, pObj,actorName) | 42 | : base(physicsScene, pObj, actorName) |
44 | { | 43 | { |
45 | m_physicsScene.DetailLog("{0},BSActorLockAxis,constructor", m_controllingPrim.LocalID); | 44 | m_physicsScene.DetailLog("{0},BSActorLockAxis,constructor", m_controllingPrim.LocalID); |
46 | LockAxisConstraint = null; | 45 | LockAxisConstraint = null; |
@@ -69,18 +68,13 @@ public class BSActorLockAxis : BSActor | |||
69 | // If all the axis are free, we don't need to exist | 68 | // If all the axis are free, we don't need to exist |
70 | if (m_controllingPrim.LockedAxis == m_controllingPrim.LockedAxisFree) | 69 | if (m_controllingPrim.LockedAxis == m_controllingPrim.LockedAxisFree) |
71 | { | 70 | { |
72 | m_physicsScene.DetailLog("{0},BSActorLockAxis,refresh,allAxisFree,removing={1}", m_controllingPrim.LocalID, ActorName); | 71 | Enabled = false; |
73 | m_controllingPrim.PhysicalActors.RemoveAndRelease(ActorName); | ||
74 | return; | ||
75 | } | 72 | } |
73 | |||
76 | // If the object is physically active, add the axis locking constraint | 74 | // If the object is physically active, add the axis locking constraint |
77 | if (Enabled | 75 | if (isActive) |
78 | && m_controllingPrim.IsPhysicallyActive | ||
79 | && TryExperimentalLockAxisCode | ||
80 | && m_controllingPrim.LockedAxis != m_controllingPrim.LockedAxisFree) | ||
81 | { | 76 | { |
82 | if (LockAxisConstraint == null) | 77 | AddAxisLockConstraint(); |
83 | AddAxisLockConstraint(); | ||
84 | } | 78 | } |
85 | else | 79 | else |
86 | { | 80 | { |
@@ -99,7 +93,7 @@ public class BSActorLockAxis : BSActor | |||
99 | // If a constraint is set up, remove it from the physical scene | 93 | // If a constraint is set up, remove it from the physical scene |
100 | RemoveAxisLockConstraint(); | 94 | RemoveAxisLockConstraint(); |
101 | // Schedule a call before the next simulation step to restore the constraint. | 95 | // Schedule a call before the next simulation step to restore the constraint. |
102 | m_physicsScene.PostTaintObject(m_controllingPrim.LockedAxisActorName, m_controllingPrim.LocalID, delegate() | 96 | m_physicsScene.PostTaintObject("BSActorLockAxis:" + ActorName, m_controllingPrim.LocalID, delegate() |
103 | { | 97 | { |
104 | Refresh(); | 98 | Refresh(); |
105 | }); | 99 | }); |
@@ -108,58 +102,61 @@ public class BSActorLockAxis : BSActor | |||
108 | 102 | ||
109 | private void AddAxisLockConstraint() | 103 | private void AddAxisLockConstraint() |
110 | { | 104 | { |
111 | // Lock that axis by creating a 6DOF constraint that has one end in the world and | 105 | if (LockAxisConstraint == null) |
112 | // the other in the object. | 106 | { |
113 | // http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?p=20817 | 107 | // Lock that axis by creating a 6DOF constraint that has one end in the world and |
114 | // http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?p=26380 | 108 | // the other in the object. |
109 | // http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?p=20817 | ||
110 | // http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?p=26380 | ||
115 | 111 | ||
116 | // Remove any existing axis constraint (just to be sure) | 112 | // Remove any existing axis constraint (just to be sure) |
117 | RemoveAxisLockConstraint(); | 113 | RemoveAxisLockConstraint(); |
118 | 114 | ||
119 | BSConstraint6Dof axisConstrainer = new BSConstraint6Dof(m_physicsScene.World, m_controllingPrim.PhysBody, | 115 | BSConstraint6Dof axisConstrainer = new BSConstraint6Dof(m_physicsScene.World, m_controllingPrim.PhysBody, |
120 | OMV.Vector3.Zero, OMV.Quaternion.Identity, | 116 | OMV.Vector3.Zero, OMV.Quaternion.Identity, |
121 | false /* useLinearReferenceFrameB */, true /* disableCollisionsBetweenLinkedBodies */); | 117 | false /* useLinearReferenceFrameB */, true /* disableCollisionsBetweenLinkedBodies */); |
122 | LockAxisConstraint = axisConstrainer; | 118 | LockAxisConstraint = axisConstrainer; |
123 | m_physicsScene.Constraints.AddConstraint(LockAxisConstraint); | 119 | m_physicsScene.Constraints.AddConstraint(LockAxisConstraint); |
124 | 120 | ||
125 | // The constraint is tied to the world and oriented to the prim. | 121 | // The constraint is tied to the world and oriented to the prim. |
126 | 122 | ||
127 | // Free to move linearly in the region | 123 | // Free to move linearly in the region |
128 | OMV.Vector3 linearLow = OMV.Vector3.Zero; | 124 | OMV.Vector3 linearLow = OMV.Vector3.Zero; |
129 | OMV.Vector3 linearHigh = m_physicsScene.TerrainManager.DefaultRegionSize; | 125 | OMV.Vector3 linearHigh = m_physicsScene.TerrainManager.DefaultRegionSize; |
130 | axisConstrainer.SetLinearLimits(linearLow, linearHigh); | 126 | axisConstrainer.SetLinearLimits(linearLow, linearHigh); |
131 | 127 | ||
132 | // Angular with some axis locked | 128 | // Angular with some axis locked |
133 | float fPI = (float)Math.PI; | 129 | float fPI = (float)Math.PI; |
134 | OMV.Vector3 angularLow = new OMV.Vector3(-fPI, -fPI, -fPI); | 130 | OMV.Vector3 angularLow = new OMV.Vector3(-fPI, -fPI, -fPI); |
135 | OMV.Vector3 angularHigh = new OMV.Vector3(fPI, fPI, fPI); | 131 | OMV.Vector3 angularHigh = new OMV.Vector3(fPI, fPI, fPI); |
136 | if (m_controllingPrim.LockedAxis.X != 1f) | 132 | if (m_controllingPrim.LockedAxis.X != 1f) |
137 | { | 133 | { |
138 | angularLow.X = 0f; | 134 | angularLow.X = 0f; |
139 | angularHigh.X = 0f; | 135 | angularHigh.X = 0f; |
140 | } | 136 | } |
141 | if (m_controllingPrim.LockedAxis.Y != 1f) | 137 | if (m_controllingPrim.LockedAxis.Y != 1f) |
142 | { | 138 | { |
143 | angularLow.Y = 0f; | 139 | angularLow.Y = 0f; |
144 | angularHigh.Y = 0f; | 140 | angularHigh.Y = 0f; |
145 | } | 141 | } |
146 | if (m_controllingPrim.LockedAxis.Z != 1f) | 142 | if (m_controllingPrim.LockedAxis.Z != 1f) |
147 | { | 143 | { |
148 | angularLow.Z = 0f; | 144 | angularLow.Z = 0f; |
149 | angularHigh.Z = 0f; | 145 | angularHigh.Z = 0f; |
150 | } | 146 | } |
151 | if (!axisConstrainer.SetAngularLimits(angularLow, angularHigh)) | 147 | if (!axisConstrainer.SetAngularLimits(angularLow, angularHigh)) |
152 | { | 148 | { |
153 | m_physicsScene.DetailLog("{0},BSActorLockAxis.AddAxisLockConstraint,failedSetAngularLimits", m_controllingPrim.LocalID); | 149 | m_physicsScene.DetailLog("{0},BSActorLockAxis.AddAxisLockConstraint,failedSetAngularLimits", m_controllingPrim.LocalID); |
154 | } | 150 | } |
155 | 151 | ||
156 | m_physicsScene.DetailLog("{0},BSActorLockAxis.AddAxisLockConstraint,create,linLow={1},linHi={2},angLow={3},angHi={4}", | 152 | m_physicsScene.DetailLog("{0},BSActorLockAxis.AddAxisLockConstraint,create,linLow={1},linHi={2},angLow={3},angHi={4}", |
157 | m_controllingPrim.LocalID, linearLow, linearHigh, angularLow, angularHigh); | 153 | m_controllingPrim.LocalID, linearLow, linearHigh, angularLow, angularHigh); |
158 | 154 | ||
159 | // Constants from one of the posts mentioned above and used in Bullet's ConstraintDemo. | 155 | // Constants from one of the posts mentioned above and used in Bullet's ConstraintDemo. |
160 | axisConstrainer.TranslationalLimitMotor(true /* enable */, 5.0f, 0.1f); | 156 | axisConstrainer.TranslationalLimitMotor(true /* enable */, 5.0f, 0.1f); |
161 | 157 | ||
162 | axisConstrainer.RecomputeConstraintVariables(m_controllingPrim.RawMass); | 158 | axisConstrainer.RecomputeConstraintVariables(m_controllingPrim.RawMass); |
159 | } | ||
163 | } | 160 | } |
164 | 161 | ||
165 | private void RemoveAxisLockConstraint() | 162 | private void RemoveAxisLockConstraint() |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSActorMoveToTarget.cs b/OpenSim/Region/Physics/BulletSPlugin/BSActorMoveToTarget.cs new file mode 100755 index 0000000..16c2b14 --- /dev/null +++ b/OpenSim/Region/Physics/BulletSPlugin/BSActorMoveToTarget.cs | |||
@@ -0,0 +1,152 @@ | |||
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... | ||
71 | if (!m_controllingPrim.MoveToTargetActive) | ||
72 | { | ||
73 | Enabled = false; | ||
74 | } | ||
75 | |||
76 | if (isActive) | ||
77 | { | ||
78 | ActivateMoveToTarget(); | ||
79 | } | ||
80 | else | ||
81 | { | ||
82 | DeactivateMoveToTarget(); | ||
83 | } | ||
84 | } | ||
85 | |||
86 | // The object's physical representation is being rebuilt so pick up any physical dependencies (constraints, ...). | ||
87 | // Register a prestep action to restore physical requirements before the next simulation step. | ||
88 | // Called at taint-time. | ||
89 | // BSActor.RemoveBodyDependencies() | ||
90 | public override void RemoveBodyDependencies() | ||
91 | { | ||
92 | // Nothing to do for the moveToTarget since it is all software at pre-step action time. | ||
93 | } | ||
94 | |||
95 | // If a hover motor has not been created, create one and start the hovering. | ||
96 | private void ActivateMoveToTarget() | ||
97 | { | ||
98 | if (m_targetMotor == null) | ||
99 | { | ||
100 | // We're taking over after this. | ||
101 | m_controllingPrim.ZeroMotion(true); | ||
102 | |||
103 | m_targetMotor = new BSVMotor("BSPrim.PIDTarget", | ||
104 | m_controllingPrim.MoveToTargetTau, // timeScale | ||
105 | BSMotor.Infinite, // decay time scale | ||
106 | BSMotor.InfiniteVector, // friction timescale | ||
107 | 1f // efficiency | ||
108 | ); | ||
109 | m_targetMotor.PhysicsScene = m_physicsScene; // DEBUG DEBUG so motor will output detail log messages. | ||
110 | m_targetMotor.SetTarget(m_controllingPrim.MoveToTargetTarget); | ||
111 | m_targetMotor.SetCurrent(m_controllingPrim.RawPosition); | ||
112 | |||
113 | m_physicsScene.BeforeStep += Mover; | ||
114 | } | ||
115 | } | ||
116 | |||
117 | private void DeactivateMoveToTarget() | ||
118 | { | ||
119 | if (m_targetMotor != null) | ||
120 | { | ||
121 | m_physicsScene.BeforeStep -= Mover; | ||
122 | m_targetMotor = null; | ||
123 | } | ||
124 | } | ||
125 | |||
126 | // Called just before the simulation step. Update the vertical position for hoverness. | ||
127 | private void Mover(float timeStep) | ||
128 | { | ||
129 | // Don't do hovering while the object is selected. | ||
130 | if (!isActive) | ||
131 | return; | ||
132 | |||
133 | OMV.Vector3 origPosition = m_controllingPrim.RawPosition; // DEBUG DEBUG (for printout below) | ||
134 | |||
135 | // 'movePosition' is where we'd like the prim to be at this moment. | ||
136 | OMV.Vector3 movePosition = m_controllingPrim.RawPosition + m_targetMotor.Step(timeStep); | ||
137 | |||
138 | // If we are very close to our target, turn off the movement motor. | ||
139 | if (m_targetMotor.ErrorIsZero()) | ||
140 | { | ||
141 | m_physicsScene.DetailLog("{0},BSPrim.PIDTarget,zeroMovement,movePos={1},pos={2},mass={3}", | ||
142 | m_controllingPrim.LocalID, movePosition, m_controllingPrim.RawPosition, m_controllingPrim.Mass); | ||
143 | m_controllingPrim.ForcePosition = m_targetMotor.TargetValue; | ||
144 | } | ||
145 | else | ||
146 | { | ||
147 | m_controllingPrim.ForcePosition = movePosition; | ||
148 | } | ||
149 | m_physicsScene.DetailLog("{0},BSPrim.PIDTarget,move,fromPos={1},movePos={2}", m_controllingPrim.LocalID, origPosition, movePosition); | ||
150 | } | ||
151 | } | ||
152 | } | ||
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSActorSetForce.cs b/OpenSim/Region/Physics/BulletSPlugin/BSActorSetForce.cs new file mode 100755 index 0000000..3ad138d --- /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 | Enabled = false; | ||
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..7a791ec --- /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,torque={1}", m_controllingPrim.LocalID, m_controllingPrim.RawTorque); | ||
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,disabling={1}", m_controllingPrim.LocalID, ActorName); | ||
74 | Enabled = false; | ||
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..12a8817 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSActors.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSActors.cs | |||
@@ -32,45 +32,72 @@ 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) |
44 | { | 44 | { |
45 | m_actors[name] = actor; | 45 | lock (m_actors) |
46 | { | ||
47 | if (!m_actors.ContainsKey(name)) | ||
48 | { | ||
49 | m_actors[name] = actor; | ||
50 | } | ||
51 | } | ||
46 | } | 52 | } |
47 | public bool RemoveAndRelease(string name) | 53 | public bool RemoveAndRelease(string name) |
48 | { | 54 | { |
49 | bool ret = false; | 55 | bool ret = false; |
50 | if (m_actors.ContainsKey(name)) | 56 | lock (m_actors) |
51 | { | 57 | { |
52 | BSActor beingRemoved = m_actors[name]; | 58 | if (m_actors.ContainsKey(name)) |
53 | beingRemoved.Dispose(); | 59 | { |
54 | m_actors.Remove(name); | 60 | BSActor beingRemoved = m_actors[name]; |
55 | ret = true; | 61 | m_actors.Remove(name); |
62 | beingRemoved.Dispose(); | ||
63 | ret = true; | ||
64 | } | ||
56 | } | 65 | } |
57 | return ret; | 66 | return ret; |
58 | } | 67 | } |
59 | public void Clear() | 68 | public void Clear() |
60 | { | 69 | { |
61 | Release(); | 70 | lock (m_actors) |
62 | m_actors.Clear(); | 71 | { |
72 | Release(); | ||
73 | m_actors.Clear(); | ||
74 | } | ||
75 | } | ||
76 | public void Dispose() | ||
77 | { | ||
78 | Clear(); | ||
63 | } | 79 | } |
64 | public bool HasActor(string name) | 80 | public bool HasActor(string name) |
65 | { | 81 | { |
66 | return m_actors.ContainsKey(name); | 82 | return m_actors.ContainsKey(name); |
67 | } | 83 | } |
84 | public bool TryGetActor(string actorName, out BSActor theActor) | ||
85 | { | ||
86 | return m_actors.TryGetValue(actorName, out theActor); | ||
87 | } | ||
68 | public void ForEachActor(Action<BSActor> act) | 88 | public void ForEachActor(Action<BSActor> act) |
69 | { | 89 | { |
70 | foreach (KeyValuePair<string, BSActor> kvp in m_actors) | 90 | lock (m_actors) |
71 | act(kvp.Value); | 91 | { |
92 | foreach (KeyValuePair<string, BSActor> kvp in m_actors) | ||
93 | act(kvp.Value); | ||
94 | } | ||
72 | } | 95 | } |
73 | 96 | ||
97 | public void Enable(bool enabl) | ||
98 | { | ||
99 | ForEachActor(a => a.SetEnabled(enabl)); | ||
100 | } | ||
74 | public void Release() | 101 | public void Release() |
75 | { | 102 | { |
76 | ForEachActor(a => a.Dispose()); | 103 | ForEachActor(a => a.Dispose()); |
@@ -98,7 +125,7 @@ public abstract class BSActor | |||
98 | { | 125 | { |
99 | protected BSScene m_physicsScene { get; private set; } | 126 | protected BSScene m_physicsScene { get; private set; } |
100 | protected BSPhysObject m_controllingPrim { get; private set; } | 127 | protected BSPhysObject m_controllingPrim { get; private set; } |
101 | protected bool Enabled { get; set; } | 128 | public virtual bool Enabled { get; set; } |
102 | public string ActorName { get; private set; } | 129 | public string ActorName { get; private set; } |
103 | 130 | ||
104 | public BSActor(BSScene physicsScene, BSPhysObject pObj, string actorName) | 131 | public BSActor(BSScene physicsScene, BSPhysObject pObj, string actorName) |
@@ -114,8 +141,10 @@ public abstract class BSActor | |||
114 | { | 141 | { |
115 | get { return Enabled; } | 142 | get { return Enabled; } |
116 | } | 143 | } |
117 | // Turn the actor on an off. | 144 | |
118 | public virtual void Enable(bool setEnabled) | 145 | // Turn the actor on an off. Only used by ActorCollection to set all enabled/disabled. |
146 | // Anyone else should assign true/false to 'Enabled'. | ||
147 | public void SetEnabled(bool setEnabled) | ||
119 | { | 148 | { |
120 | Enabled = setEnabled; | 149 | Enabled = setEnabled; |
121 | } | 150 | } |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index 25be416..a0d58d3 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. |
@@ -163,6 +160,9 @@ public sealed class BSCharacter : BSPhysObject | |||
163 | // Make so capsule does not fall over | 160 | // Make so capsule does not fall over |
164 | PhysicsScene.PE.SetAngularFactorV(PhysBody, OMV.Vector3.Zero); | 161 | PhysicsScene.PE.SetAngularFactorV(PhysBody, OMV.Vector3.Zero); |
165 | 162 | ||
163 | // The avatar mover sets some parameters. | ||
164 | PhysicalActors.Refresh(); | ||
165 | |||
166 | PhysicsScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.CF_CHARACTER_OBJECT); | 166 | PhysicsScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.CF_CHARACTER_OBJECT); |
167 | 167 | ||
168 | PhysicsScene.PE.AddObjectToWorld(PhysicsScene.World, PhysBody); | 168 | PhysicsScene.PE.AddObjectToWorld(PhysicsScene.World, PhysBody); |
@@ -176,162 +176,6 @@ public sealed class BSCharacter : BSPhysObject | |||
176 | PhysBody.ApplyCollisionMask(PhysicsScene); | 176 | PhysBody.ApplyCollisionMask(PhysicsScene); |
177 | } | 177 | } |
178 | 178 | ||
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 | 179 | ||
336 | public override void RequestPhysicsterseUpdate() | 180 | public override void RequestPhysicsterseUpdate() |
337 | { | 181 | { |
@@ -403,7 +247,7 @@ public sealed class BSCharacter : BSPhysObject | |||
403 | // Called at taint time! | 247 | // Called at taint time! |
404 | public override void ZeroMotion(bool inTaintTime) | 248 | public override void ZeroMotion(bool inTaintTime) |
405 | { | 249 | { |
406 | _velocity = OMV.Vector3.Zero; | 250 | RawVelocity = OMV.Vector3.Zero; |
407 | _acceleration = OMV.Vector3.Zero; | 251 | _acceleration = OMV.Vector3.Zero; |
408 | _rotationalVelocity = OMV.Vector3.Zero; | 252 | _rotationalVelocity = OMV.Vector3.Zero; |
409 | 253 | ||
@@ -542,15 +386,15 @@ public sealed class BSCharacter : BSPhysObject | |||
542 | } | 386 | } |
543 | 387 | ||
544 | public override OMV.Vector3 Force { | 388 | public override OMV.Vector3 Force { |
545 | get { return _force; } | 389 | get { return RawForce; } |
546 | set { | 390 | set { |
547 | _force = value; | 391 | RawForce = value; |
548 | // m_log.DebugFormat("{0}: Force = {1}", LogHeader, _force); | 392 | // m_log.DebugFormat("{0}: Force = {1}", LogHeader, _force); |
549 | PhysicsScene.TaintedObject("BSCharacter.SetForce", delegate() | 393 | PhysicsScene.TaintedObject("BSCharacter.SetForce", delegate() |
550 | { | 394 | { |
551 | DetailLog("{0},BSCharacter.setForce,taint,force={1}", LocalID, _force); | 395 | DetailLog("{0},BSCharacter.setForce,taint,force={1}", LocalID, RawForce); |
552 | if (PhysBody.HasPhysicalBody) | 396 | if (PhysBody.HasPhysicalBody) |
553 | PhysicsScene.PE.SetObjectForce(PhysBody, _force); | 397 | PhysicsScene.PE.SetObjectForce(PhysBody, RawForce); |
554 | }); | 398 | }); |
555 | } | 399 | } |
556 | } | 400 | } |
@@ -573,7 +417,7 @@ public sealed class BSCharacter : BSPhysObject | |||
573 | { | 417 | { |
574 | get | 418 | get |
575 | { | 419 | { |
576 | return m_targetVelocity; | 420 | return base.m_targetVelocity; |
577 | } | 421 | } |
578 | set | 422 | set |
579 | { | 423 | { |
@@ -583,51 +427,39 @@ public sealed class BSCharacter : BSPhysObject | |||
583 | if (_setAlwaysRun) | 427 | if (_setAlwaysRun) |
584 | targetVel *= new OMV.Vector3(BSParam.AvatarAlwaysRunFactor, BSParam.AvatarAlwaysRunFactor, 0f); | 428 | targetVel *= new OMV.Vector3(BSParam.AvatarAlwaysRunFactor, BSParam.AvatarAlwaysRunFactor, 0f); |
585 | 429 | ||
586 | PhysicsScene.TaintedObject("BSCharacter.setTargetVelocity", delegate() | 430 | if (m_moveActor != null) |
587 | { | 431 | m_moveActor.SetVelocityAndTarget(RawVelocity, targetVel, false /* inTaintTime */); |
588 | _velocityMotor.Reset(); | ||
589 | _velocityMotor.SetTarget(targetVel); | ||
590 | _velocityMotor.SetCurrent(_velocity); | ||
591 | _velocityMotor.Enabled = true; | ||
592 | }); | ||
593 | } | 432 | } |
594 | } | 433 | } |
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. | 434 | // Directly setting velocity means this is what the user really wants now. |
601 | public override OMV.Vector3 Velocity { | 435 | public override OMV.Vector3 Velocity { |
602 | get { return _velocity; } | 436 | get { return RawVelocity; } |
603 | set { | 437 | set { |
604 | _velocity = value; | 438 | RawVelocity = value; |
605 | // m_log.DebugFormat("{0}: set velocity = {1}", LogHeader, _velocity); | 439 | // m_log.DebugFormat("{0}: set velocity = {1}", LogHeader, RawVelocity); |
606 | PhysicsScene.TaintedObject("BSCharacter.setVelocity", delegate() | 440 | PhysicsScene.TaintedObject("BSCharacter.setVelocity", delegate() |
607 | { | 441 | { |
608 | _velocityMotor.Reset(); | 442 | if (m_moveActor != null) |
609 | _velocityMotor.SetCurrent(_velocity); | 443 | m_moveActor.SetVelocityAndTarget(RawVelocity, RawVelocity, true /* inTaintTime */); |
610 | _velocityMotor.SetTarget(_velocity); | ||
611 | _velocityMotor.Enabled = false; | ||
612 | 444 | ||
613 | DetailLog("{0},BSCharacter.setVelocity,taint,vel={1}", LocalID, _velocity); | 445 | DetailLog("{0},BSCharacter.setVelocity,taint,vel={1}", LocalID, RawVelocity); |
614 | ForceVelocity = _velocity; | 446 | ForceVelocity = RawVelocity; |
615 | }); | 447 | }); |
616 | } | 448 | } |
617 | } | 449 | } |
618 | public override OMV.Vector3 ForceVelocity { | 450 | public override OMV.Vector3 ForceVelocity { |
619 | get { return _velocity; } | 451 | get { return RawVelocity; } |
620 | set { | 452 | set { |
621 | PhysicsScene.AssertInTaintTime("BSCharacter.ForceVelocity"); | 453 | PhysicsScene.AssertInTaintTime("BSCharacter.ForceVelocity"); |
622 | 454 | ||
623 | _velocity = value; | 455 | RawVelocity = value; |
624 | PhysicsScene.PE.SetLinearVelocity(PhysBody, _velocity); | 456 | PhysicsScene.PE.SetLinearVelocity(PhysBody, RawVelocity); |
625 | PhysicsScene.PE.Activate(PhysBody, true); | 457 | PhysicsScene.PE.Activate(PhysBody, true); |
626 | } | 458 | } |
627 | } | 459 | } |
628 | public override OMV.Vector3 Torque { | 460 | public override OMV.Vector3 Torque { |
629 | get { return _torque; } | 461 | get { return RawTorque; } |
630 | set { _torque = value; | 462 | set { RawTorque = value; |
631 | } | 463 | } |
632 | } | 464 | } |
633 | public override float CollisionScore { | 465 | public override float CollisionScore { |
@@ -783,27 +615,6 @@ public sealed class BSCharacter : BSPhysObject | |||
783 | set { _PIDTau = value; } | 615 | set { _PIDTau = value; } |
784 | } | 616 | } |
785 | 617 | ||
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) | 618 | public override void AddForce(OMV.Vector3 force, bool pushforce) |
808 | { | 619 | { |
809 | // Since this force is being applied in only one step, make this a force per second. | 620 | // Since this force is being applied in only one step, make this a force per second. |
@@ -833,7 +644,7 @@ public sealed class BSCharacter : BSPhysObject | |||
833 | } | 644 | } |
834 | } | 645 | } |
835 | 646 | ||
836 | public override void AddAngularForce(OMV.Vector3 force, bool pushforce) { | 647 | public override void AddAngularForce(OMV.Vector3 force, bool pushforce, bool inTaintTime) { |
837 | } | 648 | } |
838 | public override void SetMomentum(OMV.Vector3 momentum) { | 649 | public override void SetMomentum(OMV.Vector3 momentum) { |
839 | } | 650 | } |
@@ -887,7 +698,7 @@ public sealed class BSCharacter : BSPhysObject | |||
887 | public override void UpdateProperties(EntityProperties entprop) | 698 | public override void UpdateProperties(EntityProperties entprop) |
888 | { | 699 | { |
889 | // Don't change position if standing on a stationary object. | 700 | // Don't change position if standing on a stationary object. |
890 | if (!_isStationaryStanding) | 701 | if (!IsStationary) |
891 | _position = entprop.Position; | 702 | _position = entprop.Position; |
892 | 703 | ||
893 | _orientation = entprop.Rotation; | 704 | _orientation = entprop.Rotation; |
@@ -896,8 +707,8 @@ public sealed class BSCharacter : BSPhysObject | |||
896 | // and will send agent updates to the clients if velocity changes by more than | 707 | // 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 | 708 | // 0.001m/s. Bullet introduces a lot of jitter in the velocity which causes many |
898 | // extra updates. | 709 | // extra updates. |
899 | if (!entprop.Velocity.ApproxEquals(_velocity, 0.1f)) | 710 | if (!entprop.Velocity.ApproxEquals(RawVelocity, 0.1f)) |
900 | _velocity = entprop.Velocity; | 711 | RawVelocity = entprop.Velocity; |
901 | 712 | ||
902 | _acceleration = entprop.Acceleration; | 713 | _acceleration = entprop.Acceleration; |
903 | _rotationalVelocity = entprop.RotationalVelocity; | 714 | _rotationalVelocity = entprop.RotationalVelocity; |
@@ -920,7 +731,7 @@ public sealed class BSCharacter : BSPhysObject | |||
920 | // base.RequestPhysicsterseUpdate(); | 731 | // base.RequestPhysicsterseUpdate(); |
921 | 732 | ||
922 | DetailLog("{0},BSCharacter.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}", | 733 | DetailLog("{0},BSCharacter.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}", |
923 | LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity); | 734 | LocalID, _position, _orientation, RawVelocity, _acceleration, _rotationalVelocity); |
924 | } | 735 | } |
925 | } | 736 | } |
926 | } | 737 | } |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs index 98ea833..64bf395 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,45 @@ 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 | // May be called at non-taint time as this just adds the actor to the action list and the real | ||
286 | // work is done during the simulation step. | ||
287 | // Note that, if the actor is already in the list and we are disabling same, the actor is just left | ||
288 | // in the list disabled. | ||
289 | public delegate BSActor CreateActor(); | ||
290 | public void EnableActor(bool enableActor, string actorName, CreateActor creator) | ||
291 | { | ||
292 | lock (PhysicalActors) | ||
293 | { | ||
294 | BSActor theActor; | ||
295 | if (PhysicalActors.TryGetActor(actorName, out theActor)) | ||
296 | { | ||
297 | // The actor already exists so just turn it on or off | ||
298 | theActor.Enabled = enableActor; | ||
299 | } | ||
300 | else | ||
301 | { | ||
302 | // The actor does not exist. If it should, create it. | ||
303 | if (enableActor) | ||
304 | { | ||
305 | theActor = creator(); | ||
306 | PhysicalActors.Add(actorName, theActor); | ||
307 | theActor.Enabled = true; | ||
308 | } | ||
309 | } | ||
310 | } | ||
311 | } | ||
241 | 312 | ||
242 | #region Collisions | 313 | #region Collisions |
243 | 314 | ||
@@ -255,7 +326,9 @@ public abstract class BSPhysObject : PhysicsActor | |||
255 | protected CollisionFlags CurrentCollisionFlags { get; set; } | 326 | protected CollisionFlags CurrentCollisionFlags { get; set; } |
256 | // On a collision, check the collider and remember if the last collider was moving | 327 | // 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) | 328 | // Used to modify the standing of avatars (avatars on stationary things stand still) |
258 | protected bool ColliderIsMoving; | 329 | public bool ColliderIsMoving; |
330 | // Used by BSCharacter to manage standing (and not slipping) | ||
331 | public bool IsStationary; | ||
259 | 332 | ||
260 | // Count of collisions for this object | 333 | // Count of collisions for this object |
261 | protected long CollisionAccumulation { get; set; } | 334 | protected long CollisionAccumulation { get; set; } |
@@ -293,7 +366,7 @@ public abstract class BSPhysObject : PhysicsActor | |||
293 | protected CollisionEventUpdate CollisionCollection; | 366 | protected CollisionEventUpdate CollisionCollection; |
294 | // Remember collisions from last tick for fancy collision based actions | 367 | // Remember collisions from last tick for fancy collision based actions |
295 | // (like a BSCharacter walking up stairs). | 368 | // (like a BSCharacter walking up stairs). |
296 | protected CollisionEventUpdate CollisionsLastTick; | 369 | public CollisionEventUpdate CollisionsLastTick; |
297 | 370 | ||
298 | // The simulation step is telling this object about a collision. | 371 | // The simulation step is telling this object about a collision. |
299 | // Return 'true' if a collision was processed and should be sent up. | 372 | // Return 'true' if a collision was processed and should be sent up. |
@@ -424,104 +497,6 @@ public abstract class BSPhysObject : PhysicsActor | |||
424 | 497 | ||
425 | public BSActorCollection PhysicalActors; | 498 | public BSActorCollection PhysicalActors; |
426 | 499 | ||
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 | 500 | // 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 | 501 | // different actors to modify the update before it is passed around |
527 | public delegate void PreUpdatePropertyAction(ref EntityProperties entprop); | 502 | public delegate void PreUpdatePropertyAction(ref EntityProperties entprop); |
@@ -533,46 +508,6 @@ public abstract class BSPhysObject : PhysicsActor | |||
533 | actions(ref entprop); | 508 | actions(ref entprop); |
534 | } | 509 | } |
535 | 510 | ||
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 | 511 | #endregion // Per Simulation Step actions |
577 | 512 | ||
578 | // High performance detailed logging routine used by the physical objects. | 513 | // 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..3423d2e 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,12 +89,13 @@ 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; |
102 | _isVolumeDetect = false; | 96 | _isVolumeDetect = false; |
103 | 97 | ||
98 | // We keep a handle to the vehicle actor so we can set vehicle parameters later. | ||
104 | VehicleActor = new BSDynamics(PhysicsScene, this, VehicleActorName); | 99 | VehicleActor = new BSDynamics(PhysicsScene, this, VehicleActorName); |
105 | PhysicalActors.Add(VehicleActorName, VehicleActor); | 100 | PhysicalActors.Add(VehicleActorName, VehicleActor); |
106 | 101 | ||
@@ -233,7 +228,7 @@ public class BSPrim : BSPhysObject | |||
233 | // Called at taint time! | 228 | // Called at taint time! |
234 | public override void ZeroMotion(bool inTaintTime) | 229 | public override void ZeroMotion(bool inTaintTime) |
235 | { | 230 | { |
236 | _velocity = OMV.Vector3.Zero; | 231 | RawVelocity = OMV.Vector3.Zero; |
237 | _acceleration = OMV.Vector3.Zero; | 232 | _acceleration = OMV.Vector3.Zero; |
238 | _rotationalVelocity = OMV.Vector3.Zero; | 233 | _rotationalVelocity = OMV.Vector3.Zero; |
239 | 234 | ||
@@ -270,19 +265,17 @@ public class BSPrim : BSPhysObject | |||
270 | if (axis.Z != 1) locking.Z = 0f; | 265 | if (axis.Z != 1) locking.Z = 0f; |
271 | LockedAxis = locking; | 266 | LockedAxis = locking; |
272 | 267 | ||
273 | if (LockedAxis != LockedAxisFree) | 268 | EnableActor(LockedAxis != LockedAxisFree, LockedAxisActorName, delegate() |
274 | { | 269 | { |
275 | PhysicsScene.TaintedObject("BSPrim.LockAngularMotion", delegate() | 270 | return new BSActorLockAxis(PhysicsScene, this, LockedAxisActorName); |
276 | { | 271 | }); |
277 | // If there is not already an axis locker, make one | 272 | |
278 | if (!PhysicalActors.HasActor(LockedAxisActorName)) | 273 | // Update parameters so the new actor's Refresh() action is called at the right time. |
279 | { | 274 | PhysicsScene.TaintedObject("BSPrim.LockAngularMotion", delegate() |
280 | DetailLog("{0},BSPrim.LockAngularMotion,taint,registeringLockAxisActor", LocalID); | 275 | { |
281 | PhysicalActors.Add(LockedAxisActorName, new BSActorLockAxis(PhysicsScene, this, LockedAxisActorName)); | 276 | UpdatePhysicalParameters(); |
282 | } | 277 | }); |
283 | UpdatePhysicalParameters(); | 278 | |
284 | }); | ||
285 | } | ||
286 | return; | 279 | return; |
287 | } | 280 | } |
288 | 281 | ||
@@ -407,9 +400,9 @@ public class BSPrim : BSPhysObject | |||
407 | ZeroMotion(inTaintTime); | 400 | ZeroMotion(inTaintTime); |
408 | ret = true; | 401 | ret = true; |
409 | } | 402 | } |
410 | if (_velocity.LengthSquared() > BSParam.MaxLinearVelocity) | 403 | if (RawVelocity.LengthSquared() > BSParam.MaxLinearVelocity) |
411 | { | 404 | { |
412 | _velocity = Util.ClampV(_velocity, BSParam.MaxLinearVelocity); | 405 | RawVelocity = Util.ClampV(RawVelocity, BSParam.MaxLinearVelocity); |
413 | ret = true; | 406 | ret = true; |
414 | } | 407 | } |
415 | if (_rotationalVelocity.LengthSquared() > BSParam.MaxAngularVelocitySquared) | 408 | if (_rotationalVelocity.LengthSquared() > BSParam.MaxAngularVelocitySquared) |
@@ -506,48 +499,25 @@ public class BSPrim : BSPhysObject | |||
506 | } | 499 | } |
507 | 500 | ||
508 | public override OMV.Vector3 Force { | 501 | public override OMV.Vector3 Force { |
509 | get { return _force; } | 502 | get { return RawForce; } |
510 | set { | 503 | set { |
511 | _force = value; | 504 | RawForce = value; |
512 | if (_force != OMV.Vector3.Zero) | 505 | EnableActor(RawForce != OMV.Vector3.Zero, SetForceActorName, delegate() |
513 | { | 506 | { |
514 | // If the force is non-zero, it must be reapplied each tick because | 507 | return new BSActorSetForce(PhysicsScene, this, SetForceActorName); |
515 | // Bullet clears the forces applied last frame. | 508 | }); |
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 | { | ||
536 | UnRegisterPreStepAction("BSPrim.setForce", LocalID); | ||
537 | } | ||
538 | } | 509 | } |
539 | } | 510 | } |
540 | 511 | ||
541 | public override int VehicleType { | 512 | public override int VehicleType { |
542 | get { | 513 | get { |
543 | return (int)VehicleActor.Type; // if we are a vehicle, return that type | 514 | return (int)VehicleActor.Type; |
544 | } | 515 | } |
545 | set { | 516 | set { |
546 | Vehicle type = (Vehicle)value; | 517 | Vehicle type = (Vehicle)value; |
547 | 518 | ||
548 | PhysicsScene.TaintedObject("setVehicleType", delegate() | 519 | PhysicsScene.TaintedObject("setVehicleType", delegate() |
549 | { | 520 | { |
550 | // Done at taint time so we're sure the physics engine is not using the variables | ||
551 | // Vehicle code changes the parameters for this vehicle type. | 521 | // Vehicle code changes the parameters for this vehicle type. |
552 | VehicleActor.ProcessTypeChange(type); | 522 | VehicleActor.ProcessTypeChange(type); |
553 | ActivateIfPhysical(false); | 523 | ActivateIfPhysical(false); |
@@ -670,63 +640,40 @@ 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 | EnableActor(RawTorque != OMV.Vector3.Zero, SetTorqueActorName, delegate() |
708 | { | ||
709 | // If the torque is non-zero, it must be reapplied each tick because | ||
710 | // Bullet clears the forces applied last frame. | ||
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 | { | 673 | { |
727 | UnRegisterPreStepAction("BSPrim.setTorque", LocalID); | 674 | return new BSActorSetTorque(PhysicsScene, this, SetTorqueActorName); |
728 | } | 675 | }); |
729 | // DetailLog("{0},BSPrim.SetTorque,call,torque={1}", LocalID, _torque); | 676 | DetailLog("{0},BSPrim.SetTorque,call,torque={1}", LocalID, RawTorque); |
730 | } | 677 | } |
731 | } | 678 | } |
732 | public override OMV.Vector3 Acceleration { | 679 | public override OMV.Vector3 Acceleration { |
@@ -839,7 +786,6 @@ public class BSPrim : BSPhysObject | |||
839 | MakeDynamic(IsStatic); | 786 | MakeDynamic(IsStatic); |
840 | 787 | ||
841 | // Update vehicle specific parameters (after MakeDynamic() so can change physical parameters) | 788 | // Update vehicle specific parameters (after MakeDynamic() so can change physical parameters) |
842 | VehicleActor.Refresh(); | ||
843 | PhysicalActors.Refresh(); | 789 | PhysicalActors.Refresh(); |
844 | 790 | ||
845 | // Arrange for collision events if the simulator wants them | 791 | // Arrange for collision events if the simulator wants them |
@@ -909,7 +855,7 @@ public class BSPrim : BSPhysObject | |||
909 | 855 | ||
910 | // For good measure, make sure the transform is set through to the motion state | 856 | // For good measure, make sure the transform is set through to the motion state |
911 | ForcePosition = _position; | 857 | ForcePosition = _position; |
912 | ForceVelocity = _velocity; | 858 | ForceVelocity = RawVelocity; |
913 | ForceRotationalVelocity = _rotationalVelocity; | 859 | ForceRotationalVelocity = _rotationalVelocity; |
914 | 860 | ||
915 | // A dynamic object has mass | 861 | // A dynamic object has mass |
@@ -966,15 +912,6 @@ public class BSPrim : BSPhysObject | |||
966 | } | 912 | } |
967 | } | 913 | } |
968 | 914 | ||
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. | 915 | // Turn on or off the flag controlling whether collision events are returned to the simulator. |
979 | private void EnableCollisions(bool wantsCollisionEvents) | 916 | private void EnableCollisions(bool wantsCollisionEvents) |
980 | { | 917 | { |
@@ -1096,78 +1033,13 @@ public class BSPrim : BSPhysObject | |||
1096 | } | 1033 | } |
1097 | } | 1034 | } |
1098 | 1035 | ||
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 { | 1036 | public override bool PIDActive { |
1111 | set { | 1037 | set { |
1112 | if (value) | 1038 | base.MoveToTargetActive = value; |
1039 | EnableActor(MoveToTargetActive, MoveToTargetActorName, delegate() | ||
1113 | { | 1040 | { |
1114 | // We're taking over after this. | 1041 | return new BSActorMoveToTarget(PhysicsScene, this, MoveToTargetActorName); |
1115 | ZeroMotion(true); | 1042 | }); |
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 | { | ||
1168 | // Stop any targetting | ||
1169 | UnRegisterPreStepAction("BSPrim.PIDTarget", LocalID); | ||
1170 | } | ||
1171 | } | 1043 | } |
1172 | } | 1044 | } |
1173 | 1045 | ||
@@ -1175,88 +1047,14 @@ public class BSPrim : BSPhysObject | |||
1175 | // Hover Height will override MoveTo target's Z | 1047 | // Hover Height will override MoveTo target's Z |
1176 | public override bool PIDHoverActive { | 1048 | public override bool PIDHoverActive { |
1177 | set { | 1049 | set { |
1178 | if (value) | 1050 | base.HoverActive = value; |
1051 | EnableActor(HoverActive, HoverActorName, delegate() | ||
1179 | { | 1052 | { |
1180 | // Turning the target on | 1053 | return new BSActorHover(PhysicsScene, this, HoverActorName); |
1181 | _hoverMotor = new BSFMotor("BSPrim.Hover", | 1054 | }); |
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 | { | ||
1213 | UnRegisterPreStepAction("BSPrim.Hover", LocalID); | ||
1214 | } | ||
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 | } | 1055 | } |
1250 | return ret; | ||
1251 | } | 1056 | } |
1252 | 1057 | ||
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) { | 1058 | public override void AddForce(OMV.Vector3 force, bool pushforce) { |
1261 | // Per documentation, max force is limited. | 1059 | // Per documentation, max force is limited. |
1262 | OMV.Vector3 addForce = Util.ClampV(force, BSParam.MaxAddForceMagnitude); | 1060 | OMV.Vector3 addForce = Util.ClampV(force, BSParam.MaxAddForceMagnitude); |
@@ -1324,10 +1122,8 @@ public class BSPrim : BSPhysObject | |||
1324 | } | 1122 | } |
1325 | } | 1123 | } |
1326 | 1124 | ||
1327 | public override void AddAngularForce(OMV.Vector3 force, bool pushforce) { | 1125 | // BSPhysObject.AddAngularForce() |
1328 | AddAngularForce(force, pushforce, false); | 1126 | public override void AddAngularForce(OMV.Vector3 force, bool pushforce, bool inTaintTime) |
1329 | } | ||
1330 | public void AddAngularForce(OMV.Vector3 force, bool pushforce, bool inTaintTime) | ||
1331 | { | 1127 | { |
1332 | if (force.IsFinite()) | 1128 | if (force.IsFinite()) |
1333 | { | 1129 | { |
@@ -1661,7 +1457,7 @@ public class BSPrim : BSPhysObject | |||
1661 | { | 1457 | { |
1662 | // Create the correct physical representation for this type of object. | 1458 | // Create the correct physical representation for this type of object. |
1663 | // Updates base.PhysBody and base.PhysShape with the new information. | 1459 | // Updates base.PhysBody and base.PhysShape with the new information. |
1664 | // Ignore 'forceRebuild'. This routine makes the right choices and changes of necessary. | 1460 | // Ignore 'forceRebuild'. 'GetBodyAndShape' makes the right choices and changes of necessary. |
1665 | PhysicsScene.Shapes.GetBodyAndShape(false /*forceRebuild */, PhysicsScene.World, this, null, delegate(BulletBody dBody) | 1461 | PhysicsScene.Shapes.GetBodyAndShape(false /*forceRebuild */, PhysicsScene.World, this, null, delegate(BulletBody dBody) |
1666 | { | 1462 | { |
1667 | // Called if the current prim body is about to be destroyed. | 1463 | // Called if the current prim body is about to be destroyed. |
@@ -1675,9 +1471,9 @@ public class BSPrim : BSPhysObject | |||
1675 | return; | 1471 | return; |
1676 | } | 1472 | } |
1677 | 1473 | ||
1474 | // Called at taint-time | ||
1678 | protected virtual void RemoveBodyDependencies() | 1475 | protected virtual void RemoveBodyDependencies() |
1679 | { | 1476 | { |
1680 | VehicleActor.RemoveBodyDependencies(); | ||
1681 | PhysicalActors.RemoveBodyDependencies(); | 1477 | PhysicalActors.RemoveBodyDependencies(); |
1682 | } | 1478 | } |
1683 | 1479 | ||
@@ -1685,6 +1481,7 @@ public class BSPrim : BSPhysObject | |||
1685 | // the world that things have changed. | 1481 | // the world that things have changed. |
1686 | public override void UpdateProperties(EntityProperties entprop) | 1482 | public override void UpdateProperties(EntityProperties entprop) |
1687 | { | 1483 | { |
1484 | // Let anyone (like the actors) modify the updated properties before they are pushed into the object and the simulator. | ||
1688 | TriggerPreUpdatePropertyAction(ref entprop); | 1485 | TriggerPreUpdatePropertyAction(ref entprop); |
1689 | 1486 | ||
1690 | // DetailLog("{0},BSPrim.UpdateProperties,entry,entprop={1}", LocalID, entprop); // DEBUG DEBUG | 1487 | // DetailLog("{0},BSPrim.UpdateProperties,entry,entprop={1}", LocalID, entprop); // DEBUG DEBUG |
@@ -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 | } |
@@ -1717,16 +1514,8 @@ public class BSPrim : BSPhysObject | |||
1717 | LastEntityProperties = CurrentEntityProperties; | 1514 | LastEntityProperties = CurrentEntityProperties; |
1718 | CurrentEntityProperties = entprop; | 1515 | CurrentEntityProperties = entprop; |
1719 | 1516 | ||
1517 | // Note that BSPrim can be overloaded by BSPrimLinkable which controls updates from root and children prims. | ||
1720 | base.RequestPhysicsterseUpdate(); | 1518 | base.RequestPhysicsterseUpdate(); |
1721 | /* | ||
1722 | else | ||
1723 | { | ||
1724 | // For debugging, report the movement of children | ||
1725 | DetailLog("{0},BSPrim.UpdateProperties,child,pos={1},orient={2},vel={3},accel={4},rotVel={5}", | ||
1726 | LocalID, entprop.Position, entprop.Rotation, entprop.Velocity, | ||
1727 | entprop.Acceleration, entprop.RotationalVelocity); | ||
1728 | } | ||
1729 | */ | ||
1730 | } | 1519 | } |
1731 | } | 1520 | } |
1732 | } | 1521 | } |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrimLinkable.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrimLinkable.cs index d65d407..28242d4 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrimLinkable.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrimLinkable.cs | |||
@@ -163,6 +163,15 @@ public class BSPrimLinkable : BSPrimDisplaced | |||
163 | // TODO: this will have to change when linksets are articulated. | 163 | // TODO: this will have to change when linksets are articulated. |
164 | base.UpdateProperties(entprop); | 164 | base.UpdateProperties(entprop); |
165 | } | 165 | } |
166 | /* | ||
167 | else | ||
168 | { | ||
169 | // For debugging, report the movement of children | ||
170 | DetailLog("{0},BSPrim.UpdateProperties,child,pos={1},orient={2},vel={3},accel={4},rotVel={5}", | ||
171 | LocalID, entprop.Position, entprop.Rotation, entprop.Velocity, | ||
172 | entprop.Acceleration, entprop.RotationalVelocity); | ||
173 | } | ||
174 | */ | ||
166 | // The linkset might like to know about changing locations | 175 | // The linkset might like to know about changing locations |
167 | Linkset.UpdateProperties(UpdatedProperties.EntPropUpdates, this); | 176 | Linkset.UpdateProperties(UpdatedProperties.EntPropUpdates, this); |
168 | } | 177 | } |
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 | |||
diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianPresenceServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianPresenceServiceConnector.cs index 854bea4..7bb06fb 100644 --- a/OpenSim/Services/Connectors/SimianGrid/SimianPresenceServiceConnector.cs +++ b/OpenSim/Services/Connectors/SimianGrid/SimianPresenceServiceConnector.cs | |||
@@ -137,10 +137,11 @@ namespace OpenSim.Services.Connectors.SimianGrid | |||
137 | userID, sessionID, secureSessionID); | 137 | userID, sessionID, secureSessionID); |
138 | 138 | ||
139 | NameValueCollection requestArgs = new NameValueCollection | 139 | NameValueCollection requestArgs = new NameValueCollection |
140 | { | 140 | { |
141 | { "RequestMethod", "AddSession" }, | 141 | { "RequestMethod", "AddSession" }, |
142 | { "UserID", userID.ToString() } | 142 | { "UserID", userID.ToString() } |
143 | }; | 143 | }; |
144 | |||
144 | if (sessionID != UUID.Zero) | 145 | if (sessionID != UUID.Zero) |
145 | { | 146 | { |
146 | requestArgs["SessionID"] = sessionID.ToString(); | 147 | requestArgs["SessionID"] = sessionID.ToString(); |
@@ -158,13 +159,13 @@ namespace OpenSim.Services.Connectors.SimianGrid | |||
158 | 159 | ||
159 | public bool LogoutAgent(UUID sessionID) | 160 | public bool LogoutAgent(UUID sessionID) |
160 | { | 161 | { |
161 | // m_log.InfoFormat("[SIMIAN PRESENCE CONNECTOR]: Logout requested for agent with sessionID " + sessionID); | 162 | // m_log.InfoFormat("[SIMIAN PRESENCE CONNECTOR]: Logout requested for agent with sessionID " + sessionID); |
162 | 163 | ||
163 | NameValueCollection requestArgs = new NameValueCollection | 164 | NameValueCollection requestArgs = new NameValueCollection |
164 | { | 165 | { |
165 | { "RequestMethod", "RemoveSession" }, | 166 | { "RequestMethod", "RemoveSession" }, |
166 | { "SessionID", sessionID.ToString() } | 167 | { "SessionID", sessionID.ToString() } |
167 | }; | 168 | }; |
168 | 169 | ||
169 | OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); | 170 | OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); |
170 | bool success = response["Success"].AsBoolean(); | 171 | bool success = response["Success"].AsBoolean(); |
@@ -177,13 +178,13 @@ namespace OpenSim.Services.Connectors.SimianGrid | |||
177 | 178 | ||
178 | public bool LogoutRegionAgents(UUID regionID) | 179 | public bool LogoutRegionAgents(UUID regionID) |
179 | { | 180 | { |
180 | // m_log.InfoFormat("[SIMIAN PRESENCE CONNECTOR]: Logout requested for all agents in region " + regionID); | 181 | // m_log.InfoFormat("[SIMIAN PRESENCE CONNECTOR]: Logout requested for all agents in region " + regionID); |
181 | 182 | ||
182 | NameValueCollection requestArgs = new NameValueCollection | 183 | NameValueCollection requestArgs = new NameValueCollection |
183 | { | 184 | { |
184 | { "RequestMethod", "RemoveSessions" }, | 185 | { "RequestMethod", "RemoveSessions" }, |
185 | { "SceneID", regionID.ToString() } | 186 | { "SceneID", regionID.ToString() } |
186 | }; | 187 | }; |
187 | 188 | ||
188 | OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); | 189 | OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); |
189 | bool success = response["Success"].AsBoolean(); | 190 | bool success = response["Success"].AsBoolean(); |
@@ -202,49 +203,46 @@ namespace OpenSim.Services.Connectors.SimianGrid | |||
202 | 203 | ||
203 | public PresenceInfo GetAgent(UUID sessionID) | 204 | public PresenceInfo GetAgent(UUID sessionID) |
204 | { | 205 | { |
205 | // m_log.DebugFormat("[SIMIAN PRESENCE CONNECTOR]: Requesting session data for agent with sessionID " + sessionID); | 206 | OSDMap sessionResponse = GetSessionDataFromSessionID(sessionID); |
206 | 207 | if (sessionResponse == null) | |
207 | NameValueCollection requestArgs = new NameValueCollection | ||
208 | { | ||
209 | { "RequestMethod", "GetSession" }, | ||
210 | { "SessionID", sessionID.ToString() } | ||
211 | }; | ||
212 | |||
213 | OSDMap sessionResponse = WebUtil.PostToService(m_serverUrl, requestArgs); | ||
214 | if (sessionResponse["Success"].AsBoolean()) | ||
215 | { | 208 | { |
216 | UUID userID = sessionResponse["UserID"].AsUUID(); | 209 | m_log.WarnFormat("[SIMIAN PRESENCE CONNECTOR]: Failed to retrieve session {0}: {1}",sessionID.ToString(),sessionResponse["Message"].AsString()); |
217 | m_log.DebugFormat("[SIMIAN PRESENCE CONNECTOR]: Requesting user data for " + userID); | 210 | return null; |
218 | |||
219 | requestArgs = new NameValueCollection | ||
220 | { | ||
221 | { "RequestMethod", "GetUser" }, | ||
222 | { "UserID", userID.ToString() } | ||
223 | }; | ||
224 | |||
225 | OSDMap userResponse = WebUtil.PostToService(m_serverUrl, requestArgs); | ||
226 | if (userResponse["Success"].AsBoolean()) | ||
227 | return ResponseToPresenceInfo(sessionResponse, userResponse); | ||
228 | else | ||
229 | m_log.Warn("[SIMIAN PRESENCE CONNECTOR]: Failed to retrieve user data for " + userID + ": " + userResponse["Message"].AsString()); | ||
230 | } | 211 | } |
231 | else | 212 | |
213 | UUID userID = sessionResponse["UserID"].AsUUID(); | ||
214 | OSDMap userResponse = GetUserData(userID); | ||
215 | if (userResponse == null) | ||
232 | { | 216 | { |
233 | m_log.Warn("[SIMIAN PRESENCE CONNECTOR]: Failed to retrieve session " + sessionID + ": " + sessionResponse["Message"].AsString()); | 217 | m_log.WarnFormat("[SIMIAN PRESENCE CONNECTOR]: Failed to retrieve user data for {0}: {1}",userID.ToString(),userResponse["Message"].AsString()); |
218 | return null; | ||
234 | } | 219 | } |
235 | 220 | ||
236 | return null; | 221 | return ResponseToPresenceInfo(sessionResponse); |
237 | } | 222 | } |
238 | 223 | ||
239 | public PresenceInfo[] GetAgents(string[] userIDs) | 224 | public PresenceInfo[] GetAgents(string[] userIDs) |
240 | { | 225 | { |
241 | List<PresenceInfo> presences = new List<PresenceInfo>(userIDs.Length); | 226 | List<PresenceInfo> presences = new List<PresenceInfo>(); |
242 | 227 | ||
243 | for (int i = 0; i < userIDs.Length; i++) | 228 | NameValueCollection requestArgs = new NameValueCollection |
229 | { | ||
230 | { "RequestMethod", "GetSessions" }, | ||
231 | { "UserIDList", String.Join(",",userIDs) } | ||
232 | }; | ||
233 | |||
234 | OSDMap sessionListResponse = WebUtil.PostToService(m_serverUrl, requestArgs); | ||
235 | if (! sessionListResponse["Success"].AsBoolean()) | ||
244 | { | 236 | { |
245 | UUID userID; | 237 | m_log.WarnFormat("[SIMIAN PRESENCE CONNECTOR]: Failed to retrieve sessions: {0}",sessionListResponse["Message"].AsString()); |
246 | if (UUID.TryParse(userIDs[i], out userID) && userID != UUID.Zero) | 238 | return null; |
247 | presences.AddRange(GetSessions(userID)); | 239 | } |
240 | |||
241 | OSDArray sessionList = sessionListResponse["Sessions"] as OSDArray; | ||
242 | for (int i = 0; i < sessionList.Count; i++) | ||
243 | { | ||
244 | OSDMap sessionInfo = sessionList[i] as OSDMap; | ||
245 | presences.Add(ResponseToPresenceInfo(sessionInfo)); | ||
248 | } | 246 | } |
249 | 247 | ||
250 | return presences.ToArray(); | 248 | return presences.ToArray(); |
@@ -262,7 +260,7 @@ namespace OpenSim.Services.Connectors.SimianGrid | |||
262 | 260 | ||
263 | public bool LoggedOut(string userID, UUID sessionID, UUID regionID, Vector3 lastPosition, Vector3 lastLookAt) | 261 | public bool LoggedOut(string userID, UUID sessionID, UUID regionID, Vector3 lastPosition, Vector3 lastLookAt) |
264 | { | 262 | { |
265 | // m_log.DebugFormat("[SIMIAN PRESENCE CONNECTOR]: Logging out user " + userID); | 263 | // m_log.DebugFormat("[SIMIAN PRESENCE CONNECTOR]: Logging out user " + userID); |
266 | 264 | ||
267 | // Remove the session to mark this user offline | 265 | // Remove the session to mark this user offline |
268 | if (!LogoutAgent(sessionID)) | 266 | if (!LogoutAgent(sessionID)) |
@@ -270,11 +268,11 @@ namespace OpenSim.Services.Connectors.SimianGrid | |||
270 | 268 | ||
271 | // Save our last position as user data | 269 | // Save our last position as user data |
272 | NameValueCollection requestArgs = new NameValueCollection | 270 | NameValueCollection requestArgs = new NameValueCollection |
273 | { | 271 | { |
274 | { "RequestMethod", "AddUserData" }, | 272 | { "RequestMethod", "AddUserData" }, |
275 | { "UserID", userID.ToString() }, | 273 | { "UserID", userID.ToString() }, |
276 | { "LastLocation", SerializeLocation(regionID, lastPosition, lastLookAt) } | 274 | { "LastLocation", SerializeLocation(regionID, lastPosition, lastLookAt) } |
277 | }; | 275 | }; |
278 | 276 | ||
279 | OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); | 277 | OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); |
280 | bool success = response["Success"].AsBoolean(); | 278 | bool success = response["Success"].AsBoolean(); |
@@ -287,14 +285,14 @@ namespace OpenSim.Services.Connectors.SimianGrid | |||
287 | 285 | ||
288 | public bool SetHome(string userID, UUID regionID, Vector3 position, Vector3 lookAt) | 286 | public bool SetHome(string userID, UUID regionID, Vector3 position, Vector3 lookAt) |
289 | { | 287 | { |
290 | // m_log.DebugFormat("[SIMIAN PRESENCE CONNECTOR]: Setting home location for user " + userID); | 288 | // m_log.DebugFormat("[SIMIAN PRESENCE CONNECTOR]: Setting home location for user " + userID); |
291 | 289 | ||
292 | NameValueCollection requestArgs = new NameValueCollection | 290 | NameValueCollection requestArgs = new NameValueCollection |
293 | { | 291 | { |
294 | { "RequestMethod", "AddUserData" }, | 292 | { "RequestMethod", "AddUserData" }, |
295 | { "UserID", userID.ToString() }, | 293 | { "UserID", userID.ToString() }, |
296 | { "HomeLocation", SerializeLocation(regionID, position, lookAt) } | 294 | { "HomeLocation", SerializeLocation(regionID, position, lookAt) } |
297 | }; | 295 | }; |
298 | 296 | ||
299 | OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); | 297 | OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); |
300 | bool success = response["Success"].AsBoolean(); | 298 | bool success = response["Success"].AsBoolean(); |
@@ -312,23 +310,14 @@ namespace OpenSim.Services.Connectors.SimianGrid | |||
312 | 310 | ||
313 | public GridUserInfo GetGridUserInfo(string user) | 311 | public GridUserInfo GetGridUserInfo(string user) |
314 | { | 312 | { |
315 | // m_log.DebugFormat("[SIMIAN PRESENCE CONNECTOR]: Requesting session data for agent " + user); | 313 | // m_log.DebugFormat("[SIMIAN PRESENCE CONNECTOR]: Requesting session data for agent " + user); |
316 | 314 | ||
317 | UUID userID = new UUID(user); | 315 | UUID userID = new UUID(user); |
318 | // m_log.DebugFormat("[SIMIAN PRESENCE CONNECTOR]: Requesting user data for " + userID); | 316 | OSDMap userResponse = GetUserData(userID); |
319 | 317 | if (userResponse != null) | |
320 | NameValueCollection requestArgs = new NameValueCollection | ||
321 | { | ||
322 | { "RequestMethod", "GetUser" }, | ||
323 | { "UserID", userID.ToString() } | ||
324 | }; | ||
325 | |||
326 | OSDMap userResponse = WebUtil.PostToService(m_serverUrl, requestArgs); | ||
327 | if (userResponse["Success"].AsBoolean()) | ||
328 | return ResponseToGridUserInfo(userResponse); | 318 | return ResponseToGridUserInfo(userResponse); |
329 | else | ||
330 | m_log.Warn("[SIMIAN PRESENCE CONNECTOR]: Failed to retrieve user data for " + userID + ": " + userResponse["Message"].AsString()); | ||
331 | 319 | ||
320 | m_log.WarnFormat("[SIMIAN PRESENCE CONNECTOR]: Failed to retrieve user data for {0}: {1}",userID,userResponse["Message"].AsString()); | ||
332 | return null; | 321 | return null; |
333 | } | 322 | } |
334 | 323 | ||
@@ -338,65 +327,49 @@ namespace OpenSim.Services.Connectors.SimianGrid | |||
338 | 327 | ||
339 | private OSDMap GetUserData(UUID userID) | 328 | private OSDMap GetUserData(UUID userID) |
340 | { | 329 | { |
341 | // m_log.DebugFormat("[SIMIAN PRESENCE CONNECTOR]: Requesting user data for " + userID); | 330 | // m_log.DebugFormat("[SIMIAN PRESENCE CONNECTOR]: Requesting user data for " + userID); |
342 | 331 | ||
343 | NameValueCollection requestArgs = new NameValueCollection | 332 | NameValueCollection requestArgs = new NameValueCollection |
344 | { | 333 | { |
345 | { "RequestMethod", "GetUser" }, | 334 | { "RequestMethod", "GetUser" }, |
346 | { "UserID", userID.ToString() } | 335 | { "UserID", userID.ToString() } |
347 | }; | 336 | }; |
348 | 337 | ||
349 | OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); | 338 | OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); |
350 | if (response["Success"].AsBoolean() && response["User"] is OSDMap) | 339 | if (response["Success"].AsBoolean() && response["User"] is OSDMap) |
351 | return response; | 340 | return response; |
352 | else | ||
353 | m_log.Warn("[SIMIAN PRESENCE CONNECTOR]: Failed to retrieve user data for " + userID + ": " + response["Message"].AsString()); | ||
354 | 341 | ||
342 | m_log.WarnFormat("[SIMIAN PRESENCE CONNECTOR]: Failed to retrieve user data for {0}; {1}",userID.ToString(),response["Message"].AsString()); | ||
355 | return null; | 343 | return null; |
356 | } | 344 | } |
357 | 345 | ||
358 | private List<PresenceInfo> GetSessions(UUID userID) | 346 | private OSDMap GetSessionDataFromSessionID(UUID sessionID) |
359 | { | 347 | { |
360 | List<PresenceInfo> presences = new List<PresenceInfo>(1); | 348 | NameValueCollection requestArgs = new NameValueCollection |
361 | |||
362 | OSDMap userResponse = GetUserData(userID); | ||
363 | if (userResponse != null) | ||
364 | { | ||
365 | // m_log.DebugFormat("[SIMIAN PRESENCE CONNECTOR]: Requesting sessions for " + userID); | ||
366 | |||
367 | NameValueCollection requestArgs = new NameValueCollection | ||
368 | { | 349 | { |
369 | { "RequestMethod", "GetSession" }, | 350 | { "RequestMethod", "GetSession" }, |
370 | { "UserID", userID.ToString() } | 351 | { "SessionID", sessionID.ToString() } |
371 | }; | 352 | }; |
372 | 353 | ||
373 | OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); | 354 | OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); |
374 | if (response["Success"].AsBoolean()) | 355 | if (response["Success"].AsBoolean()) |
375 | { | 356 | return response; |
376 | PresenceInfo presence = ResponseToPresenceInfo(response, userResponse); | ||
377 | if (presence != null) | ||
378 | presences.Add(presence); | ||
379 | } | ||
380 | // else | ||
381 | // { | ||
382 | // m_log.Debug("[SIMIAN PRESENCE CONNECTOR]: No session returned for " + userID + ": " + response["Message"].AsString()); | ||
383 | // } | ||
384 | } | ||
385 | 357 | ||
386 | return presences; | 358 | m_log.WarnFormat("[SIMIAN PRESENCE CONNECTOR]: Failed to retrieve session data for {0}; {1}",sessionID.ToString(),response["Message"].AsString()); |
359 | return null; | ||
387 | } | 360 | } |
388 | 361 | ||
389 | private bool UpdateSession(UUID sessionID, UUID regionID, Vector3 lastPosition, Vector3 lastLookAt) | 362 | private bool UpdateSession(UUID sessionID, UUID regionID, Vector3 lastPosition, Vector3 lastLookAt) |
390 | { | 363 | { |
391 | // Save our current location as session data | 364 | // Save our current location as session data |
392 | NameValueCollection requestArgs = new NameValueCollection | 365 | NameValueCollection requestArgs = new NameValueCollection |
393 | { | 366 | { |
394 | { "RequestMethod", "UpdateSession" }, | 367 | { "RequestMethod", "UpdateSession" }, |
395 | { "SessionID", sessionID.ToString() }, | 368 | { "SessionID", sessionID.ToString() }, |
396 | { "SceneID", regionID.ToString() }, | 369 | { "SceneID", regionID.ToString() }, |
397 | { "ScenePosition", lastPosition.ToString() }, | 370 | { "ScenePosition", lastPosition.ToString() }, |
398 | { "SceneLookAt", lastLookAt.ToString() } | 371 | { "SceneLookAt", lastLookAt.ToString() } |
399 | }; | 372 | }; |
400 | 373 | ||
401 | OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); | 374 | OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); |
402 | bool success = response["Success"].AsBoolean(); | 375 | bool success = response["Success"].AsBoolean(); |
@@ -407,7 +380,7 @@ namespace OpenSim.Services.Connectors.SimianGrid | |||
407 | return success; | 380 | return success; |
408 | } | 381 | } |
409 | 382 | ||
410 | private PresenceInfo ResponseToPresenceInfo(OSDMap sessionResponse, OSDMap userResponse) | 383 | private PresenceInfo ResponseToPresenceInfo(OSDMap sessionResponse) |
411 | { | 384 | { |
412 | if (sessionResponse == null) | 385 | if (sessionResponse == null) |
413 | return null; | 386 | return null; |