diff options
Diffstat (limited to 'OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs')
-rw-r--r-- | OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs | 689 |
1 files changed, 291 insertions, 398 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index 2a5397e..e2f7af9 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs | |||
@@ -28,48 +28,62 @@ 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 OMV = OpenMetaverse; | 31 | using 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 sealed class BSCharacter : BSPhysObject | 37 | public class BSCharacter : PhysicsActor |
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; | ||
42 | // private bool _stopped; | 45 | // private bool _stopped; |
43 | private OMV.Vector3 _size; | 46 | private Vector3 _size; |
47 | private Vector3 _scale; | ||
48 | private PrimitiveBaseShape _pbs; | ||
49 | private uint _localID = 0; | ||
44 | private bool _grabbed; | 50 | private bool _grabbed; |
45 | private bool _selected; | 51 | private bool _selected; |
46 | private OMV.Vector3 _position; | 52 | private Vector3 _position; |
47 | private float _mass; | 53 | private float _mass; |
48 | private float _avatarDensity; | 54 | public float _density; |
49 | private float _avatarVolume; | 55 | public float _avatarVolume; |
50 | private OMV.Vector3 _force; | 56 | private Vector3 _force; |
51 | private OMV.Vector3 _velocity; | 57 | private Vector3 _velocity; |
52 | private OMV.Vector3 _torque; | 58 | private Vector3 _torque; |
53 | private float _collisionScore; | 59 | private float _collisionScore; |
54 | private OMV.Vector3 _acceleration; | 60 | private Vector3 _acceleration; |
55 | private OMV.Quaternion _orientation; | 61 | private Quaternion _orientation; |
56 | private int _physicsActorType; | 62 | private int _physicsActorType; |
57 | private bool _isPhysical; | 63 | private bool _isPhysical; |
58 | private bool _flying; | 64 | private bool _flying; |
59 | private bool _setAlwaysRun; | 65 | private bool _setAlwaysRun; |
60 | private bool _throttleUpdates; | 66 | private bool _throttleUpdates; |
61 | private bool _isColliding; | 67 | private bool _isColliding; |
68 | private long _collidingStep; | ||
69 | private bool _collidingGround; | ||
70 | private long _collidingGroundStep; | ||
62 | private bool _collidingObj; | 71 | private bool _collidingObj; |
63 | private bool _floatOnWater; | 72 | private bool _floatOnWater; |
64 | private OMV.Vector3 _rotationalVelocity; | 73 | private Vector3 _rotationalVelocity; |
65 | private bool _kinematic; | 74 | private bool _kinematic; |
66 | private float _buoyancy; | 75 | private float _buoyancy; |
67 | 76 | ||
68 | // The friction and velocity of the avatar is modified depending on whether walking or not. | 77 | private BulletBody m_body; |
69 | private OMV.Vector3 _appliedVelocity; // the last velocity applied to the avatar | 78 | public BulletBody Body { |
70 | private float _currentFriction; // the friction currently being used (changed by setVelocity). | 79 | get { return m_body; } |
80 | set { m_body = value; } | ||
81 | } | ||
82 | |||
83 | private int _subscribedEventsMs = 0; | ||
84 | private int _nextCollisionOkTime = 0; | ||
71 | 85 | ||
72 | private OMV.Vector3 _PIDTarget; | 86 | private Vector3 _PIDTarget; |
73 | private bool _usePID; | 87 | private bool _usePID; |
74 | private float _PIDTau; | 88 | private float _PIDTau; |
75 | private bool _useHoverPID; | 89 | private bool _useHoverPID; |
@@ -77,507 +91,332 @@ public sealed class BSCharacter : BSPhysObject | |||
77 | private PIDHoverType _PIDHoverType; | 91 | private PIDHoverType _PIDHoverType; |
78 | private float _PIDHoverTao; | 92 | private float _PIDHoverTao; |
79 | 93 | ||
80 | public BSCharacter(uint localID, String avName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 size, bool isFlying) | 94 | public BSCharacter(uint localID, String avName, BSScene parent_scene, Vector3 pos, Vector3 size, bool isFlying) |
81 | { | 95 | { |
82 | base.BaseInitialize(parent_scene, localID, avName, "BSCharacter"); | 96 | _localID = localID; |
83 | _physicsActorType = (int)ActorTypes.Agent; | 97 | _avName = avName; |
98 | _scene = parent_scene; | ||
84 | _position = pos; | 99 | _position = pos; |
85 | _size = size; | 100 | _size = size; |
86 | _flying = isFlying; | 101 | _flying = isFlying; |
87 | _orientation = OMV.Quaternion.Identity; | 102 | _orientation = Quaternion.Identity; |
88 | _velocity = OMV.Vector3.Zero; | 103 | _velocity = Vector3.Zero; |
89 | _appliedVelocity = OMV.Vector3.Zero; | ||
90 | _buoyancy = ComputeBuoyancyFromFlying(isFlying); | 104 | _buoyancy = ComputeBuoyancyFromFlying(isFlying); |
91 | _currentFriction = PhysicsScene.Params.avatarStandingFriction; | ||
92 | _avatarDensity = PhysicsScene.Params.avatarDensity; | ||
93 | |||
94 | // The dimensions of the avatar capsule are kept in the scale. | 105 | // The dimensions of the avatar capsule are kept in the scale. |
95 | // Physics creates a unit capsule which is scaled by the physics engine. | 106 | // Physics creates a unit capsule which is scaled by the physics engine. |
96 | ComputeAvatarScale(_size); | 107 | _scale = new Vector3(_scene.Params.avatarCapsuleRadius, _scene.Params.avatarCapsuleRadius, size.Z); |
97 | // set _avatarVolume and _mass based on capsule size, _density and Scale | 108 | _density = _scene.Params.avatarDensity; |
98 | ComputeAvatarVolumeAndMass(); | 109 | ComputeAvatarVolumeAndMass(); // set _avatarVolume and _mass based on capsule size, _density and _scale |
99 | DetailLog("{0},BSCharacter.create,call,size={1},scale={2},density={3},volume={4},mass={5}", | 110 | |
100 | LocalID, _size, Scale, _avatarDensity, _avatarVolume, RawMass); | 111 | ShapeData shapeData = new ShapeData(); |
112 | shapeData.ID = _localID; | ||
113 | shapeData.Type = ShapeData.PhysicsShapeType.SHAPE_AVATAR; | ||
114 | shapeData.Position = _position; | ||
115 | shapeData.Rotation = _orientation; | ||
116 | shapeData.Velocity = _velocity; | ||
117 | shapeData.Scale = _scale; | ||
118 | shapeData.Mass = _mass; | ||
119 | shapeData.Buoyancy = _buoyancy; | ||
120 | shapeData.Static = ShapeData.numericFalse; | ||
121 | shapeData.Friction = _scene.Params.avatarFriction; | ||
122 | shapeData.Restitution = _scene.Params.avatarRestitution; | ||
101 | 123 | ||
102 | // do actual create at taint time | 124 | // do actual create at taint time |
103 | PhysicsScene.TaintedObject("BSCharacter.create", delegate() | 125 | _scene.TaintedObject("BSCharacter.create", delegate() |
104 | { | 126 | { |
105 | DetailLog("{0},BSCharacter.create,taint", LocalID); | 127 | BulletSimAPI.CreateObject(parent_scene.WorldID, shapeData); |
106 | // New body and shape into BSBody and BSShape | ||
107 | PhysicsScene.Shapes.GetBodyAndShape(true, PhysicsScene.World, this, null, null); | ||
108 | 128 | ||
109 | SetPhysicalProperties(); | 129 | m_body = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID)); |
130 | // avatars get all collisions no matter what | ||
131 | BulletSimAPI.AddToCollisionFlags2(Body.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); | ||
110 | }); | 132 | }); |
133 | |||
111 | return; | 134 | return; |
112 | } | 135 | } |
113 | 136 | ||
114 | // called when this character is being destroyed and the resources should be released | 137 | // called when this character is being destroyed and the resources should be released |
115 | public override void Destroy() | 138 | public void Destroy() |
116 | { | 139 | { |
117 | DetailLog("{0},BSCharacter.Destroy", LocalID); | 140 | // DetailLog("{0},BSCharacter.Destroy", LocalID); |
118 | PhysicsScene.TaintedObject("BSCharacter.destroy", delegate() | 141 | _scene.TaintedObject("BSCharacter.destroy", delegate() |
119 | { | 142 | { |
120 | PhysicsScene.Shapes.DereferenceBody(PhysBody, true, null); | 143 | BulletSimAPI.DestroyObject(_scene.WorldID, _localID); |
121 | PhysicsScene.Shapes.DereferenceShape(PhysShape, true, null); | ||
122 | }); | 144 | }); |
123 | } | 145 | } |
124 | 146 | ||
125 | private void SetPhysicalProperties() | ||
126 | { | ||
127 | BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, PhysBody.ptr); | ||
128 | |||
129 | ZeroMotion(); | ||
130 | ForcePosition = _position; | ||
131 | // Set the velocity and compute the proper friction | ||
132 | ForceVelocity = _velocity; | ||
133 | |||
134 | BulletSimAPI.SetRestitution2(PhysBody.ptr, PhysicsScene.Params.avatarRestitution); | ||
135 | BulletSimAPI.SetMargin2(PhysShape.ptr, PhysicsScene.Params.collisionMargin); | ||
136 | BulletSimAPI.SetLocalScaling2(PhysShape.ptr, Scale); | ||
137 | BulletSimAPI.SetContactProcessingThreshold2(PhysBody.ptr, PhysicsScene.Params.contactProcessingThreshold); | ||
138 | if (PhysicsScene.Params.ccdMotionThreshold > 0f) | ||
139 | { | ||
140 | BulletSimAPI.SetCcdMotionThreshold2(PhysBody.ptr, PhysicsScene.Params.ccdMotionThreshold); | ||
141 | BulletSimAPI.SetCcdSweptSphereRadius2(PhysBody.ptr, PhysicsScene.Params.ccdSweptSphereRadius); | ||
142 | } | ||
143 | |||
144 | UpdatePhysicalMassProperties(RawMass); | ||
145 | |||
146 | // Make so capsule does not fall over | ||
147 | BulletSimAPI.SetAngularFactorV2(PhysBody.ptr, OMV.Vector3.Zero); | ||
148 | |||
149 | BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.CF_CHARACTER_OBJECT); | ||
150 | |||
151 | BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, PhysBody.ptr); | ||
152 | |||
153 | // BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.ACTIVE_TAG); | ||
154 | BulletSimAPI.ForceActivationState2(PhysBody.ptr, ActivationState.DISABLE_DEACTIVATION); | ||
155 | BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, PhysBody.ptr); | ||
156 | |||
157 | // Do this after the object has been added to the world | ||
158 | BulletSimAPI.SetCollisionFilterMask2(PhysBody.ptr, | ||
159 | (uint)CollisionFilterGroups.AvatarFilter, | ||
160 | (uint)CollisionFilterGroups.AvatarMask); | ||
161 | } | ||
162 | |||
163 | public override void RequestPhysicsterseUpdate() | 147 | public override void RequestPhysicsterseUpdate() |
164 | { | 148 | { |
165 | base.RequestPhysicsterseUpdate(); | 149 | base.RequestPhysicsterseUpdate(); |
166 | } | 150 | } |
167 | // No one calls this method so I don't know what it could possibly mean | 151 | // No one calls this method so I don't know what it could possibly mean |
168 | public override bool Stopped { get { return false; } } | 152 | public override bool Stopped { |
169 | 153 | get { return false; } | |
170 | public override OMV.Vector3 Size { | 154 | } |
155 | public override Vector3 Size { | ||
171 | get | 156 | get |
172 | { | 157 | { |
173 | // Avatar capsule size is kept in the scale parameter. | 158 | // Avatar capsule size is kept in the scale parameter. |
174 | // return _size; | 159 | return new Vector3(_scale.X * 2, _scale.Y * 2, _scale.Z); |
175 | return new OMV.Vector3(Scale.X * 2f, Scale.Y * 2f, Scale.Z); | ||
176 | } | 160 | } |
177 | 161 | ||
178 | set { | 162 | set { |
179 | // When an avatar's size is set, only the height is changed. | 163 | // When an avatar's size is set, only the height is changed |
164 | // and that really only depends on the radius. | ||
180 | _size = value; | 165 | _size = value; |
181 | ComputeAvatarScale(_size); | 166 | _scale.Z = (_size.Z * 1.15f) - (_scale.X + _scale.Y); |
167 | |||
168 | // TODO: something has to be done with the avatar's vertical position | ||
169 | |||
182 | ComputeAvatarVolumeAndMass(); | 170 | ComputeAvatarVolumeAndMass(); |
183 | DetailLog("{0},BSCharacter.setSize,call,scale={1},density={2},volume={3},mass={4}", | ||
184 | LocalID, Scale, _avatarDensity, _avatarVolume, RawMass); | ||
185 | 171 | ||
186 | PhysicsScene.TaintedObject("BSCharacter.setSize", delegate() | 172 | _scene.TaintedObject("BSCharacter.setSize", delegate() |
187 | { | 173 | { |
188 | BulletSimAPI.SetLocalScaling2(PhysShape.ptr, Scale); | 174 | BulletSimAPI.SetObjectScaleMass(_scene.WorldID, LocalID, _scale, _mass, true); |
189 | UpdatePhysicalMassProperties(RawMass); | ||
190 | }); | 175 | }); |
191 | 176 | ||
192 | } | 177 | } |
193 | } | 178 | } |
194 | 179 | public override PrimitiveBaseShape Shape { | |
195 | public override OMV.Vector3 Scale { get; set; } | 180 | set { _pbs = value; |
196 | 181 | } | |
197 | public override PrimitiveBaseShape Shape | ||
198 | { | ||
199 | set { BaseShape = value; } | ||
200 | } | 182 | } |
201 | // I want the physics engine to make an avatar capsule | 183 | public override uint LocalID { |
202 | public override ShapeData.PhysicsShapeType PreferredPhysicalShape | 184 | set { _localID = value; |
203 | { | 185 | } |
204 | get {return ShapeData.PhysicsShapeType.SHAPE_AVATAR; } | 186 | get { return _localID; } |
205 | } | 187 | } |
206 | 188 | public override bool Grabbed { | |
207 | public override bool Grabbed { | 189 | set { _grabbed = value; |
208 | set { _grabbed = value; } | 190 | } |
209 | } | 191 | } |
210 | public override bool Selected { | 192 | public override bool Selected { |
211 | set { _selected = value; } | 193 | set { _selected = value; |
194 | } | ||
212 | } | 195 | } |
213 | public override void CrossingFailure() { return; } | 196 | public override void CrossingFailure() { return; } |
214 | public override void link(PhysicsActor obj) { return; } | 197 | public override void link(PhysicsActor obj) { return; } |
215 | public override void delink() { return; } | 198 | public override void delink() { return; } |
199 | public override void LockAngularMotion(Vector3 axis) { return; } | ||
216 | 200 | ||
217 | // Set motion values to zero. | 201 | public override Vector3 Position { |
218 | // Do it to the properties so the values get set in the physics engine. | ||
219 | // Push the setting of the values to the viewer. | ||
220 | // Called at taint time! | ||
221 | public override void ZeroMotion() | ||
222 | { | ||
223 | _velocity = OMV.Vector3.Zero; | ||
224 | _acceleration = OMV.Vector3.Zero; | ||
225 | _rotationalVelocity = OMV.Vector3.Zero; | ||
226 | |||
227 | // Zero some other properties directly into the physics engine | ||
228 | BulletSimAPI.SetLinearVelocity2(PhysBody.ptr, OMV.Vector3.Zero); | ||
229 | BulletSimAPI.SetAngularVelocity2(PhysBody.ptr, OMV.Vector3.Zero); | ||
230 | BulletSimAPI.SetInterpolationVelocity2(PhysBody.ptr, OMV.Vector3.Zero, OMV.Vector3.Zero); | ||
231 | BulletSimAPI.ClearForces2(PhysBody.ptr); | ||
232 | } | ||
233 | |||
234 | public override void LockAngularMotion(OMV.Vector3 axis) { return; } | ||
235 | |||
236 | public override OMV.Vector3 RawPosition | ||
237 | { | ||
238 | get { return _position; } | ||
239 | set { _position = value; } | ||
240 | } | ||
241 | public override OMV.Vector3 Position { | ||
242 | get { | 202 | get { |
243 | // Don't refetch the position because this function is called a zillion times | 203 | // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID); |
244 | // _position = BulletSimAPI.GetObjectPosition2(Scene.World.ptr, LocalID); | 204 | return _position; |
245 | return _position; | 205 | } |
246 | } | ||
247 | set { | 206 | set { |
248 | _position = value; | 207 | _position = value; |
249 | PositionSanityCheck(); | 208 | PositionSanityCheck(); |
250 | 209 | ||
251 | PhysicsScene.TaintedObject("BSCharacter.setPosition", delegate() | 210 | _scene.TaintedObject("BSCharacter.setPosition", delegate() |
252 | { | 211 | { |
253 | DetailLog("{0},BSCharacter.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); | 212 | DetailLog("{0},BSCharacter.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); |
254 | BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); | 213 | BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation); |
255 | }); | 214 | }); |
256 | } | 215 | } |
257 | } | ||
258 | public override OMV.Vector3 ForcePosition { | ||
259 | get { | ||
260 | _position = BulletSimAPI.GetPosition2(PhysBody.ptr); | ||
261 | return _position; | ||
262 | } | ||
263 | set { | ||
264 | _position = value; | ||
265 | PositionSanityCheck(); | ||
266 | BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); | ||
267 | } | ||
268 | } | 216 | } |
269 | 217 | ||
270 | |||
271 | // Check that the current position is sane and, if not, modify the position to make it so. | 218 | // Check that the current position is sane and, if not, modify the position to make it so. |
272 | // Check for being below terrain or on water. | 219 | // Check for being below terrain and being out of bounds. |
273 | // Returns 'true' of the position was made sane by some action. | 220 | // Returns 'true' of the position was made sane by some action. |
274 | private bool PositionSanityCheck() | 221 | private bool PositionSanityCheck() |
275 | { | 222 | { |
276 | bool ret = false; | 223 | bool ret = false; |
277 | 224 | ||
278 | // If below the ground, move the avatar up | 225 | // If below the ground, move the avatar up |
279 | float terrainHeight = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(_position); | 226 | float terrainHeight = Scene.GetTerrainHeightAtXYZ(_position); |
280 | if (Position.Z < terrainHeight) | 227 | if (_position.Z < terrainHeight) |
281 | { | 228 | { |
282 | DetailLog("{0},BSCharacter.PositionAdjustUnderGround,call,pos={1},terrain={2}", LocalID, _position, terrainHeight); | 229 | DetailLog("{0},BSCharacter.PositionAdjustUnderGround,call,pos={1},orient={2}", LocalID, _position, _orientation); |
283 | _position.Z = terrainHeight + 2.0f; | 230 | _position.Z = terrainHeight + 2.0f; |
284 | ret = true; | 231 | ret = true; |
285 | } | 232 | } |
286 | if ((CurrentCollisionFlags & CollisionFlags.BS_FLOATS_ON_WATER) != 0) | ||
287 | { | ||
288 | float waterHeight = PhysicsScene.GetWaterLevelAtXYZ(_position); | ||
289 | if (Position.Z < waterHeight) | ||
290 | { | ||
291 | _position.Z = waterHeight; | ||
292 | ret = true; | ||
293 | } | ||
294 | } | ||
295 | 233 | ||
296 | // TODO: check for out of bounds | 234 | // TODO: check for out of bounds |
297 | return ret; | ||
298 | } | ||
299 | 235 | ||
300 | // A version of the sanity check that also makes sure a new position value is | ||
301 | // pushed back to the physics engine. This routine would be used by anyone | ||
302 | // who is not already pushing the value. | ||
303 | private bool PositionSanityCheck(bool inTaintTime) | ||
304 | { | ||
305 | bool ret = false; | ||
306 | if (PositionSanityCheck()) | ||
307 | { | ||
308 | // The new position value must be pushed into the physics engine but we can't | ||
309 | // just assign to "Position" because of potential call loops. | ||
310 | PhysicsScene.TaintedObject(inTaintTime, "BSCharacter.PositionSanityCheck", delegate() | ||
311 | { | ||
312 | DetailLog("{0},BSCharacter.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation); | ||
313 | BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); | ||
314 | }); | ||
315 | ret = true; | ||
316 | } | ||
317 | return ret; | 236 | return ret; |
318 | } | 237 | } |
319 | 238 | ||
320 | public override float Mass { get { return _mass; } } | 239 | public override float Mass { |
321 | 240 | get { | |
322 | // used when we only want this prim's mass and not the linkset thing | 241 | return _mass; |
323 | public override float RawMass { | 242 | } |
324 | get {return _mass; } | ||
325 | } | ||
326 | public override void UpdatePhysicalMassProperties(float physMass) | ||
327 | { | ||
328 | OMV.Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(PhysShape.ptr, physMass); | ||
329 | BulletSimAPI.SetMassProps2(PhysBody.ptr, physMass, localInertia); | ||
330 | } | 243 | } |
331 | 244 | public override Vector3 Force { | |
332 | public override OMV.Vector3 Force { | 245 | get { return _force; } |
333 | get { return _force; } | ||
334 | set { | 246 | set { |
335 | _force = value; | 247 | _force = value; |
336 | // m_log.DebugFormat("{0}: Force = {1}", LogHeader, _force); | 248 | // m_log.DebugFormat("{0}: Force = {1}", LogHeader, _force); |
337 | PhysicsScene.TaintedObject("BSCharacter.SetForce", delegate() | 249 | Scene.TaintedObject("BSCharacter.SetForce", delegate() |
338 | { | 250 | { |
339 | DetailLog("{0},BSCharacter.setForce,taint,force={1}", LocalID, _force); | 251 | DetailLog("{0},BSCharacter.setForce,taint,force={1}", LocalID, _force); |
340 | BulletSimAPI.SetObjectForce2(PhysBody.ptr, _force); | 252 | BulletSimAPI.SetObjectForce(Scene.WorldID, LocalID, _force); |
341 | }); | 253 | }); |
342 | } | 254 | } |
343 | } | 255 | } |
344 | 256 | ||
345 | // Avatars don't do vehicles | 257 | public override int VehicleType { |
346 | public override int VehicleType { get { return (int)Vehicle.TYPE_NONE; } set { return; } } | 258 | get { return 0; } |
259 | set { return; } | ||
260 | } | ||
347 | public override void VehicleFloatParam(int param, float value) { } | 261 | public override void VehicleFloatParam(int param, float value) { } |
348 | public override void VehicleVectorParam(int param, OMV.Vector3 value) {} | 262 | public override void VehicleVectorParam(int param, Vector3 value) {} |
349 | public override void VehicleRotationParam(int param, OMV.Quaternion rotation) { } | 263 | public override void VehicleRotationParam(int param, Quaternion rotation) { } |
350 | public override void VehicleFlags(int param, bool remove) { } | 264 | public override void VehicleFlags(int param, bool remove) { } |
351 | 265 | ||
352 | // Allows the detection of collisions with inherently non-physical prims. see llVolumeDetect for more | 266 | // Allows the detection of collisions with inherently non-physical prims. see llVolumeDetect for more |
353 | public override void SetVolumeDetect(int param) { return; } | 267 | public override void SetVolumeDetect(int param) { return; } |
354 | 268 | ||
355 | public override OMV.Vector3 GeometricCenter { get { return OMV.Vector3.Zero; } } | 269 | public override Vector3 GeometricCenter { get { return Vector3.Zero; } } |
356 | public override OMV.Vector3 CenterOfMass { get { return OMV.Vector3.Zero; } } | 270 | public override Vector3 CenterOfMass { get { return Vector3.Zero; } } |
357 | public override OMV.Vector3 Velocity { | 271 | public override Vector3 Velocity { |
358 | get { return _velocity; } | 272 | get { return _velocity; } |
359 | set { | 273 | set { |
360 | _velocity = value; | 274 | _velocity = value; |
361 | // m_log.DebugFormat("{0}: set velocity = {1}", LogHeader, _velocity); | 275 | // m_log.DebugFormat("{0}: set velocity = {1}", LogHeader, _velocity); |
362 | PhysicsScene.TaintedObject("BSCharacter.setVelocity", delegate() | 276 | _scene.TaintedObject("BSCharacter.setVelocity", delegate() |
363 | { | 277 | { |
364 | DetailLog("{0},BSCharacter.setVelocity,taint,vel={1}", LocalID, _velocity); | 278 | DetailLog("{0},BSCharacter.setVelocity,taint,vel={1}", LocalID, _velocity); |
365 | ForceVelocity = _velocity; | 279 | BulletSimAPI.SetObjectVelocity(_scene.WorldID, _localID, _velocity); |
366 | }); | 280 | }); |
367 | } | 281 | } |
368 | } | ||
369 | public override OMV.Vector3 ForceVelocity { | ||
370 | get { return _velocity; } | ||
371 | set { | ||
372 | // Depending on whether the avatar is moving or not, change the friction | ||
373 | // to keep the avatar from slipping around | ||
374 | if (_velocity.Length() == 0) | ||
375 | { | ||
376 | if (_currentFriction != PhysicsScene.Params.avatarStandingFriction) | ||
377 | { | ||
378 | _currentFriction = PhysicsScene.Params.avatarStandingFriction; | ||
379 | BulletSimAPI.SetFriction2(PhysBody.ptr, _currentFriction); | ||
380 | } | ||
381 | } | ||
382 | else | ||
383 | { | ||
384 | if (_currentFriction != PhysicsScene.Params.avatarFriction) | ||
385 | { | ||
386 | _currentFriction = PhysicsScene.Params.avatarFriction; | ||
387 | BulletSimAPI.SetFriction2(PhysBody.ptr, _currentFriction); | ||
388 | } | ||
389 | } | ||
390 | _velocity = value; | ||
391 | // Remember the set velocity so we can suppress the reduction by friction, ... | ||
392 | _appliedVelocity = value; | ||
393 | |||
394 | BulletSimAPI.SetLinearVelocity2(PhysBody.ptr, _velocity); | ||
395 | BulletSimAPI.Activate2(PhysBody.ptr, true); | ||
396 | } | ||
397 | } | 282 | } |
398 | public override OMV.Vector3 Torque { | 283 | public override Vector3 Torque { |
399 | get { return _torque; } | 284 | get { return _torque; } |
400 | set { _torque = value; | 285 | set { _torque = value; |
401 | } | 286 | } |
402 | } | 287 | } |
403 | public override float CollisionScore { | 288 | public override float CollisionScore { |
404 | get { return _collisionScore; } | 289 | get { return _collisionScore; } |
405 | set { _collisionScore = value; | 290 | set { _collisionScore = value; |
406 | } | 291 | } |
407 | } | 292 | } |
408 | public override OMV.Vector3 Acceleration { | 293 | public override Vector3 Acceleration { |
409 | get { return _acceleration; } | 294 | get { return _acceleration; } |
410 | set { _acceleration = value; } | 295 | set { _acceleration = value; } |
411 | } | 296 | } |
412 | public override OMV.Quaternion RawOrientation | 297 | public override Quaternion Orientation { |
413 | { | 298 | get { return _orientation; } |
414 | get { return _orientation; } | ||
415 | set { _orientation = value; } | ||
416 | } | ||
417 | public override OMV.Quaternion Orientation { | ||
418 | get { return _orientation; } | ||
419 | set { | 299 | set { |
420 | _orientation = value; | 300 | _orientation = value; |
421 | // m_log.DebugFormat("{0}: set orientation to {1}", LogHeader, _orientation); | 301 | // m_log.DebugFormat("{0}: set orientation to {1}", LogHeader, _orientation); |
422 | PhysicsScene.TaintedObject("BSCharacter.setOrientation", delegate() | 302 | _scene.TaintedObject("BSCharacter.setOrientation", delegate() |
423 | { | 303 | { |
424 | // _position = BulletSimAPI.GetPosition2(BSBody.ptr); | 304 | // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID); |
425 | BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); | 305 | BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation); |
426 | }); | 306 | }); |
427 | } | 307 | } |
428 | } | 308 | } |
429 | // Go directly to Bullet to get/set the value. | 309 | public override int PhysicsActorType { |
430 | public override OMV.Quaternion ForceOrientation | 310 | get { return _physicsActorType; } |
431 | { | 311 | set { _physicsActorType = value; |
432 | get | 312 | } |
433 | { | ||
434 | _orientation = BulletSimAPI.GetOrientation2(PhysBody.ptr); | ||
435 | return _orientation; | ||
436 | } | ||
437 | set | ||
438 | { | ||
439 | _orientation = value; | ||
440 | BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); | ||
441 | } | ||
442 | } | ||
443 | public override int PhysicsActorType { | ||
444 | get { return _physicsActorType; } | ||
445 | set { _physicsActorType = value; | ||
446 | } | ||
447 | } | 313 | } |
448 | public override bool IsPhysical { | 314 | public override bool IsPhysical { |
449 | get { return _isPhysical; } | 315 | get { return _isPhysical; } |
450 | set { _isPhysical = value; | 316 | set { _isPhysical = value; |
451 | } | 317 | } |
452 | } | ||
453 | public override bool IsSolid { | ||
454 | get { return true; } | ||
455 | } | 318 | } |
456 | public override bool IsStatic { | 319 | public override bool Flying { |
457 | get { return false; } | 320 | get { return _flying; } |
458 | } | ||
459 | public override bool Flying { | ||
460 | get { return _flying; } | ||
461 | set { | 321 | set { |
462 | _flying = value; | 322 | if (_flying != value) |
463 | // simulate flying by changing the effect of gravity | 323 | { |
464 | Buoyancy = ComputeBuoyancyFromFlying(_flying); | 324 | _flying = value; |
465 | } | 325 | // simulate flying by changing the effect of gravity |
326 | this.Buoyancy = ComputeBuoyancyFromFlying(_flying); | ||
327 | } | ||
328 | } | ||
466 | } | 329 | } |
467 | // Flying is implimented by changing the avatar's buoyancy. | ||
468 | // Would this be done better with a vehicle type? | ||
469 | private float ComputeBuoyancyFromFlying(bool ifFlying) { | 330 | private float ComputeBuoyancyFromFlying(bool ifFlying) { |
470 | return ifFlying ? 1f : 0f; | 331 | return ifFlying ? 1f : 0f; |
471 | } | 332 | } |
472 | public override bool | 333 | public override bool |
473 | SetAlwaysRun { | 334 | SetAlwaysRun { |
474 | get { return _setAlwaysRun; } | 335 | get { return _setAlwaysRun; } |
475 | set { _setAlwaysRun = value; } | 336 | set { _setAlwaysRun = value; } |
476 | } | 337 | } |
477 | public override bool ThrottleUpdates { | 338 | public override bool ThrottleUpdates { |
478 | get { return _throttleUpdates; } | 339 | get { return _throttleUpdates; } |
479 | set { _throttleUpdates = value; } | 340 | set { _throttleUpdates = value; } |
480 | } | 341 | } |
481 | public override bool IsColliding { | 342 | public override bool IsColliding { |
482 | get { return (CollidingStep == PhysicsScene.SimulationStep); } | 343 | get { return (_collidingStep == _scene.SimulationStep); } |
483 | set { _isColliding = value; } | 344 | set { _isColliding = value; } |
484 | } | 345 | } |
485 | public override bool CollidingGround { | 346 | public override bool CollidingGround { |
486 | get { return (CollidingGroundStep == PhysicsScene.SimulationStep); } | 347 | get { return (_collidingGroundStep == _scene.SimulationStep); } |
487 | set { CollidingGround = value; } | 348 | set { _collidingGround = value; } |
488 | } | ||
489 | public override bool CollidingObj { | ||
490 | get { return _collidingObj; } | ||
491 | set { _collidingObj = value; } | ||
492 | } | 349 | } |
493 | public override bool FloatOnWater { | 350 | public override bool CollidingObj { |
494 | set { | 351 | get { return _collidingObj; } |
495 | _floatOnWater = value; | 352 | set { _collidingObj = value; } |
496 | PhysicsScene.TaintedObject("BSCharacter.setFloatOnWater", delegate() | ||
497 | { | ||
498 | if (_floatOnWater) | ||
499 | CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_FLOATS_ON_WATER); | ||
500 | else | ||
501 | CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_FLOATS_ON_WATER); | ||
502 | }); | ||
503 | } | ||
504 | } | 353 | } |
505 | public override OMV.Vector3 RotationalVelocity { | 354 | public override bool FloatOnWater { |
506 | get { return _rotationalVelocity; } | 355 | set { _floatOnWater = value; } |
507 | set { _rotationalVelocity = value; } | ||
508 | } | 356 | } |
509 | public override OMV.Vector3 ForceRotationalVelocity { | 357 | public override Vector3 RotationalVelocity { |
510 | get { return _rotationalVelocity; } | 358 | get { return _rotationalVelocity; } |
511 | set { _rotationalVelocity = value; } | 359 | set { _rotationalVelocity = value; } |
512 | } | 360 | } |
513 | public override bool Kinematic { | 361 | public override bool Kinematic { |
514 | get { return _kinematic; } | 362 | get { return _kinematic; } |
515 | set { _kinematic = value; } | 363 | set { _kinematic = value; } |
516 | } | 364 | } |
517 | // neg=fall quickly, 0=1g, 1=0g, pos=float up | 365 | // neg=fall quickly, 0=1g, 1=0g, pos=float up |
518 | public override float Buoyancy { | 366 | public override float Buoyancy { |
519 | get { return _buoyancy; } | 367 | get { return _buoyancy; } |
520 | set { _buoyancy = value; | 368 | set { _buoyancy = value; |
521 | PhysicsScene.TaintedObject("BSCharacter.setBuoyancy", delegate() | 369 | _scene.TaintedObject("BSCharacter.setBuoyancy", delegate() |
522 | { | 370 | { |
523 | DetailLog("{0},BSCharacter.setBuoyancy,taint,buoy={1}", LocalID, _buoyancy); | 371 | DetailLog("{0},BSCharacter.setBuoyancy,taint,buoy={1}", LocalID, _buoyancy); |
524 | ForceBuoyancy = _buoyancy; | 372 | BulletSimAPI.SetObjectBuoyancy(_scene.WorldID, LocalID, _buoyancy); |
525 | }); | 373 | }); |
526 | } | 374 | } |
527 | } | ||
528 | public override float ForceBuoyancy { | ||
529 | get { return _buoyancy; } | ||
530 | set { _buoyancy = value; | ||
531 | DetailLog("{0},BSCharacter.setForceBuoyancy,taint,buoy={1}", LocalID, _buoyancy); | ||
532 | // Buoyancy is faked by changing the gravity applied to the object | ||
533 | float grav = PhysicsScene.Params.gravity * (1f - _buoyancy); | ||
534 | BulletSimAPI.SetGravity2(PhysBody.ptr, new OMV.Vector3(0f, 0f, grav)); | ||
535 | } | ||
536 | } | 375 | } |
537 | 376 | ||
538 | // Used for MoveTo | 377 | // Used for MoveTo |
539 | public override OMV.Vector3 PIDTarget { | 378 | public override Vector3 PIDTarget { |
540 | set { _PIDTarget = value; } | 379 | set { _PIDTarget = value; } |
541 | } | 380 | } |
542 | public override bool PIDActive { | 381 | public override bool PIDActive { |
543 | set { _usePID = value; } | 382 | set { _usePID = value; } |
544 | } | 383 | } |
545 | public override float PIDTau { | 384 | public override float PIDTau { |
546 | set { _PIDTau = value; } | 385 | set { _PIDTau = value; } |
547 | } | 386 | } |
548 | 387 | ||
549 | // Used for llSetHoverHeight and maybe vehicle height | 388 | // Used for llSetHoverHeight and maybe vehicle height |
550 | // Hover Height will override MoveTo target's Z | 389 | // Hover Height will override MoveTo target's Z |
551 | public override bool PIDHoverActive { | 390 | public override bool PIDHoverActive { |
552 | set { _useHoverPID = value; } | 391 | set { _useHoverPID = value; } |
553 | } | 392 | } |
554 | public override float PIDHoverHeight { | 393 | public override float PIDHoverHeight { |
555 | set { _PIDHoverHeight = value; } | 394 | set { _PIDHoverHeight = value; } |
556 | } | 395 | } |
557 | public override PIDHoverType PIDHoverType { | 396 | public override PIDHoverType PIDHoverType { |
558 | set { _PIDHoverType = value; } | 397 | set { _PIDHoverType = value; } |
559 | } | 398 | } |
560 | public override float PIDHoverTau { | 399 | public override float PIDHoverTau { |
561 | set { _PIDHoverTao = value; } | 400 | set { _PIDHoverTao = value; } |
562 | } | 401 | } |
563 | 402 | ||
564 | // For RotLookAt | 403 | // For RotLookAt |
565 | public override OMV.Quaternion APIDTarget { set { return; } } | 404 | public override Quaternion APIDTarget { set { return; } } |
566 | public override bool APIDActive { set { return; } } | 405 | public override bool APIDActive { set { return; } } |
567 | public override float APIDStrength { set { return; } } | 406 | public override float APIDStrength { set { return; } } |
568 | public override float APIDDamping { set { return; } } | 407 | public override float APIDDamping { set { return; } } |
569 | 408 | ||
570 | public override void AddForce(OMV.Vector3 force, bool pushforce) { | 409 | public override void AddForce(Vector3 force, bool pushforce) { |
571 | if (force.IsFinite()) | 410 | if (force.IsFinite()) |
572 | { | 411 | { |
573 | _force.X += force.X; | 412 | _force.X += force.X; |
574 | _force.Y += force.Y; | 413 | _force.Y += force.Y; |
575 | _force.Z += force.Z; | 414 | _force.Z += force.Z; |
576 | // m_log.DebugFormat("{0}: AddForce. adding={1}, newForce={2}", LogHeader, force, _force); | 415 | // m_log.DebugFormat("{0}: AddForce. adding={1}, newForce={2}", LogHeader, force, _force); |
577 | PhysicsScene.TaintedObject("BSCharacter.AddForce", delegate() | 416 | _scene.TaintedObject("BSCharacter.AddForce", delegate() |
578 | { | 417 | { |
579 | DetailLog("{0},BSCharacter.setAddForce,taint,addedForce={1}", LocalID, _force); | 418 | DetailLog("{0},BSCharacter.setAddForce,taint,addedForce={1}", LocalID, _force); |
580 | BulletSimAPI.SetObjectForce2(PhysBody.ptr, _force); | 419 | BulletSimAPI.AddObjectForce2(Body.Ptr, _force); |
581 | }); | 420 | }); |
582 | } | 421 | } |
583 | else | 422 | else |
@@ -587,75 +426,129 @@ public sealed class BSCharacter : BSPhysObject | |||
587 | //m_lastUpdateSent = false; | 426 | //m_lastUpdateSent = false; |
588 | } | 427 | } |
589 | 428 | ||
590 | public override void AddAngularForce(OMV.Vector3 force, bool pushforce) { | 429 | public override void AddAngularForce(Vector3 force, bool pushforce) { |
591 | } | 430 | } |
592 | public override void SetMomentum(OMV.Vector3 momentum) { | 431 | public override void SetMomentum(Vector3 momentum) { |
593 | } | 432 | } |
594 | 433 | ||
595 | private void ComputeAvatarScale(OMV.Vector3 size) | 434 | // Turn on collision events at a rate no faster than one every the given milliseconds |
596 | { | 435 | public override void SubscribeEvents(int ms) { |
597 | // The 'size' given by the simulator is the mid-point of the avatar | 436 | _subscribedEventsMs = ms; |
598 | // and X and Y are unspecified. | 437 | if (ms > 0) |
599 | 438 | { | |
600 | OMV.Vector3 newScale = OMV.Vector3.Zero; | 439 | // make sure first collision happens |
601 | newScale.X = PhysicsScene.Params.avatarCapsuleRadius; | 440 | _nextCollisionOkTime = Util.EnvironmentTickCount() - _subscribedEventsMs; |
602 | newScale.Y = PhysicsScene.Params.avatarCapsuleRadius; | ||
603 | 441 | ||
604 | // From the total height, remove the capsule half spheres that are at each end | 442 | Scene.TaintedObject("BSCharacter.SubscribeEvents", delegate() |
605 | newScale.Z = size.Z- (newScale.X + newScale.Y); | 443 | { |
606 | Scale = newScale; | 444 | BulletSimAPI.AddToCollisionFlags2(Body.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); |
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); | ||
607 | } | 460 | } |
608 | 461 | ||
609 | // set _avatarVolume and _mass based on capsule size, _density and Scale | 462 | // set _avatarVolume and _mass based on capsule size, _density and _scale |
610 | private void ComputeAvatarVolumeAndMass() | 463 | private void ComputeAvatarVolumeAndMass() |
611 | { | 464 | { |
612 | _avatarVolume = (float)( | 465 | _avatarVolume = (float)( |
613 | Math.PI | 466 | Math.PI |
614 | * Scale.X | 467 | * _scale.X |
615 | * Scale.Y // the area of capsule cylinder | 468 | * _scale.Y // the area of capsule cylinder |
616 | * Scale.Z // times height of capsule cylinder | 469 | * _scale.Z // times height of capsule cylinder |
617 | + 1.33333333f | 470 | + 1.33333333f |
618 | * Math.PI | 471 | * Math.PI |
619 | * Scale.X | 472 | * _scale.X |
620 | * Math.Min(Scale.X, Scale.Y) | 473 | * Math.Min(_scale.X, _scale.Y) |
621 | * Scale.Y // plus the volume of the capsule end caps | 474 | * _scale.Y // plus the volume of the capsule end caps |
622 | ); | 475 | ); |
623 | _mass = _avatarDensity * _avatarVolume; | 476 | _mass = _density * _avatarVolume; |
624 | } | 477 | } |
625 | 478 | ||
626 | // The physics engine says that properties have updated. Update same and inform | 479 | // The physics engine says that properties have updated. Update same and inform |
627 | // the world that things have changed. | 480 | // the world that things have changed. |
628 | public override void UpdateProperties(EntityProperties entprop) | 481 | public void UpdateProperties(EntityProperties entprop) |
629 | { | 482 | { |
630 | _position = entprop.Position; | 483 | _position = entprop.Position; |
631 | _orientation = entprop.Rotation; | 484 | _orientation = entprop.Rotation; |
632 | _velocity = entprop.Velocity; | 485 | _velocity = entprop.Velocity; |
633 | _acceleration = entprop.Acceleration; | 486 | _acceleration = entprop.Acceleration; |
634 | _rotationalVelocity = entprop.RotationalVelocity; | 487 | _rotationalVelocity = entprop.RotationalVelocity; |
635 | // Do some sanity checking for the avatar. Make sure it's above ground and inbounds. | 488 | // Avatars don't report their changes the usual way. Changes are checked for in the heartbeat loop. |
636 | PositionSanityCheck(true); | 489 | // base.RequestPhysicsterseUpdate(); |
490 | |||
491 | /* | ||
492 | DetailLog("{0},BSCharacter.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}", | ||
493 | LocalID, entprop.Position, entprop.Rotation, entprop.Velocity, | ||
494 | entprop.Acceleration, entprop.RotationalVelocity); | ||
495 | */ | ||
496 | } | ||
637 | 497 | ||
638 | // remember the current and last set values | 498 | // Called by the scene when a collision with this object is reported |
639 | LastEntityProperties = CurrentEntityProperties; | 499 | // The collision, if it should be reported to the character, is placed in a collection |
640 | CurrentEntityProperties = entprop; | 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); | ||
641 | 505 | ||
642 | if (entprop.Velocity != LastEntityProperties.Velocity) | 506 | // The following makes IsColliding() and IsCollidingGround() work |
507 | _collidingStep = _scene.SimulationStep; | ||
508 | if (collidingWith == BSScene.TERRAIN_ID || collidingWith == BSScene.GROUNDPLANE_ID) | ||
643 | { | 509 | { |
644 | // Changes in the velocity are suppressed in avatars. | 510 | _collidingGroundStep = _scene.SimulationStep; |
645 | // That's just the way they are defined. | ||
646 | OMV.Vector3 avVel = new OMV.Vector3(_appliedVelocity.X, _appliedVelocity.Y, entprop.Velocity.Z); | ||
647 | _velocity = avVel; | ||
648 | BulletSimAPI.SetLinearVelocity2(PhysBody.ptr, avVel); | ||
649 | } | 511 | } |
512 | // DetailLog("{0},BSCharacter.Collison,call,with={1}", LocalID, collidingWith); | ||
650 | 513 | ||
651 | // Tell the linkset about value changes | 514 | // throttle collisions to the rate specified in the subscription |
652 | Linkset.UpdateProperties(this); | 515 | if (_subscribedEventsMs != 0) { |
516 | int nowTime = _scene.SimulationNowTime; | ||
517 | if (nowTime >= _nextCollisionOkTime) { | ||
518 | _nextCollisionOkTime = nowTime + _subscribedEventsMs; | ||
653 | 519 | ||
654 | // Avatars don't report their changes the usual way. Changes are checked for in the heartbeat loop. | 520 | if (collisionCollection == null) |
655 | // base.RequestPhysicsterseUpdate(); | 521 | collisionCollection = new CollisionEventUpdate(); |
522 | collisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth)); | ||
523 | } | ||
524 | } | ||
525 | } | ||
656 | 526 | ||
657 | DetailLog("{0},BSCharacter.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}", | 527 | public void SendCollisions() |
658 | LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity); | 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); | ||
659 | } | 552 | } |
660 | } | 553 | } |
661 | } | 554 | } |