diff options
Diffstat (limited to 'OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs')
-rw-r--r-- | OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs | 538 |
1 files changed, 269 insertions, 269 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index e2f7af9..2a52e01 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs | |||
@@ -28,62 +28,46 @@ using System; | |||
28 | using System.Collections.Generic; | 28 | using System.Collections.Generic; |
29 | using System.Reflection; | 29 | using System.Reflection; |
30 | using log4net; | 30 | using log4net; |
31 | using OpenMetaverse; | 31 | using OMV = OpenMetaverse; |
32 | using OpenSim.Framework; | 32 | using OpenSim.Framework; |
33 | using OpenSim.Region.Physics.Manager; | 33 | using OpenSim.Region.Physics.Manager; |
34 | 34 | ||
35 | namespace OpenSim.Region.Physics.BulletSPlugin | 35 | namespace OpenSim.Region.Physics.BulletSPlugin |
36 | { | 36 | { |
37 | public class BSCharacter : PhysicsActor | 37 | public class BSCharacter : BSPhysObject |
38 | { | 38 | { |
39 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 39 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
40 | private static readonly string LogHeader = "[BULLETS CHAR]"; | 40 | private static readonly string LogHeader = "[BULLETS CHAR]"; |
41 | 41 | ||
42 | private BSScene _scene; | ||
43 | public BSScene Scene { get { return _scene; } } | ||
44 | private String _avName; | ||
45 | // private bool _stopped; | 42 | // private bool _stopped; |
46 | private Vector3 _size; | 43 | private OMV.Vector3 _size; |
47 | private Vector3 _scale; | 44 | private OMV.Vector3 _scale; |
48 | private PrimitiveBaseShape _pbs; | 45 | private PrimitiveBaseShape _pbs; |
49 | private uint _localID = 0; | ||
50 | private bool _grabbed; | 46 | private bool _grabbed; |
51 | private bool _selected; | 47 | private bool _selected; |
52 | private Vector3 _position; | 48 | private OMV.Vector3 _position; |
53 | private float _mass; | 49 | private float _mass; |
54 | public float _density; | 50 | private float _avatarDensity; |
55 | public float _avatarVolume; | 51 | private float _avatarVolume; |
56 | private Vector3 _force; | 52 | private OMV.Vector3 _force; |
57 | private Vector3 _velocity; | 53 | private OMV.Vector3 _velocity; |
58 | private Vector3 _torque; | 54 | private OMV.Vector3 _torque; |
59 | private float _collisionScore; | 55 | private float _collisionScore; |
60 | private Vector3 _acceleration; | 56 | private OMV.Vector3 _acceleration; |
61 | private Quaternion _orientation; | 57 | private OMV.Quaternion _orientation; |
62 | private int _physicsActorType; | 58 | private int _physicsActorType; |
63 | private bool _isPhysical; | 59 | private bool _isPhysical; |
64 | private bool _flying; | 60 | private bool _flying; |
65 | private bool _setAlwaysRun; | 61 | private bool _setAlwaysRun; |
66 | private bool _throttleUpdates; | 62 | private bool _throttleUpdates; |
67 | private bool _isColliding; | 63 | private bool _isColliding; |
68 | private long _collidingStep; | ||
69 | private bool _collidingGround; | ||
70 | private long _collidingGroundStep; | ||
71 | private bool _collidingObj; | 64 | private bool _collidingObj; |
72 | private bool _floatOnWater; | 65 | private bool _floatOnWater; |
73 | private Vector3 _rotationalVelocity; | 66 | private OMV.Vector3 _rotationalVelocity; |
74 | private bool _kinematic; | 67 | private bool _kinematic; |
75 | private float _buoyancy; | 68 | private float _buoyancy; |
76 | 69 | ||
77 | private BulletBody m_body; | 70 | private OMV.Vector3 _PIDTarget; |
78 | public BulletBody Body { | ||
79 | get { return m_body; } | ||
80 | set { m_body = value; } | ||
81 | } | ||
82 | |||
83 | private int _subscribedEventsMs = 0; | ||
84 | private int _nextCollisionOkTime = 0; | ||
85 | |||
86 | private Vector3 _PIDTarget; | ||
87 | private bool _usePID; | 71 | private bool _usePID; |
88 | private float _PIDTau; | 72 | private float _PIDTau; |
89 | private bool _useHoverPID; | 73 | private bool _useHoverPID; |
@@ -91,25 +75,26 @@ public class BSCharacter : PhysicsActor | |||
91 | private PIDHoverType _PIDHoverType; | 75 | private PIDHoverType _PIDHoverType; |
92 | private float _PIDHoverTao; | 76 | private float _PIDHoverTao; |
93 | 77 | ||
94 | public BSCharacter(uint localID, String avName, BSScene parent_scene, Vector3 pos, Vector3 size, bool isFlying) | 78 | public BSCharacter(uint localID, String avName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 size, bool isFlying) |
95 | { | 79 | { |
96 | _localID = localID; | 80 | base.BaseInitialize(parent_scene, localID, avName, "BSCharacter"); |
97 | _avName = avName; | 81 | _physicsActorType = (int)ActorTypes.Agent; |
98 | _scene = parent_scene; | ||
99 | _position = pos; | 82 | _position = pos; |
100 | _size = size; | 83 | _size = size; |
101 | _flying = isFlying; | 84 | _flying = isFlying; |
102 | _orientation = Quaternion.Identity; | 85 | _orientation = OMV.Quaternion.Identity; |
103 | _velocity = Vector3.Zero; | 86 | _velocity = OMV.Vector3.Zero; |
104 | _buoyancy = ComputeBuoyancyFromFlying(isFlying); | 87 | _buoyancy = ComputeBuoyancyFromFlying(isFlying); |
88 | |||
105 | // The dimensions of the avatar capsule are kept in the scale. | 89 | // The dimensions of the avatar capsule are kept in the scale. |
106 | // Physics creates a unit capsule which is scaled by the physics engine. | 90 | // Physics creates a unit capsule which is scaled by the physics engine. |
107 | _scale = new Vector3(_scene.Params.avatarCapsuleRadius, _scene.Params.avatarCapsuleRadius, size.Z); | 91 | ComputeAvatarScale(_size); |
108 | _density = _scene.Params.avatarDensity; | 92 | _avatarDensity = PhysicsScene.Params.avatarDensity; |
109 | ComputeAvatarVolumeAndMass(); // set _avatarVolume and _mass based on capsule size, _density and _scale | 93 | // set _avatarVolume and _mass based on capsule size, _density and _scale |
94 | ComputeAvatarVolumeAndMass(); | ||
110 | 95 | ||
111 | ShapeData shapeData = new ShapeData(); | 96 | ShapeData shapeData = new ShapeData(); |
112 | shapeData.ID = _localID; | 97 | shapeData.ID = LocalID; |
113 | shapeData.Type = ShapeData.PhysicsShapeType.SHAPE_AVATAR; | 98 | shapeData.Type = ShapeData.PhysicsShapeType.SHAPE_AVATAR; |
114 | shapeData.Position = _position; | 99 | shapeData.Position = _position; |
115 | shapeData.Rotation = _orientation; | 100 | shapeData.Rotation = _orientation; |
@@ -118,29 +103,35 @@ public class BSCharacter : PhysicsActor | |||
118 | shapeData.Mass = _mass; | 103 | shapeData.Mass = _mass; |
119 | shapeData.Buoyancy = _buoyancy; | 104 | shapeData.Buoyancy = _buoyancy; |
120 | shapeData.Static = ShapeData.numericFalse; | 105 | shapeData.Static = ShapeData.numericFalse; |
121 | shapeData.Friction = _scene.Params.avatarFriction; | 106 | shapeData.Friction = PhysicsScene.Params.avatarFriction; |
122 | shapeData.Restitution = _scene.Params.avatarRestitution; | 107 | shapeData.Restitution = PhysicsScene.Params.avatarRestitution; |
123 | 108 | ||
124 | // do actual create at taint time | 109 | // do actual create at taint time |
125 | _scene.TaintedObject("BSCharacter.create", delegate() | 110 | PhysicsScene.TaintedObject("BSCharacter.create", delegate() |
126 | { | 111 | { |
127 | BulletSimAPI.CreateObject(parent_scene.WorldID, shapeData); | 112 | DetailLog("{0},BSCharacter.create,taint", LocalID); |
113 | BulletSimAPI.CreateObject(PhysicsScene.WorldID, shapeData); | ||
114 | |||
115 | // Set the buoyancy for flying. This will be refactored when all the settings happen in C#. | ||
116 | // If not set at creation, the avatar will stop flying when created after crossing a region boundry. | ||
117 | BulletSimAPI.SetObjectBuoyancy(PhysicsScene.WorldID, LocalID, _buoyancy); | ||
118 | |||
119 | BSBody = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(PhysicsScene.World.ptr, LocalID)); | ||
128 | 120 | ||
129 | m_body = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID)); | 121 | // This works here because CreateObject has already put the character into the physical world. |
130 | // avatars get all collisions no matter what | 122 | BulletSimAPI.SetCollisionFilterMask2(BSBody.ptr, |
131 | BulletSimAPI.AddToCollisionFlags2(Body.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); | 123 | (uint)CollisionFilterGroups.AvatarFilter, (uint)CollisionFilterGroups.AvatarMask); |
132 | }); | 124 | }); |
133 | |||
134 | return; | 125 | return; |
135 | } | 126 | } |
136 | 127 | ||
137 | // called when this character is being destroyed and the resources should be released | 128 | // called when this character is being destroyed and the resources should be released |
138 | public void Destroy() | 129 | public override void Destroy() |
139 | { | 130 | { |
140 | // DetailLog("{0},BSCharacter.Destroy", LocalID); | 131 | DetailLog("{0},BSCharacter.Destroy", LocalID); |
141 | _scene.TaintedObject("BSCharacter.destroy", delegate() | 132 | PhysicsScene.TaintedObject("BSCharacter.destroy", delegate() |
142 | { | 133 | { |
143 | BulletSimAPI.DestroyObject(_scene.WorldID, _localID); | 134 | BulletSimAPI.DestroyObject(PhysicsScene.WorldID, LocalID); |
144 | }); | 135 | }); |
145 | } | 136 | } |
146 | 137 | ||
@@ -149,274 +140,357 @@ public class BSCharacter : PhysicsActor | |||
149 | base.RequestPhysicsterseUpdate(); | 140 | base.RequestPhysicsterseUpdate(); |
150 | } | 141 | } |
151 | // No one calls this method so I don't know what it could possibly mean | 142 | // No one calls this method so I don't know what it could possibly mean |
152 | public override bool Stopped { | 143 | public override bool Stopped { |
153 | get { return false; } | 144 | get { return false; } |
154 | } | 145 | } |
155 | public override Vector3 Size { | 146 | public override OMV.Vector3 Size { |
156 | get | 147 | get |
157 | { | 148 | { |
158 | // Avatar capsule size is kept in the scale parameter. | 149 | // Avatar capsule size is kept in the scale parameter. |
159 | return new Vector3(_scale.X * 2, _scale.Y * 2, _scale.Z); | 150 | return new OMV.Vector3(_scale.X * 2, _scale.Y * 2, _scale.Z); |
160 | } | 151 | } |
161 | 152 | ||
162 | set { | 153 | set { |
163 | // When an avatar's size is set, only the height is changed | 154 | // When an avatar's size is set, only the height is changed |
164 | // and that really only depends on the radius. | 155 | // and that really only depends on the radius. |
165 | _size = value; | 156 | _size = value; |
166 | _scale.Z = (_size.Z * 1.15f) - (_scale.X + _scale.Y); | 157 | ComputeAvatarScale(_size); |
167 | 158 | ||
168 | // TODO: something has to be done with the avatar's vertical position | 159 | // TODO: something has to be done with the avatar's vertical position |
169 | 160 | ||
170 | ComputeAvatarVolumeAndMass(); | 161 | ComputeAvatarVolumeAndMass(); |
171 | 162 | ||
172 | _scene.TaintedObject("BSCharacter.setSize", delegate() | 163 | PhysicsScene.TaintedObject("BSCharacter.setSize", delegate() |
173 | { | 164 | { |
174 | BulletSimAPI.SetObjectScaleMass(_scene.WorldID, LocalID, _scale, _mass, true); | 165 | BulletSimAPI.SetObjectScaleMass(PhysicsScene.WorldID, LocalID, _scale, _mass, true); |
175 | }); | 166 | }); |
176 | 167 | ||
177 | } | 168 | } |
178 | } | ||
179 | public override PrimitiveBaseShape Shape { | ||
180 | set { _pbs = value; | ||
181 | } | ||
182 | } | 169 | } |
183 | public override uint LocalID { | 170 | public override PrimitiveBaseShape Shape { |
184 | set { _localID = value; | 171 | set { _pbs = value; |
185 | } | 172 | } |
186 | get { return _localID; } | ||
187 | } | 173 | } |
188 | public override bool Grabbed { | 174 | public override bool Grabbed { |
189 | set { _grabbed = value; | 175 | set { _grabbed = value; |
190 | } | 176 | } |
191 | } | 177 | } |
192 | public override bool Selected { | 178 | public override bool Selected { |
193 | set { _selected = value; | 179 | set { _selected = value; |
194 | } | 180 | } |
195 | } | 181 | } |
196 | public override void CrossingFailure() { return; } | 182 | public override void CrossingFailure() { return; } |
197 | public override void link(PhysicsActor obj) { return; } | 183 | public override void link(PhysicsActor obj) { return; } |
198 | public override void delink() { return; } | 184 | public override void delink() { return; } |
199 | public override void LockAngularMotion(Vector3 axis) { return; } | ||
200 | 185 | ||
201 | public override Vector3 Position { | 186 | // Set motion values to zero. |
187 | // Do it to the properties so the values get set in the physics engine. | ||
188 | // Push the setting of the values to the viewer. | ||
189 | // Called at taint time! | ||
190 | public override void ZeroMotion() | ||
191 | { | ||
192 | _velocity = OMV.Vector3.Zero; | ||
193 | _acceleration = OMV.Vector3.Zero; | ||
194 | _rotationalVelocity = OMV.Vector3.Zero; | ||
195 | |||
196 | // Zero some other properties directly into the physics engine | ||
197 | BulletSimAPI.SetLinearVelocity2(BSBody.ptr, OMV.Vector3.Zero); | ||
198 | BulletSimAPI.SetAngularVelocity2(BSBody.ptr, OMV.Vector3.Zero); | ||
199 | BulletSimAPI.SetInterpolationVelocity2(BSBody.ptr, OMV.Vector3.Zero, OMV.Vector3.Zero); | ||
200 | BulletSimAPI.ClearForces2(BSBody.ptr); | ||
201 | } | ||
202 | |||
203 | public override void LockAngularMotion(OMV.Vector3 axis) { return; } | ||
204 | |||
205 | public override OMV.Vector3 Position { | ||
202 | get { | 206 | get { |
203 | // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID); | 207 | // _position = BulletSimAPI.GetObjectPosition(Scene.WorldID, _localID); |
204 | return _position; | 208 | return _position; |
205 | } | 209 | } |
206 | set { | 210 | set { |
207 | _position = value; | 211 | _position = value; |
208 | PositionSanityCheck(); | 212 | PositionSanityCheck(); |
209 | 213 | ||
210 | _scene.TaintedObject("BSCharacter.setPosition", delegate() | 214 | PhysicsScene.TaintedObject("BSCharacter.setPosition", delegate() |
211 | { | 215 | { |
212 | DetailLog("{0},BSCharacter.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); | 216 | DetailLog("{0},BSCharacter.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); |
213 | BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation); | 217 | BulletSimAPI.SetObjectTranslation(PhysicsScene.WorldID, LocalID, _position, _orientation); |
214 | }); | 218 | }); |
215 | } | 219 | } |
220 | } | ||
221 | public override OMV.Vector3 ForcePosition { | ||
222 | get { | ||
223 | _position = BulletSimAPI.GetPosition2(BSBody.ptr); | ||
224 | return _position; | ||
225 | } | ||
226 | set { | ||
227 | _position = value; | ||
228 | PositionSanityCheck(); | ||
229 | BulletSimAPI.SetTranslation2(BSBody.ptr, _position, _orientation); | ||
230 | } | ||
216 | } | 231 | } |
217 | 232 | ||
233 | |||
218 | // Check that the current position is sane and, if not, modify the position to make it so. | 234 | // Check that the current position is sane and, if not, modify the position to make it so. |
219 | // Check for being below terrain and being out of bounds. | 235 | // Check for being below terrain and being out of bounds. |
220 | // Returns 'true' of the position was made sane by some action. | 236 | // Returns 'true' of the position was made sane by some action. |
221 | private bool PositionSanityCheck() | 237 | private bool PositionSanityCheck() |
222 | { | 238 | { |
223 | bool ret = false; | 239 | bool ret = false; |
224 | 240 | ||
225 | // If below the ground, move the avatar up | 241 | // If below the ground, move the avatar up |
226 | float terrainHeight = Scene.GetTerrainHeightAtXYZ(_position); | 242 | float terrainHeight = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(_position); |
227 | if (_position.Z < terrainHeight) | 243 | if (Position.Z < terrainHeight) |
228 | { | 244 | { |
229 | DetailLog("{0},BSCharacter.PositionAdjustUnderGround,call,pos={1},orient={2}", LocalID, _position, _orientation); | 245 | DetailLog("{0},BSCharacter.PositionAdjustUnderGround,call,pos={1},terrain={2}", LocalID, _position, terrainHeight); |
230 | _position.Z = terrainHeight + 2.0f; | 246 | _position.Z = terrainHeight + 2.0f; |
231 | ret = true; | 247 | ret = true; |
232 | } | 248 | } |
249 | if ((CurrentCollisionFlags & CollisionFlags.BS_FLOATS_ON_WATER) != 0) | ||
250 | { | ||
251 | float waterHeight = PhysicsScene.GetWaterLevelAtXYZ(_position); | ||
252 | if (Position.Z < waterHeight) | ||
253 | { | ||
254 | _position.Z = waterHeight; | ||
255 | ret = true; | ||
256 | } | ||
257 | } | ||
233 | 258 | ||
234 | // TODO: check for out of bounds | 259 | // TODO: check for out of bounds |
260 | return ret; | ||
261 | } | ||
235 | 262 | ||
263 | // A version of the sanity check that also makes sure a new position value is | ||
264 | // pushed back to the physics engine. This routine would be used by anyone | ||
265 | // who is not already pushing the value. | ||
266 | private bool PositionSanityCheck2(bool atTaintTime) | ||
267 | { | ||
268 | bool ret = false; | ||
269 | if (PositionSanityCheck()) | ||
270 | { | ||
271 | // The new position value must be pushed into the physics engine but we can't | ||
272 | // just assign to "Position" because of potential call loops. | ||
273 | BSScene.TaintCallback sanityOperation = delegate() | ||
274 | { | ||
275 | DetailLog("{0},BSCharacter.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation); | ||
276 | BulletSimAPI.SetObjectTranslation(PhysicsScene.WorldID, LocalID, _position, _orientation); | ||
277 | }; | ||
278 | if (atTaintTime) | ||
279 | sanityOperation(); | ||
280 | else | ||
281 | PhysicsScene.TaintedObject("BSCharacter.PositionSanityCheck", sanityOperation); | ||
282 | ret = true; | ||
283 | } | ||
236 | return ret; | 284 | return ret; |
237 | } | 285 | } |
238 | 286 | ||
239 | public override float Mass { | 287 | public override float Mass { |
240 | get { | 288 | get { |
241 | return _mass; | 289 | return _mass; |
242 | } | 290 | } |
243 | } | 291 | } |
244 | public override Vector3 Force { | 292 | |
245 | get { return _force; } | 293 | // used when we only want this prim's mass and not the linkset thing |
294 | public override float MassRaw { get {return _mass; } } | ||
295 | |||
296 | public override OMV.Vector3 Force { | ||
297 | get { return _force; } | ||
246 | set { | 298 | set { |
247 | _force = value; | 299 | _force = value; |
248 | // m_log.DebugFormat("{0}: Force = {1}", LogHeader, _force); | 300 | // m_log.DebugFormat("{0}: Force = {1}", LogHeader, _force); |
249 | Scene.TaintedObject("BSCharacter.SetForce", delegate() | 301 | PhysicsScene.TaintedObject("BSCharacter.SetForce", delegate() |
250 | { | 302 | { |
251 | DetailLog("{0},BSCharacter.setForce,taint,force={1}", LocalID, _force); | 303 | DetailLog("{0},BSCharacter.setForce,taint,force={1}", LocalID, _force); |
252 | BulletSimAPI.SetObjectForce(Scene.WorldID, LocalID, _force); | 304 | BulletSimAPI.SetObjectForce(PhysicsScene.WorldID, LocalID, _force); |
253 | }); | 305 | }); |
254 | } | 306 | } |
255 | } | 307 | } |
256 | 308 | ||
257 | public override int VehicleType { | 309 | public override int VehicleType { |
258 | get { return 0; } | 310 | get { return 0; } |
259 | set { return; } | 311 | set { return; } |
260 | } | 312 | } |
261 | public override void VehicleFloatParam(int param, float value) { } | 313 | public override void VehicleFloatParam(int param, float value) { } |
262 | public override void VehicleVectorParam(int param, Vector3 value) {} | 314 | public override void VehicleVectorParam(int param, OMV.Vector3 value) {} |
263 | public override void VehicleRotationParam(int param, Quaternion rotation) { } | 315 | public override void VehicleRotationParam(int param, OMV.Quaternion rotation) { } |
264 | public override void VehicleFlags(int param, bool remove) { } | 316 | public override void VehicleFlags(int param, bool remove) { } |
265 | 317 | ||
266 | // Allows the detection of collisions with inherently non-physical prims. see llVolumeDetect for more | 318 | // Allows the detection of collisions with inherently non-physical prims. see llVolumeDetect for more |
267 | public override void SetVolumeDetect(int param) { return; } | 319 | public override void SetVolumeDetect(int param) { return; } |
268 | 320 | ||
269 | public override Vector3 GeometricCenter { get { return Vector3.Zero; } } | 321 | public override OMV.Vector3 GeometricCenter { get { return OMV.Vector3.Zero; } } |
270 | public override Vector3 CenterOfMass { get { return Vector3.Zero; } } | 322 | public override OMV.Vector3 CenterOfMass { get { return OMV.Vector3.Zero; } } |
271 | public override Vector3 Velocity { | 323 | public override OMV.Vector3 Velocity { |
272 | get { return _velocity; } | 324 | get { return _velocity; } |
273 | set { | 325 | set { |
274 | _velocity = value; | 326 | _velocity = value; |
275 | // m_log.DebugFormat("{0}: set velocity = {1}", LogHeader, _velocity); | 327 | // m_log.DebugFormat("{0}: set velocity = {1}", LogHeader, _velocity); |
276 | _scene.TaintedObject("BSCharacter.setVelocity", delegate() | 328 | PhysicsScene.TaintedObject("BSCharacter.setVelocity", delegate() |
277 | { | 329 | { |
278 | DetailLog("{0},BSCharacter.setVelocity,taint,vel={1}", LocalID, _velocity); | 330 | DetailLog("{0},BSCharacter.setVelocity,taint,vel={1}", LocalID, _velocity); |
279 | BulletSimAPI.SetObjectVelocity(_scene.WorldID, _localID, _velocity); | 331 | BulletSimAPI.SetObjectVelocity(PhysicsScene.WorldID, LocalID, _velocity); |
280 | }); | 332 | }); |
281 | } | 333 | } |
282 | } | 334 | } |
283 | public override Vector3 Torque { | 335 | public override OMV.Vector3 Torque { |
284 | get { return _torque; } | 336 | get { return _torque; } |
285 | set { _torque = value; | 337 | set { _torque = value; |
286 | } | 338 | } |
287 | } | 339 | } |
288 | public override float CollisionScore { | 340 | public override float CollisionScore { |
289 | get { return _collisionScore; } | 341 | get { return _collisionScore; } |
290 | set { _collisionScore = value; | 342 | set { _collisionScore = value; |
291 | } | 343 | } |
292 | } | 344 | } |
293 | public override Vector3 Acceleration { | 345 | public override OMV.Vector3 Acceleration { |
294 | get { return _acceleration; } | 346 | get { return _acceleration; } |
295 | set { _acceleration = value; } | 347 | set { _acceleration = value; } |
296 | } | 348 | } |
297 | public override Quaternion Orientation { | 349 | public override OMV.Quaternion Orientation { |
298 | get { return _orientation; } | 350 | get { return _orientation; } |
299 | set { | 351 | set { |
300 | _orientation = value; | 352 | _orientation = value; |
301 | // m_log.DebugFormat("{0}: set orientation to {1}", LogHeader, _orientation); | 353 | // m_log.DebugFormat("{0}: set orientation to {1}", LogHeader, _orientation); |
302 | _scene.TaintedObject("BSCharacter.setOrientation", delegate() | 354 | PhysicsScene.TaintedObject("BSCharacter.setOrientation", delegate() |
303 | { | 355 | { |
304 | // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID); | 356 | // _position = BulletSimAPI.GetObjectPosition(Scene.WorldID, _localID); |
305 | BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation); | 357 | BulletSimAPI.SetObjectTranslation(PhysicsScene.WorldID, LocalID, _position, _orientation); |
306 | }); | 358 | }); |
307 | } | 359 | } |
360 | } | ||
361 | // Go directly to Bullet to get/set the value. | ||
362 | public override OMV.Quaternion ForceOrientation | ||
363 | { | ||
364 | get | ||
365 | { | ||
366 | _orientation = BulletSimAPI.GetOrientation2(BSBody.ptr); | ||
367 | return _orientation; | ||
368 | } | ||
369 | set | ||
370 | { | ||
371 | _orientation = value; | ||
372 | BulletSimAPI.SetTranslation2(BSBody.ptr, _position, _orientation); | ||
373 | } | ||
308 | } | 374 | } |
309 | public override int PhysicsActorType { | 375 | public override int PhysicsActorType { |
310 | get { return _physicsActorType; } | 376 | get { return _physicsActorType; } |
311 | set { _physicsActorType = value; | 377 | set { _physicsActorType = value; |
312 | } | 378 | } |
313 | } | 379 | } |
314 | public override bool IsPhysical { | 380 | public override bool IsPhysical { |
315 | get { return _isPhysical; } | 381 | get { return _isPhysical; } |
316 | set { _isPhysical = value; | 382 | set { _isPhysical = value; |
317 | } | 383 | } |
318 | } | 384 | } |
319 | public override bool Flying { | 385 | public override bool Flying { |
320 | get { return _flying; } | 386 | get { return _flying; } |
321 | set { | 387 | set { |
322 | if (_flying != value) | 388 | _flying = value; |
323 | { | 389 | // simulate flying by changing the effect of gravity |
324 | _flying = value; | 390 | this.Buoyancy = ComputeBuoyancyFromFlying(_flying); |
325 | // simulate flying by changing the effect of gravity | 391 | } |
326 | this.Buoyancy = ComputeBuoyancyFromFlying(_flying); | ||
327 | } | ||
328 | } | ||
329 | } | 392 | } |
393 | // Flying is implimented by changing the avatar's buoyancy. | ||
394 | // Would this be done better with a vehicle type? | ||
330 | private float ComputeBuoyancyFromFlying(bool ifFlying) { | 395 | private float ComputeBuoyancyFromFlying(bool ifFlying) { |
331 | return ifFlying ? 1f : 0f; | 396 | return ifFlying ? 1f : 0f; |
332 | } | 397 | } |
333 | public override bool | 398 | public override bool |
334 | SetAlwaysRun { | 399 | SetAlwaysRun { |
335 | get { return _setAlwaysRun; } | 400 | get { return _setAlwaysRun; } |
336 | set { _setAlwaysRun = value; } | 401 | set { _setAlwaysRun = value; } |
337 | } | 402 | } |
338 | public override bool ThrottleUpdates { | 403 | public override bool ThrottleUpdates { |
339 | get { return _throttleUpdates; } | 404 | get { return _throttleUpdates; } |
340 | set { _throttleUpdates = value; } | 405 | set { _throttleUpdates = value; } |
341 | } | 406 | } |
342 | public override bool IsColliding { | 407 | public override bool IsColliding { |
343 | get { return (_collidingStep == _scene.SimulationStep); } | 408 | get { return (CollidingStep == PhysicsScene.SimulationStep); } |
344 | set { _isColliding = value; } | 409 | set { _isColliding = value; } |
345 | } | 410 | } |
346 | public override bool CollidingGround { | 411 | public override bool CollidingGround { |
347 | get { return (_collidingGroundStep == _scene.SimulationStep); } | 412 | get { return (CollidingGroundStep == PhysicsScene.SimulationStep); } |
348 | set { _collidingGround = value; } | 413 | set { CollidingGround = value; } |
349 | } | 414 | } |
350 | public override bool CollidingObj { | 415 | public override bool CollidingObj { |
351 | get { return _collidingObj; } | 416 | get { return _collidingObj; } |
352 | set { _collidingObj = value; } | 417 | set { _collidingObj = value; } |
353 | } | 418 | } |
354 | public override bool FloatOnWater { | 419 | public override bool FloatOnWater { |
355 | set { _floatOnWater = value; } | 420 | set { |
421 | _floatOnWater = value; | ||
422 | PhysicsScene.TaintedObject("BSCharacter.setFloatOnWater", delegate() | ||
423 | { | ||
424 | if (_floatOnWater) | ||
425 | CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.ptr, CollisionFlags.BS_FLOATS_ON_WATER); | ||
426 | else | ||
427 | CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.ptr, CollisionFlags.BS_FLOATS_ON_WATER); | ||
428 | }); | ||
429 | } | ||
356 | } | 430 | } |
357 | public override Vector3 RotationalVelocity { | 431 | public override OMV.Vector3 RotationalVelocity { |
358 | get { return _rotationalVelocity; } | 432 | get { return _rotationalVelocity; } |
359 | set { _rotationalVelocity = value; } | 433 | set { _rotationalVelocity = value; } |
360 | } | 434 | } |
361 | public override bool Kinematic { | 435 | public override bool Kinematic { |
362 | get { return _kinematic; } | 436 | get { return _kinematic; } |
363 | set { _kinematic = value; } | 437 | set { _kinematic = value; } |
364 | } | 438 | } |
365 | // neg=fall quickly, 0=1g, 1=0g, pos=float up | 439 | // neg=fall quickly, 0=1g, 1=0g, pos=float up |
366 | public override float Buoyancy { | 440 | public override float Buoyancy { |
367 | get { return _buoyancy; } | 441 | get { return _buoyancy; } |
368 | set { _buoyancy = value; | 442 | set { _buoyancy = value; |
369 | _scene.TaintedObject("BSCharacter.setBuoyancy", delegate() | 443 | PhysicsScene.TaintedObject("BSCharacter.setBuoyancy", delegate() |
370 | { | 444 | { |
371 | DetailLog("{0},BSCharacter.setBuoyancy,taint,buoy={1}", LocalID, _buoyancy); | 445 | DetailLog("{0},BSCharacter.setBuoyancy,taint,buoy={1}", LocalID, _buoyancy); |
372 | BulletSimAPI.SetObjectBuoyancy(_scene.WorldID, LocalID, _buoyancy); | 446 | BulletSimAPI.SetObjectBuoyancy(PhysicsScene.WorldID, LocalID, _buoyancy); |
373 | }); | 447 | }); |
374 | } | 448 | } |
375 | } | 449 | } |
376 | 450 | ||
377 | // Used for MoveTo | 451 | // Used for MoveTo |
378 | public override Vector3 PIDTarget { | 452 | public override OMV.Vector3 PIDTarget { |
379 | set { _PIDTarget = value; } | 453 | set { _PIDTarget = value; } |
380 | } | 454 | } |
381 | public override bool PIDActive { | 455 | public override bool PIDActive { |
382 | set { _usePID = value; } | 456 | set { _usePID = value; } |
383 | } | 457 | } |
384 | public override float PIDTau { | 458 | public override float PIDTau { |
385 | set { _PIDTau = value; } | 459 | set { _PIDTau = value; } |
386 | } | 460 | } |
387 | 461 | ||
388 | // Used for llSetHoverHeight and maybe vehicle height | 462 | // Used for llSetHoverHeight and maybe vehicle height |
389 | // Hover Height will override MoveTo target's Z | 463 | // Hover Height will override MoveTo target's Z |
390 | public override bool PIDHoverActive { | 464 | public override bool PIDHoverActive { |
391 | set { _useHoverPID = value; } | 465 | set { _useHoverPID = value; } |
392 | } | 466 | } |
393 | public override float PIDHoverHeight { | 467 | public override float PIDHoverHeight { |
394 | set { _PIDHoverHeight = value; } | 468 | set { _PIDHoverHeight = value; } |
395 | } | 469 | } |
396 | public override PIDHoverType PIDHoverType { | 470 | public override PIDHoverType PIDHoverType { |
397 | set { _PIDHoverType = value; } | 471 | set { _PIDHoverType = value; } |
398 | } | 472 | } |
399 | public override float PIDHoverTau { | 473 | public override float PIDHoverTau { |
400 | set { _PIDHoverTao = value; } | 474 | set { _PIDHoverTao = value; } |
401 | } | 475 | } |
402 | 476 | ||
403 | // For RotLookAt | 477 | // For RotLookAt |
404 | public override Quaternion APIDTarget { set { return; } } | 478 | public override OMV.Quaternion APIDTarget { set { return; } } |
405 | public override bool APIDActive { set { return; } } | 479 | public override bool APIDActive { set { return; } } |
406 | public override float APIDStrength { set { return; } } | 480 | public override float APIDStrength { set { return; } } |
407 | public override float APIDDamping { set { return; } } | 481 | public override float APIDDamping { set { return; } } |
408 | 482 | ||
409 | public override void AddForce(Vector3 force, bool pushforce) { | 483 | public override void AddForce(OMV.Vector3 force, bool pushforce) { |
410 | if (force.IsFinite()) | 484 | if (force.IsFinite()) |
411 | { | 485 | { |
412 | _force.X += force.X; | 486 | _force.X += force.X; |
413 | _force.Y += force.Y; | 487 | _force.Y += force.Y; |
414 | _force.Z += force.Z; | 488 | _force.Z += force.Z; |
415 | // m_log.DebugFormat("{0}: AddForce. adding={1}, newForce={2}", LogHeader, force, _force); | 489 | // m_log.DebugFormat("{0}: AddForce. adding={1}, newForce={2}", LogHeader, force, _force); |
416 | _scene.TaintedObject("BSCharacter.AddForce", delegate() | 490 | PhysicsScene.TaintedObject("BSCharacter.AddForce", delegate() |
417 | { | 491 | { |
418 | DetailLog("{0},BSCharacter.setAddForce,taint,addedForce={1}", LocalID, _force); | 492 | DetailLog("{0},BSCharacter.setAddForce,taint,addedForce={1}", LocalID, _force); |
419 | BulletSimAPI.AddObjectForce2(Body.Ptr, _force); | 493 | BulletSimAPI.SetObjectForce2(BSBody.ptr, _force); |
420 | }); | 494 | }); |
421 | } | 495 | } |
422 | else | 496 | else |
@@ -426,37 +500,19 @@ public class BSCharacter : PhysicsActor | |||
426 | //m_lastUpdateSent = false; | 500 | //m_lastUpdateSent = false; |
427 | } | 501 | } |
428 | 502 | ||
429 | public override void AddAngularForce(Vector3 force, bool pushforce) { | 503 | public override void AddAngularForce(OMV.Vector3 force, bool pushforce) { |
430 | } | 504 | } |
431 | public override void SetMomentum(Vector3 momentum) { | 505 | public override void SetMomentum(OMV.Vector3 momentum) { |
432 | } | 506 | } |
433 | 507 | ||
434 | // Turn on collision events at a rate no faster than one every the given milliseconds | 508 | private void ComputeAvatarScale(OMV.Vector3 size) |
435 | public override void SubscribeEvents(int ms) { | 509 | { |
436 | _subscribedEventsMs = ms; | 510 | _scale.X = PhysicsScene.Params.avatarCapsuleRadius; |
437 | if (ms > 0) | 511 | _scale.Y = PhysicsScene.Params.avatarCapsuleRadius; |
438 | { | ||
439 | // make sure first collision happens | ||
440 | _nextCollisionOkTime = Util.EnvironmentTickCount() - _subscribedEventsMs; | ||
441 | 512 | ||
442 | Scene.TaintedObject("BSCharacter.SubscribeEvents", delegate() | 513 | // The 1.15 came from ODE but it seems to cause the avatar to float off the ground |
443 | { | 514 | // _scale.Z = (_size.Z * 1.15f) - (_scale.X + _scale.Y); |
444 | BulletSimAPI.AddToCollisionFlags2(Body.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); | 515 | _scale.Z = (_size.Z) - (_scale.X + _scale.Y); |
445 | }); | ||
446 | } | ||
447 | } | ||
448 | // Stop collision events | ||
449 | public override void UnSubscribeEvents() { | ||
450 | _subscribedEventsMs = 0; | ||
451 | // Avatars get all their collision events | ||
452 | // Scene.TaintedObject("BSCharacter.UnSubscribeEvents", delegate() | ||
453 | // { | ||
454 | // BulletSimAPI.RemoveFromCollisionFlags2(Body.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); | ||
455 | // }); | ||
456 | } | ||
457 | // Return 'true' if someone has subscribed to events | ||
458 | public override bool SubscribedEvents() { | ||
459 | return (_subscribedEventsMs > 0); | ||
460 | } | 516 | } |
461 | 517 | ||
462 | // set _avatarVolume and _mass based on capsule size, _density and _scale | 518 | // set _avatarVolume and _mass based on capsule size, _density and _scale |
@@ -473,82 +529,26 @@ public class BSCharacter : PhysicsActor | |||
473 | * Math.Min(_scale.X, _scale.Y) | 529 | * Math.Min(_scale.X, _scale.Y) |
474 | * _scale.Y // plus the volume of the capsule end caps | 530 | * _scale.Y // plus the volume of the capsule end caps |
475 | ); | 531 | ); |
476 | _mass = _density * _avatarVolume; | 532 | _mass = _avatarDensity * _avatarVolume; |
477 | } | 533 | } |
478 | 534 | ||
479 | // The physics engine says that properties have updated. Update same and inform | 535 | // The physics engine says that properties have updated. Update same and inform |
480 | // the world that things have changed. | 536 | // the world that things have changed. |
481 | public void UpdateProperties(EntityProperties entprop) | 537 | public override void UpdateProperties(EntityProperties entprop) |
482 | { | 538 | { |
483 | _position = entprop.Position; | 539 | _position = entprop.Position; |
484 | _orientation = entprop.Rotation; | 540 | _orientation = entprop.Rotation; |
485 | _velocity = entprop.Velocity; | 541 | _velocity = entprop.Velocity; |
486 | _acceleration = entprop.Acceleration; | 542 | _acceleration = entprop.Acceleration; |
487 | _rotationalVelocity = entprop.RotationalVelocity; | 543 | _rotationalVelocity = entprop.RotationalVelocity; |
544 | // Do some sanity checking for the avatar. Make sure it's above ground and inbounds. | ||
545 | PositionSanityCheck2(true); | ||
546 | |||
488 | // Avatars don't report their changes the usual way. Changes are checked for in the heartbeat loop. | 547 | // Avatars don't report their changes the usual way. Changes are checked for in the heartbeat loop. |
489 | // base.RequestPhysicsterseUpdate(); | 548 | // base.RequestPhysicsterseUpdate(); |
490 | 549 | ||
491 | /* | ||
492 | DetailLog("{0},BSCharacter.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}", | 550 | DetailLog("{0},BSCharacter.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}", |
493 | LocalID, entprop.Position, entprop.Rotation, entprop.Velocity, | 551 | LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity); |
494 | entprop.Acceleration, entprop.RotationalVelocity); | ||
495 | */ | ||
496 | } | ||
497 | |||
498 | // Called by the scene when a collision with this object is reported | ||
499 | // The collision, if it should be reported to the character, is placed in a collection | ||
500 | // that will later be sent to the simulator when SendCollisions() is called. | ||
501 | CollisionEventUpdate collisionCollection = null; | ||
502 | public void Collide(uint collidingWith, ActorTypes type, Vector3 contactPoint, Vector3 contactNormal, float pentrationDepth) | ||
503 | { | ||
504 | // m_log.DebugFormat("{0}: Collide: ms={1}, id={2}, with={3}", LogHeader, _subscribedEventsMs, LocalID, collidingWith); | ||
505 | |||
506 | // The following makes IsColliding() and IsCollidingGround() work | ||
507 | _collidingStep = _scene.SimulationStep; | ||
508 | if (collidingWith == BSScene.TERRAIN_ID || collidingWith == BSScene.GROUNDPLANE_ID) | ||
509 | { | ||
510 | _collidingGroundStep = _scene.SimulationStep; | ||
511 | } | ||
512 | // DetailLog("{0},BSCharacter.Collison,call,with={1}", LocalID, collidingWith); | ||
513 | |||
514 | // throttle collisions to the rate specified in the subscription | ||
515 | if (_subscribedEventsMs != 0) { | ||
516 | int nowTime = _scene.SimulationNowTime; | ||
517 | if (nowTime >= _nextCollisionOkTime) { | ||
518 | _nextCollisionOkTime = nowTime + _subscribedEventsMs; | ||
519 | |||
520 | if (collisionCollection == null) | ||
521 | collisionCollection = new CollisionEventUpdate(); | ||
522 | collisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth)); | ||
523 | } | ||
524 | } | ||
525 | } | ||
526 | |||
527 | public void SendCollisions() | ||
528 | { | ||
529 | /* | ||
530 | if (collisionCollection != null && collisionCollection.Count > 0) | ||
531 | { | ||
532 | base.SendCollisionUpdate(collisionCollection); | ||
533 | collisionCollection = null; | ||
534 | } | ||
535 | */ | ||
536 | // Kludge to make a collision call even if there are no collisions. | ||
537 | // This causes the avatar animation to get updated. | ||
538 | if (collisionCollection == null) | ||
539 | collisionCollection = new CollisionEventUpdate(); | ||
540 | base.SendCollisionUpdate(collisionCollection); | ||
541 | // If there were any collisions in the collection, make sure we don't use the | ||
542 | // same instance next time. | ||
543 | if (collisionCollection.Count > 0) | ||
544 | collisionCollection = null; | ||
545 | // End kludge | ||
546 | } | ||
547 | |||
548 | // Invoke the detailed logger and output something if it's enabled. | ||
549 | private void DetailLog(string msg, params Object[] args) | ||
550 | { | ||
551 | Scene.PhysicsLogging.Write(msg, args); | ||
552 | } | 552 | } |
553 | } | 553 | } |
554 | } | 554 | } |