aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs')
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs451
1 files changed, 451 insertions, 0 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
new file mode 100644
index 0000000..682eb80
--- /dev/null
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
@@ -0,0 +1,451 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyrightD
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27using System;
28using System.Collections.Generic;
29using System.Reflection;
30using log4net;
31using OpenMetaverse;
32using OpenSim.Framework;
33using OpenSim.Region.Physics.Manager;
34
35namespace OpenSim.Region.Physics.BulletSPlugin
36{
37public class BSCharacter : PhysicsActor
38{
39 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
40 private static readonly string LogHeader = "[BULLETS CHAR]";
41
42 private BSScene _scene;
43 private String _avName;
44 private bool _stopped;
45 private Vector3 _size;
46 private Vector3 _scale;
47 private PrimitiveBaseShape _pbs;
48 private uint _localID = 0;
49 private bool _grabbed;
50 private bool _selected;
51 private Vector3 _position;
52 private float _mass;
53 public float _density;
54 public float _avatarVolume;
55 private Vector3 _force;
56 private Vector3 _velocity;
57 private Vector3 _torque;
58 private float _collisionScore;
59 private Vector3 _acceleration;
60 private Quaternion _orientation;
61 private int _physicsActorType;
62 private bool _isPhysical;
63 private bool _flying;
64 private bool _setAlwaysRun;
65 private bool _throttleUpdates;
66 private bool _isColliding;
67 private long _collidingStep;
68 private bool _collidingGround;
69 private long _collidingGroundStep;
70 private bool _collidingObj;
71 private bool _floatOnWater;
72 private Vector3 _rotationalVelocity;
73 private bool _kinematic;
74 private float _buoyancy;
75
76 private int _subscribedEventsMs = 0;
77 private int _lastCollisionTime = 0;
78
79 private Vector3 _PIDTarget;
80 private bool _usePID;
81 private float _PIDTau;
82 private bool _useHoverPID;
83 private float _PIDHoverHeight;
84 private PIDHoverType _PIDHoverType;
85 private float _PIDHoverTao;
86
87 public BSCharacter(uint localID, String avName, BSScene parent_scene, Vector3 pos, Vector3 size, bool isFlying)
88 {
89 _localID = localID;
90 _avName = avName;
91 _scene = parent_scene;
92 _position = pos;
93 _size = size;
94 _flying = isFlying;
95 _orientation = Quaternion.Identity;
96 _velocity = Vector3.Zero;
97 _buoyancy = isFlying ? 1f : 0f;
98 _scale = new Vector3(1f, 1f, 1f);
99 _density = _scene.Params.avatarDensity;
100 ComputeAvatarVolumeAndMass(); // set _avatarVolume and _mass based on capsule size, _density and _scale
101
102 ShapeData shapeData = new ShapeData();
103 shapeData.ID = _localID;
104 shapeData.Type = ShapeData.PhysicsShapeType.SHAPE_AVATAR;
105 shapeData.Position = _position;
106 shapeData.Rotation = _orientation;
107 shapeData.Velocity = _velocity;
108 shapeData.Scale = _scale;
109 shapeData.Mass = _mass;
110 shapeData.Buoyancy = _buoyancy;
111 shapeData.Static = ShapeData.numericFalse;
112 shapeData.Friction = _scene.Params.avatarFriction;
113 shapeData.Restitution = _scene.Params.defaultRestitution;
114
115 // do actual create at taint time
116 _scene.TaintedObject(delegate()
117 {
118 BulletSimAPI.CreateObject(parent_scene.WorldID, shapeData);
119 });
120
121 return;
122 }
123
124 // called when this character is being destroyed and the resources should be released
125 public void Destroy()
126 {
127 _scene.TaintedObject(delegate()
128 {
129 BulletSimAPI.DestroyObject(_scene.WorldID, _localID);
130 });
131 }
132
133 public override void RequestPhysicsterseUpdate()
134 {
135 base.RequestPhysicsterseUpdate();
136 }
137
138 public override bool Stopped {
139 get { return _stopped; }
140 }
141 public override Vector3 Size {
142 get { return _size; }
143 set { _size = value;
144 }
145 }
146 public override PrimitiveBaseShape Shape {
147 set { _pbs = value;
148 }
149 }
150 public override uint LocalID {
151 set { _localID = value;
152 }
153 get { return _localID; }
154 }
155 public override bool Grabbed {
156 set { _grabbed = value;
157 }
158 }
159 public override bool Selected {
160 set { _selected = value;
161 }
162 }
163 public override void CrossingFailure() { return; }
164 public override void link(PhysicsActor obj) { return; }
165 public override void delink() { return; }
166 public override void LockAngularMotion(Vector3 axis) { return; }
167
168 public override Vector3 Position {
169 get {
170 // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID);
171 return _position;
172 }
173 set {
174 _position = value;
175 _scene.TaintedObject(delegate()
176 {
177 BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation);
178 });
179 }
180 }
181 public override float Mass {
182 get {
183 return _mass;
184 }
185 }
186 public override Vector3 Force {
187 get { return _force; }
188 set {
189 _force = value;
190 // m_log.DebugFormat("{0}: Force = {1}", LogHeader, _force);
191 _scene.TaintedObject(delegate()
192 {
193 BulletSimAPI.SetObjectForce(_scene.WorldID, _localID, _force);
194 });
195 }
196 }
197
198 public override int VehicleType {
199 get { return 0; }
200 set { return; }
201 }
202 public override void VehicleFloatParam(int param, float value) { }
203 public override void VehicleVectorParam(int param, Vector3 value) {}
204 public override void VehicleRotationParam(int param, Quaternion rotation) { }
205 public override void VehicleFlags(int param, bool remove) { }
206
207 // Allows the detection of collisions with inherently non-physical prims. see llVolumeDetect for more
208 public override void SetVolumeDetect(int param) { return; }
209
210 public override Vector3 GeometricCenter { get { return Vector3.Zero; } }
211 public override Vector3 CenterOfMass { get { return Vector3.Zero; } }
212 public override Vector3 Velocity {
213 get { return _velocity; }
214 set {
215 _velocity = value;
216 // m_log.DebugFormat("{0}: set velocity = {1}", LogHeader, _velocity);
217 _scene.TaintedObject(delegate()
218 {
219 BulletSimAPI.SetObjectVelocity(_scene.WorldID, _localID, _velocity);
220 });
221 }
222 }
223 public override Vector3 Torque {
224 get { return _torque; }
225 set { _torque = value;
226 }
227 }
228 public override float CollisionScore {
229 get { return _collisionScore; }
230 set { _collisionScore = value;
231 }
232 }
233 public override Vector3 Acceleration {
234 get { return _acceleration; }
235 }
236 public override Quaternion Orientation {
237 get { return _orientation; }
238 set {
239 _orientation = value;
240 // m_log.DebugFormat("{0}: set orientation to {1}", LogHeader, _orientation);
241 _scene.TaintedObject(delegate()
242 {
243 // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID);
244 BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation);
245 });
246 }
247 }
248 public override int PhysicsActorType {
249 get { return _physicsActorType; }
250 set { _physicsActorType = value;
251 }
252 }
253 public override bool IsPhysical {
254 get { return _isPhysical; }
255 set { _isPhysical = value;
256 }
257 }
258 public override bool Flying {
259 get { return _flying; }
260 set {
261 _flying = value;
262 _scene.TaintedObject(delegate()
263 {
264 // simulate flying by changing the effect of gravity
265 BulletSimAPI.SetObjectBuoyancy(_scene.WorldID, LocalID, _flying ? 1f : 0f);
266 });
267 }
268 }
269 public override bool
270 SetAlwaysRun {
271 get { return _setAlwaysRun; }
272 set { _setAlwaysRun = value; }
273 }
274 public override bool ThrottleUpdates {
275 get { return _throttleUpdates; }
276 set { _throttleUpdates = value; }
277 }
278 public override bool IsColliding {
279 get { return (_collidingStep == _scene.SimulationStep); }
280 set { _isColliding = value; }
281 }
282 public override bool CollidingGround {
283 get { return (_collidingGroundStep == _scene.SimulationStep); }
284 set { _collidingGround = value; }
285 }
286 public override bool CollidingObj {
287 get { return _collidingObj; }
288 set { _collidingObj = value; }
289 }
290 public override bool FloatOnWater {
291 set { _floatOnWater = value; }
292 }
293 public override Vector3 RotationalVelocity {
294 get { return _rotationalVelocity; }
295 set { _rotationalVelocity = value; }
296 }
297 public override bool Kinematic {
298 get { return _kinematic; }
299 set { _kinematic = value; }
300 }
301 public override float Buoyancy {
302 get { return _buoyancy; }
303 set { _buoyancy = value;
304 _scene.TaintedObject(delegate()
305 {
306 BulletSimAPI.SetObjectBuoyancy(_scene.WorldID, LocalID, _buoyancy);
307 });
308 }
309 }
310
311 // Used for MoveTo
312 public override Vector3 PIDTarget {
313 set { _PIDTarget = value; }
314 }
315 public override bool PIDActive {
316 set { _usePID = value; }
317 }
318 public override float PIDTau {
319 set { _PIDTau = value; }
320 }
321
322 // Used for llSetHoverHeight and maybe vehicle height
323 // Hover Height will override MoveTo target's Z
324 public override bool PIDHoverActive {
325 set { _useHoverPID = value; }
326 }
327 public override float PIDHoverHeight {
328 set { _PIDHoverHeight = value; }
329 }
330 public override PIDHoverType PIDHoverType {
331 set { _PIDHoverType = value; }
332 }
333 public override float PIDHoverTau {
334 set { _PIDHoverTao = value; }
335 }
336
337 // For RotLookAt
338 public override Quaternion APIDTarget { set { return; } }
339 public override bool APIDActive { set { return; } }
340 public override float APIDStrength { set { return; } }
341 public override float APIDDamping { set { return; } }
342
343 public override void AddForce(Vector3 force, bool pushforce) {
344 if (force.IsFinite())
345 {
346 _force.X += force.X;
347 _force.Y += force.Y;
348 _force.Z += force.Z;
349 // m_log.DebugFormat("{0}: AddForce. adding={1}, newForce={2}", LogHeader, force, _force);
350 _scene.TaintedObject(delegate()
351 {
352 BulletSimAPI.SetObjectForce(_scene.WorldID, _localID, _force);
353 });
354 }
355 else
356 {
357 m_log.WarnFormat("{0}: Got a NaN force applied to a Character", LogHeader);
358 }
359 //m_lastUpdateSent = false;
360 }
361 public override void AddAngularForce(Vector3 force, bool pushforce) {
362 }
363 public override void SetMomentum(Vector3 momentum) {
364 }
365 public override void SubscribeEvents(int ms) {
366 _subscribedEventsMs = ms;
367 _lastCollisionTime = Util.EnvironmentTickCount() - _subscribedEventsMs; // make first collision happen
368 }
369 public override void UnSubscribeEvents() {
370 _subscribedEventsMs = 0;
371 }
372 public override bool SubscribedEvents() {
373 return (_subscribedEventsMs > 0);
374 }
375
376 // set _avatarVolume and _mass based on capsule size, _density and _scale
377 private void ComputeAvatarVolumeAndMass()
378 {
379 _avatarVolume = (float)(
380 Math.PI
381 * _scene.Params.avatarCapsuleRadius * _scale.X
382 * _scene.Params.avatarCapsuleRadius * _scale.Y
383 * _scene.Params.avatarCapsuleHeight * _scale.Z);
384 _mass = _density * _avatarVolume;
385 }
386
387 // The physics engine says that properties have updated. Update same and inform
388 // the world that things have changed.
389 public void UpdateProperties(EntityProperties entprop)
390 {
391 bool changed = false;
392 // we assign to the local variables so the normal set action does not happen
393 if (_position != entprop.Position)
394 {
395 _position = entprop.Position;
396 changed = true;
397 }
398 if (_orientation != entprop.Rotation)
399 {
400 _orientation = entprop.Rotation;
401 changed = true;
402 }
403 if (_velocity != entprop.Velocity)
404 {
405 _velocity = entprop.Velocity;
406 changed = true;
407 }
408 if (_acceleration != entprop.Acceleration)
409 {
410 _acceleration = entprop.Acceleration;
411 changed = true;
412 }
413 if (_rotationalVelocity != entprop.RotationalVelocity)
414 {
415 _rotationalVelocity = entprop.RotationalVelocity;
416 changed = true;
417 }
418 if (changed)
419 {
420 // m_log.DebugFormat("{0}: UpdateProperties: id={1}, c={2}, pos={3}, rot={4}", LogHeader, LocalID, changed, _position, _orientation);
421 // Avatar movement is not done by generating this event. There is a system that
422 // checks for avatar updates each heartbeat loop.
423 // base.RequestPhysicsterseUpdate();
424 }
425 }
426
427 public void Collide(uint collidingWith, ActorTypes type, Vector3 contactPoint, Vector3 contactNormal, float pentrationDepth)
428 {
429 // m_log.DebugFormat("{0}: Collide: ms={1}, id={2}, with={3}", LogHeader, _subscribedEventsMs, LocalID, collidingWith);
430
431 // The following makes IsColliding() and IsCollidingGround() work
432 _collidingStep = _scene.SimulationStep;
433 if (collidingWith == BSScene.TERRAIN_ID || collidingWith == BSScene.GROUNDPLANE_ID)
434 {
435 _collidingGroundStep = _scene.SimulationStep;
436 }
437
438 // throttle collisions to the rate specified in the subscription
439 if (_subscribedEventsMs == 0) return; // don't want collisions
440 int nowTime = _scene.SimulationNowTime;
441 if (nowTime < (_lastCollisionTime + _subscribedEventsMs)) return;
442 _lastCollisionTime = nowTime;
443
444 Dictionary<uint, ContactPoint> contactPoints = new Dictionary<uint, ContactPoint>();
445 contactPoints.Add(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth));
446 CollisionEventUpdate args = new CollisionEventUpdate(LocalID, (int)type, 1, contactPoints);
447 base.SendCollisionUpdate(args);
448 }
449
450}
451}