123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434 |
- /*
- * Copyright (c) Contributors, http://opensimulator.org/
- * See CONTRIBUTORS.TXT for a full list of copyright holders.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyrightD
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither the name of the OpenSimulator Project nor the
- * names of its contributors may be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
- using System;
- using System.Reflection;
- using System.Collections.Generic;
- using System.Xml;
- using log4net;
- using OMV = OpenMetaverse;
- using OpenSim.Framework;
- using OpenSim.Region.Physics.Manager;
- using OpenSim.Region.Physics.ConvexDecompositionDotNet;
- namespace OpenSim.Region.Physics.BulletSPlugin
- {
- [Serializable]
- public sealed class BSPrim : BSPhysObject
- {
- private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
- private static readonly string LogHeader = "[BULLETS PRIM]";
- // _size is what the user passed. Scale is what we pass to the physics engine with the mesh.
- // Often Scale is unity because the meshmerizer will apply _size when creating the mesh.
- private OMV.Vector3 _size; // the multiplier for each mesh dimension as passed by the user
- private bool _grabbed;
- private bool _isSelected;
- private bool _isVolumeDetect;
- private OMV.Vector3 _position;
- private float _mass; // the mass of this object
- private float _density;
- private OMV.Vector3 _force;
- private OMV.Vector3 _velocity;
- private OMV.Vector3 _torque;
- private float _collisionScore;
- private OMV.Vector3 _acceleration;
- private OMV.Quaternion _orientation;
- private int _physicsActorType;
- private bool _isPhysical;
- private bool _flying;
- private float _friction;
- private float _restitution;
- private bool _setAlwaysRun;
- private bool _throttleUpdates;
- private bool _isColliding;
- private bool _collidingGround;
- private bool _collidingObj;
- private bool _floatOnWater;
- private OMV.Vector3 _rotationalVelocity;
- private bool _kinematic;
- private float _buoyancy;
- private BSDynamics _vehicle;
- private OMV.Vector3 _PIDTarget;
- private bool _usePID;
- private float _PIDTau;
- private bool _useHoverPID;
- private float _PIDHoverHeight;
- private PIDHoverType _PIDHoverType;
- private float _PIDHoverTao;
- public BSPrim(uint localID, String primName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 size,
- OMV.Quaternion rotation, PrimitiveBaseShape pbs, bool pisPhysical)
- : base(parent_scene, localID, primName, "BSPrim")
- {
- // m_log.DebugFormat("{0}: BSPrim creation of {1}, id={2}", LogHeader, primName, localID);
- _physicsActorType = (int)ActorTypes.Prim;
- _position = pos;
- _size = size;
- Scale = size; // the scale will be set by CreateGeom depending on object type
- _orientation = rotation;
- _buoyancy = 1f;
- _velocity = OMV.Vector3.Zero;
- _rotationalVelocity = OMV.Vector3.Zero;
- BaseShape = pbs;
- _isPhysical = pisPhysical;
- _isVolumeDetect = false;
- _friction = PhysicsScene.Params.defaultFriction; // TODO: compute based on object material
- _density = PhysicsScene.Params.defaultDensity; // TODO: compute based on object material
- _restitution = PhysicsScene.Params.defaultRestitution;
- _vehicle = new BSDynamics(PhysicsScene, this); // add vehicleness
- _mass = CalculateMass();
- // No body or shape yet
- PhysBody = new BulletBody(LocalID, IntPtr.Zero);
- PhysShape = new BulletShape(IntPtr.Zero);
- DetailLog("{0},BSPrim.constructor,call", LocalID);
- // do the actual object creation at taint time
- PhysicsScene.TaintedObject("BSPrim.create", delegate()
- {
- CreateGeomAndObject(true);
- CurrentCollisionFlags = BulletSimAPI.GetCollisionFlags2(PhysBody.ptr);
- });
- }
- // called when this prim is being destroyed and we should free all the resources
- public override void Destroy()
- {
- // m_log.DebugFormat("{0}: Destroy, id={1}", LogHeader, LocalID);
- // Undo any links between me and any other object
- BSPhysObject parentBefore = Linkset.LinksetRoot;
- int childrenBefore = Linkset.NumberOfChildren;
- Linkset = Linkset.RemoveMeFromLinkset(this);
- DetailLog("{0},BSPrim.Destroy,call,parentBefore={1},childrenBefore={2},parentAfter={3},childrenAfter={4}",
- LocalID, parentBefore.LocalID, childrenBefore, Linkset.LinksetRoot.LocalID, Linkset.NumberOfChildren);
- // Undo any vehicle properties
- this.VehicleType = (int)Vehicle.TYPE_NONE;
- PhysicsScene.TaintedObject("BSPrim.destroy", delegate()
- {
- DetailLog("{0},BSPrim.Destroy,taint,", LocalID);
- // If there are physical body and shape, release my use of same.
- PhysicsScene.Shapes.DereferenceBody(PhysBody, true, null);
- PhysicsScene.Shapes.DereferenceShape(PhysShape, true, null);
- });
- }
- // No one uses this property.
- public override bool Stopped {
- get { return false; }
- }
- public override OMV.Vector3 Size {
- get { return _size; }
- set {
- // We presume the scale and size are the same. If scale must be changed for
- // the physical shape, that is done when the geometry is built.
- _size = value;
- ForceBodyShapeRebuild(false);
- }
- }
- // Scale is what we set in the physics engine. It is different than 'size' in that
- // 'size' can be encorporated into the mesh. In that case, the scale is <1,1,1>.
- public override OMV.Vector3 Scale { get; set; }
- public override PrimitiveBaseShape Shape {
- set {
- BaseShape = value;
- ForceBodyShapeRebuild(false);
- }
- }
- // Whatever the linkset wants is what I want.
- public override BSPhysicsShapeType PreferredPhysicalShape
- { get { return Linkset.PreferredPhysicalShape(this); } }
- public override bool ForceBodyShapeRebuild(bool inTaintTime)
- {
- LastAssetBuildFailed = false;
- PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ForceBodyShapeRebuild", delegate()
- {
- _mass = CalculateMass(); // changing the shape changes the mass
- CreateGeomAndObject(true);
- });
- return true;
- }
- public override bool Grabbed {
- set { _grabbed = value;
- }
- }
- public override bool Selected {
- set {
- _isSelected = value;
- PhysicsScene.TaintedObject("BSPrim.setSelected", delegate()
- {
- DetailLog("{0},BSPrim.selected,taint,selected={1}", LocalID, _isSelected);
- SetObjectDynamic(false);
- });
- }
- }
- public override void CrossingFailure() { return; }
- // link me to the specified parent
- public override void link(PhysicsActor obj) {
- BSPrim parent = obj as BSPrim;
- if (parent != null)
- {
- BSPhysObject parentBefore = Linkset.LinksetRoot;
- int childrenBefore = Linkset.NumberOfChildren;
- Linkset = parent.Linkset.AddMeToLinkset(this);
- DetailLog("{0},BSPrim.link,call,parentBefore={1}, childrenBefore=={2}, parentAfter={3}, childrenAfter={4}",
- LocalID, parentBefore.LocalID, childrenBefore, Linkset.LinksetRoot.LocalID, Linkset.NumberOfChildren);
- }
- return;
- }
- // delink me from my linkset
- public override void delink() {
- // TODO: decide if this parent checking needs to happen at taint time
- // Race condition here: if link() and delink() in same simulation tick, the delink will not happen
- BSPhysObject parentBefore = Linkset.LinksetRoot;
- int childrenBefore = Linkset.NumberOfChildren;
- Linkset = Linkset.RemoveMeFromLinkset(this);
- DetailLog("{0},BSPrim.delink,parentBefore={1},childrenBefore={2},parentAfter={3},childrenAfter={4}, ",
- LocalID, parentBefore.LocalID, childrenBefore, Linkset.LinksetRoot.LocalID, Linkset.NumberOfChildren);
- return;
- }
- // Set motion values to zero.
- // Do it to the properties so the values get set in the physics engine.
- // Push the setting of the values to the viewer.
- // Called at taint time!
- public override void ZeroMotion(bool inTaintTime)
- {
- _velocity = OMV.Vector3.Zero;
- _acceleration = OMV.Vector3.Zero;
- _rotationalVelocity = OMV.Vector3.Zero;
- // Zero some other properties in the physics engine
- PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ZeroMotion", delegate()
- {
- BulletSimAPI.ClearAllForces2(PhysBody.ptr);
- });
- }
- public override void ZeroAngularMotion(bool inTaintTime)
- {
- _rotationalVelocity = OMV.Vector3.Zero;
- // Zero some other properties in the physics engine
- PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ZeroMotion", delegate()
- {
- // DetailLog("{0},BSPrim.ZeroAngularMotion,call,rotVel={1}", LocalID, _rotationalVelocity);
- BulletSimAPI.SetInterpolationAngularVelocity2(PhysBody.ptr, _rotationalVelocity);
- BulletSimAPI.SetAngularVelocity2(PhysBody.ptr, _rotationalVelocity);
- });
- }
- public override void LockAngularMotion(OMV.Vector3 axis)
- {
- DetailLog("{0},BSPrim.LockAngularMotion,call,axis={1}", LocalID, axis);
- return;
- }
- public override OMV.Vector3 RawPosition
- {
- get { return _position; }
- set { _position = value; }
- }
- public override OMV.Vector3 Position {
- get {
- // child prims move around based on their parent. Need to get the latest location
- if (!Linkset.IsRoot(this))
- _position = Linkset.Position(this);
- // don't do the GetObjectPosition for root elements because this function is called a zillion times.
- // _position = BulletSimAPI.GetObjectPosition2(PhysicsScene.World.ptr, BSBody.ptr);
- return _position;
- }
- set {
- // If the position must be forced into the physics engine, use ForcePosition.
- if (_position == value)
- {
- return;
- }
- _position = value;
- // TODO: what does it mean to set the position of a child prim?? Rebuild the constraint?
- PositionSanityCheck(false);
- PhysicsScene.TaintedObject("BSPrim.setPosition", delegate()
- {
- // DetailLog("{0},BSPrim.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation);
- BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation);
- ActivateIfPhysical(false);
- });
- }
- }
- public override OMV.Vector3 ForcePosition {
- get {
- _position = BulletSimAPI.GetPosition2(PhysBody.ptr);
- return _position;
- }
- set {
- _position = value;
- // PositionSanityCheck(); // Don't do this! Causes a loop and caller should know better.
- BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation);
- ActivateIfPhysical(false);
- }
- }
- // Check that the current position is sane and, if not, modify the position to make it so.
- // Check for being below terrain and being out of bounds.
- // Returns 'true' of the position was made sane by some action.
- private bool PositionSanityCheck(bool inTaintTime)
- {
- bool ret = false;
- float terrainHeight = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(_position);
- OMV.Vector3 upForce = OMV.Vector3.Zero;
- if (Position.Z < terrainHeight)
- {
- DetailLog("{0},BSPrim.PositionAdjustUnderGround,call,pos={1},terrain={2}", LocalID, _position, terrainHeight);
- float targetHeight = terrainHeight + (Size.Z / 2f);
- // Upforce proportional to the distance away from the terrain. Correct the error in 1 sec.
- upForce.Z = (terrainHeight - Position.Z) * 1f;
- ret = true;
- }
- if ((CurrentCollisionFlags & CollisionFlags.BS_FLOATS_ON_WATER) != 0)
- {
- float waterHeight = PhysicsScene.TerrainManager.GetWaterLevelAtXYZ(_position);
- // TODO: a floating motor so object will bob in the water
- if (Math.Abs(Position.Z - waterHeight) > 0.1f)
- {
- // Upforce proportional to the distance away from the water. Correct the error in 1 sec.
- upForce.Z = (waterHeight - Position.Z) * 1f;
- ret = true;
- }
- }
- // TODO: check for out of bounds
- // The above code computes a force to apply to correct any out-of-bounds problems. Apply same.
- // TODO: This should be intergrated with a geneal physics action mechanism.
- // TODO: This should be moderated with PID'ness.
- if (ret)
- {
- // Apply upforce and overcome gravity.
- AddForce(upForce - PhysicsScene.DefaultGravity, false, inTaintTime);
- }
- return ret;
- }
- // Return the effective mass of the object.
- // If there are multiple items in the linkset, add them together for the root
- public override float Mass
- {
- get
- {
- return Linkset.LinksetMass;
- // return _mass;
- }
- }
- // used when we only want this prim's mass and not the linkset thing
- public override float RawMass {
- get { return _mass; }
- }
- // Set the physical mass to the passed mass.
- // Note that this does not change _mass!
- public override void UpdatePhysicalMassProperties(float physMass)
- {
- if (IsStatic)
- {
- Inertia = OMV.Vector3.Zero;
- BulletSimAPI.SetMassProps2(PhysBody.ptr, 0f, Inertia);
- BulletSimAPI.UpdateInertiaTensor2(PhysBody.ptr);
- }
- else
- {
- Inertia = BulletSimAPI.CalculateLocalInertia2(PhysShape.ptr, physMass);
- BulletSimAPI.SetMassProps2(PhysBody.ptr, physMass, Inertia);
- BulletSimAPI.UpdateInertiaTensor2(PhysBody.ptr);
- // center of mass is at the zero of the object
- // DEBUG DEBUG BulletSimAPI.SetCenterOfMassByPosRot2(PhysBody.ptr, ForcePosition, ForceOrientation);
- DetailLog("{0},BSPrim.UpdateMassProperties,mass={1},localInertia={2}", LocalID, physMass, Inertia);
- }
- }
- // Is this used?
- public override OMV.Vector3 CenterOfMass
- {
- get { return Linkset.CenterOfMass; }
- }
- // Is this used?
- public override OMV.Vector3 GeometricCenter
- {
- get { return Linkset.GeometricCenter; }
- }
- public override OMV.Vector3 Force {
- get { return _force; }
- set {
- _force = value;
- PhysicsScene.TaintedObject("BSPrim.setForce", delegate()
- {
- // DetailLog("{0},BSPrim.setForce,taint,force={1}", LocalID, _force);
- BulletSimAPI.SetObjectForce2(PhysBody.ptr, _force);
- });
- }
- }
- public override int VehicleType {
- get {
- return (int)_vehicle.Type; // if we are a vehicle, return that type
- }
- set {
- Vehicle type = (Vehicle)value;
- // Tell the scene about the vehicle so it will get processing each frame.
- PhysicsScene.VehicleInSceneTypeChanged(this, type);
- PhysicsScene.TaintedObject("setVehicleType", delegate()
- {
- // Done at taint time so we're sure the physics engine is not using the variables
- // Vehicle code changes the parameters for this vehicle type.
- _vehicle.ProcessTypeChange(type);
- ActivateIfPhysical(false);
- });
- }
- }
- public override void VehicleFloatParam(int param, float value)
- {
- PhysicsScene.TaintedObject("BSPrim.VehicleFloatParam", delegate()
- {
- _vehicle.ProcessFloatVehicleParam((Vehicle)param, value);
- ActivateIfPhysical(false);
- });
- }
- public override void VehicleVectorParam(int param, OMV.Vector3 value)
- {
- PhysicsScene.TaintedObject("BSPrim.VehicleVectorParam", delegate()
- {
- _vehicle.ProcessVectorVehicleParam((Vehicle)param, value);
- ActivateIfPhysical(false);
- });
- }
- public override void VehicleRotationParam(int param, OMV.Quaternion rotation)
- {
- PhysicsScene.TaintedObject("BSPrim.VehicleRotationParam", delegate()
- {
- _vehicle.ProcessRotationVehicleParam((Vehicle)param, rotation);
- ActivateIfPhysical(false);
- });
- }
- public override void VehicleFlags(int param, bool remove)
- {
- PhysicsScene.TaintedObject("BSPrim.VehicleFlags", delegate()
- {
- _vehicle.ProcessVehicleFlags(param, remove);
- });
- }
- // Called each simulation step to advance vehicle characteristics.
- // Called from Scene when doing simulation step so we're in taint processing time.
- public override void StepVehicle(float timeStep)
- {
- if (IsPhysical && _vehicle.IsActive)
- {
- _vehicle.Step(timeStep);
- /* // TEST TEST DEBUG DEBUG -- trying to reduce the extra action of Bullet simulation step
- PhysicsScene.PostTaintObject("BSPrim.StepVehicles", LocalID, delegate()
- {
- // This resets the interpolation values and recomputes the tensor variables
- BulletSimAPI.SetCenterOfMassByPosRot2(BSBody.ptr, ForcePosition, ForceOrientation);
- });
- */
- }
- }
- // Allows the detection of collisions with inherently non-physical prims. see llVolumeDetect for more
- public override void SetVolumeDetect(int param) {
- bool newValue = (param != 0);
- if (_isVolumeDetect != newValue)
- {
- _isVolumeDetect = newValue;
- PhysicsScene.TaintedObject("BSPrim.SetVolumeDetect", delegate()
- {
- // DetailLog("{0},setVolumeDetect,taint,volDetect={1}", LocalID, _isVolumeDetect);
- SetObjectDynamic(true);
- });
- }
- return;
- }
- public override OMV.Vector3 Velocity {
- get { return _velocity; }
- set {
- _velocity = value;
- PhysicsScene.TaintedObject("BSPrim.setVelocity", delegate()
- {
- // DetailLog("{0},BSPrim.SetVelocity,taint,vel={1}", LocalID, _velocity);
- BulletSimAPI.SetLinearVelocity2(PhysBody.ptr, _velocity);
- });
- }
- }
- public override OMV.Vector3 ForceVelocity {
- get { return _velocity; }
- set {
- _velocity = value;
- BulletSimAPI.SetLinearVelocity2(PhysBody.ptr, _velocity);
- }
- }
- public override OMV.Vector3 Torque {
- get { return _torque; }
- set {
- _torque = value;
- AddAngularForce(_torque, false, false);
- // DetailLog("{0},BSPrim.SetTorque,call,torque={1}", LocalID, _torque);
- }
- }
- public override float CollisionScore {
- get { return _collisionScore; }
- set { _collisionScore = value;
- }
- }
- public override OMV.Vector3 Acceleration {
- get { return _acceleration; }
- set { _acceleration = value; }
- }
- public override OMV.Quaternion RawOrientation
- {
- get { return _orientation; }
- set { _orientation = value; }
- }
- public override OMV.Quaternion Orientation {
- get {
- // Children move around because tied to parent. Get a fresh value.
- if (!Linkset.IsRoot(this))
- {
- _orientation = Linkset.Orientation(this);
- }
- return _orientation;
- }
- set {
- if (_orientation == value)
- return;
- _orientation = value;
- // TODO: what does it mean if a child in a linkset changes its orientation? Rebuild the constraint?
- PhysicsScene.TaintedObject("BSPrim.setOrientation", delegate()
- {
- // _position = BulletSimAPI.GetObjectPosition2(PhysicsScene.World.ptr, BSBody.ptr);
- // DetailLog("{0},BSPrim.setOrientation,taint,pos={1},orient={2}", LocalID, _position, _orientation);
- BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation);
- });
- }
- }
- // Go directly to Bullet to get/set the value.
- public override OMV.Quaternion ForceOrientation
- {
- get
- {
- _orientation = BulletSimAPI.GetOrientation2(PhysBody.ptr);
- return _orientation;
- }
- set
- {
- _orientation = value;
- BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation);
- }
- }
- public override int PhysicsActorType {
- get { return _physicsActorType; }
- set { _physicsActorType = value; }
- }
- public override bool IsPhysical {
- get { return _isPhysical; }
- set {
- if (_isPhysical != value)
- {
- _isPhysical = value;
- PhysicsScene.TaintedObject("BSPrim.setIsPhysical", delegate()
- {
- // DetailLog("{0},setIsPhysical,taint,isPhys={1}", LocalID, _isPhysical);
- SetObjectDynamic(true);
- // whether phys-to-static or static-to-phys, the object is not moving.
- ZeroMotion(true);
- });
- }
- }
- }
- // An object is static (does not move) if selected or not physical
- public override bool IsStatic
- {
- get { return _isSelected || !IsPhysical; }
- }
- // An object is solid if it's not phantom and if it's not doing VolumeDetect
- public override bool IsSolid
- {
- get { return !IsPhantom && !_isVolumeDetect; }
- }
- // Make gravity work if the object is physical and not selected
- // Called at taint-time!!
- private void SetObjectDynamic(bool forceRebuild)
- {
- // Recreate the physical object if necessary
- CreateGeomAndObject(forceRebuild);
- }
- // Convert the simulator's physical properties into settings on BulletSim objects.
- // There are four flags we're interested in:
- // IsStatic: Object does not move, otherwise the object has mass and moves
- // isSolid: other objects bounce off of this object
- // isVolumeDetect: other objects pass through but can generate collisions
- // collisionEvents: whether this object returns collision events
- private void UpdatePhysicalParameters()
- {
- // DetailLog("{0},BSPrim.UpdatePhysicalParameters,entry,body={1},shape={2}", LocalID, BSBody, BSShape);
- // Mangling all the physical properties requires the object not be in the physical world.
- // This is a NOOP if the object is not in the world (BulletSim and Bullet ignore objects not found).
- BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, PhysBody.ptr);
- // Set up the object physicalness (does gravity and collisions move this object)
- MakeDynamic(IsStatic);
- // Update vehicle specific parameters (after MakeDynamic() so can change physical parameters)
- _vehicle.Refresh();
- // Arrange for collision events if the simulator wants them
- EnableCollisions(SubscribedEvents());
- // Make solid or not (do things bounce off or pass through this object).
- MakeSolid(IsSolid);
- BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, PhysBody.ptr);
- // Rebuild its shape
- BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, PhysBody.ptr);
- // Collision filter can be set only when the object is in the world
- if (PhysBody.collisionFilter != 0 || PhysBody.collisionMask != 0)
- {
- BulletSimAPI.SetCollisionFilterMask2(PhysBody.ptr, (uint)PhysBody.collisionFilter, (uint)PhysBody.collisionMask);
- }
- // Recompute any linkset parameters.
- // When going from non-physical to physical, this re-enables the constraints that
- // had been automatically disabled when the mass was set to zero.
- // For compound based linksets, this enables and disables interactions of the children.
- Linkset.Refresh(this);
- DetailLog("{0},BSPrim.UpdatePhysicalParameters,taintExit,static={1},solid={2},mass={3},collide={4},cf={5:X},body={6},shape={7}",
- LocalID, IsStatic, IsSolid, _mass, SubscribedEvents(), CurrentCollisionFlags, PhysBody, PhysShape);
- }
- // "Making dynamic" means changing to and from static.
- // When static, gravity does not effect the object and it is fixed in space.
- // When dynamic, the object can fall and be pushed by others.
- // This is independent of its 'solidness' which controls what passes through
- // this object and what interacts with it.
- private void MakeDynamic(bool makeStatic)
- {
- if (makeStatic)
- {
- // Become a Bullet 'static' object type
- CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.CF_STATIC_OBJECT);
- // Stop all movement
- ZeroMotion(true);
- // Center of mass is at the center of the object
- // DEBUG DEBUG BulletSimAPI.SetCenterOfMassByPosRot2(Linkset.LinksetRoot.PhysBody.ptr, _position, _orientation);
- // Mass is zero which disables a bunch of physics stuff in Bullet
- UpdatePhysicalMassProperties(0f);
- // Set collision detection parameters
- if (PhysicsScene.Params.ccdMotionThreshold > 0f)
- {
- BulletSimAPI.SetCcdMotionThreshold2(PhysBody.ptr, PhysicsScene.Params.ccdMotionThreshold);
- BulletSimAPI.SetCcdSweptSphereRadius2(PhysBody.ptr, PhysicsScene.Params.ccdSweptSphereRadius);
- }
- // There can be special things needed for implementing linksets
- Linkset.MakeStatic(this);
- // The activation state is 'disabled' so Bullet will not try to act on it.
- BulletSimAPI.ForceActivationState2(PhysBody.ptr, ActivationState.DISABLE_SIMULATION);
- // Start it out sleeping and physical actions could wake it up.
- // BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.ISLAND_SLEEPING);
- PhysBody.collisionFilter = CollisionFilterGroups.StaticObjectFilter;
- PhysBody.collisionMask = CollisionFilterGroups.StaticObjectMask;
- }
- else
- {
- // Not a Bullet static object
- CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(PhysBody.ptr, CollisionFlags.CF_STATIC_OBJECT);
- // Set various physical properties so internal dynamic properties will get computed correctly as they are set
- BulletSimAPI.SetFriction2(PhysBody.ptr, PhysicsScene.Params.defaultFriction);
- BulletSimAPI.SetRestitution2(PhysBody.ptr, PhysicsScene.Params.defaultRestitution);
- // per http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=3382
- // Since this can be called multiple times, only zero forces when becoming physical
- // BulletSimAPI.ClearAllForces2(BSBody.ptr);
- // For good measure, make sure the transform is set through to the motion state
- BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation);
- // Center of mass is at the center of the object
- // DEBUG DEBUG BulletSimAPI.SetCenterOfMassByPosRot2(Linkset.LinksetRoot.PhysBody.ptr, _position, _orientation);
- // A dynamic object has mass
- UpdatePhysicalMassProperties(RawMass);
- // Set collision detection parameters
- if (PhysicsScene.Params.ccdMotionThreshold > 0f)
- {
- BulletSimAPI.SetCcdMotionThreshold2(PhysBody.ptr, PhysicsScene.Params.ccdMotionThreshold);
- BulletSimAPI.SetCcdSweptSphereRadius2(PhysBody.ptr, PhysicsScene.Params.ccdSweptSphereRadius);
- }
- // Various values for simulation limits
- BulletSimAPI.SetDamping2(PhysBody.ptr, PhysicsScene.Params.linearDamping, PhysicsScene.Params.angularDamping);
- BulletSimAPI.SetDeactivationTime2(PhysBody.ptr, PhysicsScene.Params.deactivationTime);
- BulletSimAPI.SetSleepingThresholds2(PhysBody.ptr, PhysicsScene.Params.linearSleepingThreshold, PhysicsScene.Params.angularSleepingThreshold);
- BulletSimAPI.SetContactProcessingThreshold2(PhysBody.ptr, PhysicsScene.Params.contactProcessingThreshold);
- // There might be special things needed for implementing linksets.
- Linkset.MakeDynamic(this);
- // Force activation of the object so Bullet will act on it.
- // Must do the ForceActivationState2() to overcome the DISABLE_SIMULATION from static objects.
- BulletSimAPI.ForceActivationState2(PhysBody.ptr, ActivationState.ACTIVE_TAG);
- // BulletSimAPI.Activate2(BSBody.ptr, true);
- PhysBody.collisionFilter = CollisionFilterGroups.ObjectFilter;
- PhysBody.collisionMask = CollisionFilterGroups.ObjectMask;
- }
- }
- // "Making solid" means that other object will not pass through this object.
- // To make transparent, we create a Bullet ghost object.
- // Note: This expects to be called from the UpdatePhysicalParameters() routine as
- // the functions after this one set up the state of a possibly newly created collision body.
- private void MakeSolid(bool makeSolid)
- {
- CollisionObjectTypes bodyType = (CollisionObjectTypes)BulletSimAPI.GetBodyType2(PhysBody.ptr);
- if (makeSolid)
- {
- // Verify the previous code created the correct shape for this type of thing.
- if ((bodyType & CollisionObjectTypes.CO_RIGID_BODY) == 0)
- {
- m_log.ErrorFormat("{0} MakeSolid: physical body of wrong type for solidity. id={1}, type={2}", LogHeader, LocalID, bodyType);
- }
- CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(PhysBody.ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE);
- }
- else
- {
- if ((bodyType & CollisionObjectTypes.CO_GHOST_OBJECT) == 0)
- {
- m_log.ErrorFormat("{0} MakeSolid: physical body of wrong type for non-solidness. id={1}, type={2}", LogHeader, LocalID, bodyType);
- }
- CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE);
- PhysBody.collisionFilter = CollisionFilterGroups.VolumeDetectFilter;
- PhysBody.collisionMask = CollisionFilterGroups.VolumeDetectMask;
- }
- }
- // Enable physical actions. Bullet will keep sleeping non-moving physical objects so
- // they need waking up when parameters are changed.
- // Called in taint-time!!
- private void ActivateIfPhysical(bool forceIt)
- {
- if (IsPhysical)
- BulletSimAPI.Activate2(PhysBody.ptr, forceIt);
- }
- // Turn on or off the flag controlling whether collision events are returned to the simulator.
- private void EnableCollisions(bool wantsCollisionEvents)
- {
- if (wantsCollisionEvents)
- {
- CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
- }
- else
- {
- CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
- }
- }
- // prims don't fly
- public override bool Flying {
- get { return _flying; }
- set {
- _flying = value;
- }
- }
- public override bool SetAlwaysRun {
- get { return _setAlwaysRun; }
- set { _setAlwaysRun = value; }
- }
- public override bool ThrottleUpdates {
- get { return _throttleUpdates; }
- set { _throttleUpdates = value; }
- }
- public override bool IsColliding {
- get { return (CollidingStep == PhysicsScene.SimulationStep); }
- set { _isColliding = value; }
- }
- public override bool CollidingGround {
- get { return (CollidingGroundStep == PhysicsScene.SimulationStep); }
- set { _collidingGround = value; }
- }
- public override bool CollidingObj {
- get { return _collidingObj; }
- set { _collidingObj = value; }
- }
- public bool IsPhantom {
- get {
- // SceneObjectPart removes phantom objects from the physics scene
- // so, although we could implement touching and such, we never
- // are invoked as a phantom object
- return false;
- }
- }
- public override bool FloatOnWater {
- set {
- _floatOnWater = value;
- PhysicsScene.TaintedObject("BSPrim.setFloatOnWater", delegate()
- {
- if (_floatOnWater)
- CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_FLOATS_ON_WATER);
- else
- CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_FLOATS_ON_WATER);
- });
- }
- }
- public override OMV.Vector3 RotationalVelocity {
- get {
- /*
- OMV.Vector3 pv = OMV.Vector3.Zero;
- // if close to zero, report zero
- // This is copied from ODE but I'm not sure why it returns zero but doesn't
- // zero the property in the physics engine.
- if (_rotationalVelocity.ApproxEquals(pv, 0.2f))
- return pv;
- */
- return _rotationalVelocity;
- }
- set {
- _rotationalVelocity = value;
- // m_log.DebugFormat("{0}: RotationalVelocity={1}", LogHeader, _rotationalVelocity);
- PhysicsScene.TaintedObject("BSPrim.setRotationalVelocity", delegate()
- {
- DetailLog("{0},BSPrim.SetRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity);
- BulletSimAPI.SetAngularVelocity2(PhysBody.ptr, _rotationalVelocity);
- });
- }
- }
- public override OMV.Vector3 ForceRotationalVelocity {
- get {
- return _rotationalVelocity;
- }
- set {
- _rotationalVelocity = value;
- BulletSimAPI.SetAngularVelocity2(PhysBody.ptr, _rotationalVelocity);
- }
- }
- public override bool Kinematic {
- get { return _kinematic; }
- set { _kinematic = value;
- // m_log.DebugFormat("{0}: Kinematic={1}", LogHeader, _kinematic);
- }
- }
- public override float Buoyancy {
- get { return _buoyancy; }
- set {
- _buoyancy = value;
- PhysicsScene.TaintedObject("BSPrim.setBuoyancy", delegate()
- {
- ForceBuoyancy = _buoyancy;
- });
- }
- }
- public override float ForceBuoyancy {
- get { return _buoyancy; }
- set {
- _buoyancy = value;
- // DetailLog("{0},BSPrim.setForceBuoyancy,taint,buoy={1}", LocalID, _buoyancy);
- // Buoyancy is faked by changing the gravity applied to the object
- float grav = PhysicsScene.Params.gravity * (1f - _buoyancy);
- BulletSimAPI.SetGravity2(PhysBody.ptr, new OMV.Vector3(0f, 0f, grav));
- }
- }
- // Used for MoveTo
- public override OMV.Vector3 PIDTarget {
- set { _PIDTarget = value; }
- }
- public override bool PIDActive {
- set { _usePID = value; }
- }
- public override float PIDTau {
- set { _PIDTau = value; }
- }
- // Used for llSetHoverHeight and maybe vehicle height
- // Hover Height will override MoveTo target's Z
- public override bool PIDHoverActive {
- set { _useHoverPID = value; }
- }
- public override float PIDHoverHeight {
- set { _PIDHoverHeight = value; }
- }
- public override PIDHoverType PIDHoverType {
- set { _PIDHoverType = value; }
- }
- public override float PIDHoverTau {
- set { _PIDHoverTao = value; }
- }
- // For RotLookAt
- public override OMV.Quaternion APIDTarget { set { return; } }
- public override bool APIDActive { set { return; } }
- public override float APIDStrength { set { return; } }
- public override float APIDDamping { set { return; } }
- private List<OMV.Vector3> m_accumulatedForces = new List<OMV.Vector3>();
- public override void AddForce(OMV.Vector3 force, bool pushforce) {
- AddForce(force, pushforce, false);
- }
- // Applying a force just adds this to the total force on the object.
- public void AddForce(OMV.Vector3 force, bool pushforce, bool inTaintTime) {
- // for an object, doesn't matter if force is a pushforce or not
- if (force.IsFinite())
- {
- // _force += force;
- lock (m_accumulatedForces)
- m_accumulatedForces.Add(new OMV.Vector3(force));
- }
- else
- {
- m_log.WarnFormat("{0}: Got a NaN force applied to a prim. LocalID={1}", LogHeader, LocalID);
- return;
- }
- PhysicsScene.TaintedObject(inTaintTime, "BSPrim.AddForce", delegate()
- {
- OMV.Vector3 fSum = OMV.Vector3.Zero;
- lock (m_accumulatedForces)
- {
- // Sum the accumulated additional forces for one big force to apply once.
- foreach (OMV.Vector3 v in m_accumulatedForces)
- {
- fSum += v;
- }
- m_accumulatedForces.Clear();
- }
- DetailLog("{0},BSPrim.AddForce,taint,force={1}", LocalID, fSum);
- if (fSum != OMV.Vector3.Zero)
- BulletSimAPI.ApplyCentralForce2(PhysBody.ptr, fSum);
- });
- }
- // An impulse force is scaled by the mass of the object.
- public void ApplyForceImpulse(OMV.Vector3 impulse, bool inTaintTime)
- {
- OMV.Vector3 applyImpulse = impulse;
- PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ApplyForceImpulse", delegate()
- {
- DetailLog("{0},BSPrim.ApplyForceImpulse,taint,tImpulse={1}", LocalID, applyImpulse);
- BulletSimAPI.ApplyCentralImpulse2(PhysBody.ptr, applyImpulse);
- });
- }
- private List<OMV.Vector3> m_accumulatedAngularForces = new List<OMV.Vector3>();
- public override void AddAngularForce(OMV.Vector3 force, bool pushforce) {
- AddAngularForce(force, pushforce, false);
- }
- public void AddAngularForce(OMV.Vector3 force, bool pushforce, bool inTaintTime)
- {
- if (force.IsFinite())
- {
- // _force += force;
- lock (m_accumulatedAngularForces)
- m_accumulatedAngularForces.Add(new OMV.Vector3(force));
- }
- else
- {
- m_log.WarnFormat("{0}: Got a NaN force applied to a prim. LocalID={1}", LogHeader, LocalID);
- return;
- }
- PhysicsScene.TaintedObject(inTaintTime, "BSPrim.AddAngularForce", delegate()
- {
- OMV.Vector3 fSum = OMV.Vector3.Zero;
- lock (m_accumulatedAngularForces)
- {
- // Sum the accumulated additional forces for one big force to apply once.
- foreach (OMV.Vector3 v in m_accumulatedAngularForces)
- {
- fSum += v;
- }
- m_accumulatedAngularForces.Clear();
- }
- DetailLog("{0},BSPrim.AddAngularForce,taint,aForce={1}", LocalID, fSum);
- if (fSum != OMV.Vector3.Zero)
- {
- BulletSimAPI.ApplyTorque2(PhysBody.ptr, fSum);
- _torque = fSum;
- }
- });
- }
- // A torque impulse.
- public void ApplyTorqueImpulse(OMV.Vector3 impulse, bool inTaintTime)
- {
- OMV.Vector3 applyImpulse = impulse;
- PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ApplyTorqueImpulse", delegate()
- {
- BulletSimAPI.ApplyTorqueImpulse2(PhysBody.ptr, applyImpulse);
- });
- }
- public override void SetMomentum(OMV.Vector3 momentum) {
- // DetailLog("{0},BSPrim.SetMomentum,call,mom={1}", LocalID, momentum);
- }
- #region Mass Calculation
- private float CalculateMass()
- {
- float volume = _size.X * _size.Y * _size.Z; // default
- float tmp;
- float returnMass = 0;
- float hollowAmount = (float)BaseShape.ProfileHollow * 2.0e-5f;
- float hollowVolume = hollowAmount * hollowAmount;
- switch (BaseShape.ProfileShape)
- {
- case ProfileShape.Square:
- // default box
- if (BaseShape.PathCurve == (byte)Extrusion.Straight)
- {
- if (hollowAmount > 0.0)
- {
- switch (BaseShape.HollowShape)
- {
- case HollowShape.Square:
- case HollowShape.Same:
- break;
- case HollowShape.Circle:
- hollowVolume *= 0.78539816339f;
- break;
- case HollowShape.Triangle:
- hollowVolume *= (0.5f * .5f);
- break;
- default:
- hollowVolume = 0;
- break;
- }
- volume *= (1.0f - hollowVolume);
- }
- }
- else if (BaseShape.PathCurve == (byte)Extrusion.Curve1)
- {
- //a tube
- volume *= 0.78539816339e-2f * (float)(200 - BaseShape.PathScaleX);
- tmp= 1.0f -2.0e-2f * (float)(200 - BaseShape.PathScaleY);
- volume -= volume*tmp*tmp;
- if (hollowAmount > 0.0)
- {
- hollowVolume *= hollowAmount;
- switch (BaseShape.HollowShape)
- {
- case HollowShape.Square:
- case HollowShape.Same:
- break;
- case HollowShape.Circle:
- hollowVolume *= 0.78539816339f;;
- break;
- case HollowShape.Triangle:
- hollowVolume *= 0.5f * 0.5f;
- break;
- default:
- hollowVolume = 0;
- break;
- }
- volume *= (1.0f - hollowVolume);
- }
- }
- break;
- case ProfileShape.Circle:
- if (BaseShape.PathCurve == (byte)Extrusion.Straight)
- {
- volume *= 0.78539816339f; // elipse base
- if (hollowAmount > 0.0)
- {
- switch (BaseShape.HollowShape)
- {
- case HollowShape.Same:
- case HollowShape.Circle:
- break;
- case HollowShape.Square:
- hollowVolume *= 0.5f * 2.5984480504799f;
- break;
- case HollowShape.Triangle:
- hollowVolume *= .5f * 1.27323954473516f;
- break;
- default:
- hollowVolume = 0;
- break;
- }
- volume *= (1.0f - hollowVolume);
- }
- }
- else if (BaseShape.PathCurve == (byte)Extrusion.Curve1)
- {
- volume *= 0.61685027506808491367715568749226e-2f * (float)(200 - BaseShape.PathScaleX);
- tmp = 1.0f - .02f * (float)(200 - BaseShape.PathScaleY);
- volume *= (1.0f - tmp * tmp);
- if (hollowAmount > 0.0)
- {
- // calculate the hollow volume by it's shape compared to the prim shape
- hollowVolume *= hollowAmount;
- switch (BaseShape.HollowShape)
- {
- case HollowShape.Same:
- case HollowShape.Circle:
- break;
- case HollowShape.Square:
- hollowVolume *= 0.5f * 2.5984480504799f;
- break;
- case HollowShape.Triangle:
- hollowVolume *= .5f * 1.27323954473516f;
- break;
- default:
- hollowVolume = 0;
- break;
- }
- volume *= (1.0f - hollowVolume);
- }
- }
- break;
- case ProfileShape.HalfCircle:
- if (BaseShape.PathCurve == (byte)Extrusion.Curve1)
- {
- volume *= 0.52359877559829887307710723054658f;
- }
- break;
- case ProfileShape.EquilateralTriangle:
- if (BaseShape.PathCurve == (byte)Extrusion.Straight)
- {
- volume *= 0.32475953f;
- if (hollowAmount > 0.0)
- {
- // calculate the hollow volume by it's shape compared to the prim shape
- switch (BaseShape.HollowShape)
- {
- case HollowShape.Same:
- case HollowShape.Triangle:
- hollowVolume *= .25f;
- break;
- case HollowShape.Square:
- hollowVolume *= 0.499849f * 3.07920140172638f;
- break;
- case HollowShape.Circle:
- // Hollow shape is a perfect cyllinder in respect to the cube's scale
- // Cyllinder hollow volume calculation
- hollowVolume *= 0.1963495f * 3.07920140172638f;
- break;
- default:
- hollowVolume = 0;
- break;
- }
- volume *= (1.0f - hollowVolume);
- }
- }
- else if (BaseShape.PathCurve == (byte)Extrusion.Curve1)
- {
- volume *= 0.32475953f;
- volume *= 0.01f * (float)(200 - BaseShape.PathScaleX);
- tmp = 1.0f - .02f * (float)(200 - BaseShape.PathScaleY);
- volume *= (1.0f - tmp * tmp);
- if (hollowAmount > 0.0)
- {
- hollowVolume *= hollowAmount;
- switch (BaseShape.HollowShape)
- {
- case HollowShape.Same:
- case HollowShape.Triangle:
- hollowVolume *= .25f;
- break;
- case HollowShape.Square:
- hollowVolume *= 0.499849f * 3.07920140172638f;
- break;
- case HollowShape.Circle:
- hollowVolume *= 0.1963495f * 3.07920140172638f;
- break;
- default:
- hollowVolume = 0;
- break;
- }
- volume *= (1.0f - hollowVolume);
- }
- }
- break;
- default:
- break;
- }
- float taperX1;
- float taperY1;
- float taperX;
- float taperY;
- float pathBegin;
- float pathEnd;
- float profileBegin;
- float profileEnd;
- if (BaseShape.PathCurve == (byte)Extrusion.Straight || BaseShape.PathCurve == (byte)Extrusion.Flexible)
- {
- taperX1 = BaseShape.PathScaleX * 0.01f;
- if (taperX1 > 1.0f)
- taperX1 = 2.0f - taperX1;
- taperX = 1.0f - taperX1;
- taperY1 = BaseShape.PathScaleY * 0.01f;
- if (taperY1 > 1.0f)
- taperY1 = 2.0f - taperY1;
- taperY = 1.0f - taperY1;
- }
- else
- {
- taperX = BaseShape.PathTaperX * 0.01f;
- if (taperX < 0.0f)
- taperX = -taperX;
- taperX1 = 1.0f - taperX;
- taperY = BaseShape.PathTaperY * 0.01f;
- if (taperY < 0.0f)
- taperY = -taperY;
- taperY1 = 1.0f - taperY;
- }
- volume *= (taperX1 * taperY1 + 0.5f * (taperX1 * taperY + taperX * taperY1) + 0.3333333333f * taperX * taperY);
- pathBegin = (float)BaseShape.PathBegin * 2.0e-5f;
- pathEnd = 1.0f - (float)BaseShape.PathEnd * 2.0e-5f;
- volume *= (pathEnd - pathBegin);
- // this is crude aproximation
- profileBegin = (float)BaseShape.ProfileBegin * 2.0e-5f;
- profileEnd = 1.0f - (float)BaseShape.ProfileEnd * 2.0e-5f;
- volume *= (profileEnd - profileBegin);
- returnMass = _density * volume;
- /* Comment out code that computes the mass of the linkset. That is done in the Linkset class.
- if (IsRootOfLinkset)
- {
- foreach (BSPrim prim in _childrenPrims)
- {
- returnMass += prim.CalculateMass();
- }
- }
- */
- if (returnMass <= 0)
- returnMass = 0.0001f;
- if (returnMass > PhysicsScene.MaximumObjectMass)
- returnMass = PhysicsScene.MaximumObjectMass;
- return returnMass;
- }// end CalculateMass
- #endregion Mass Calculation
- // Rebuild the geometry and object.
- // This is called when the shape changes so we need to recreate the mesh/hull.
- // Called at taint-time!!!
- private void CreateGeomAndObject(bool forceRebuild)
- {
- // If this prim is part of a linkset, we must remove and restore the physical
- // links if the body is rebuilt.
- bool needToRestoreLinkset = false;
- bool needToRestoreVehicle = false;
- // Create the correct physical representation for this type of object.
- // Updates PhysBody and PhysShape with the new information.
- // Ignore 'forceRebuild'. This routine makes the right choices and changes of necessary.
- // Returns 'true' if either the body or the shape was changed.
- PhysicsScene.Shapes.GetBodyAndShape(false, PhysicsScene.World, this, null, delegate(BulletBody dBody)
- {
- // Called if the current prim body is about to be destroyed.
- // Remove all the physical dependencies on the old body.
- // (Maybe someday make the changing of BSShape an event handled by BSLinkset.)
- needToRestoreLinkset = Linkset.RemoveBodyDependencies(this);
- needToRestoreVehicle = _vehicle.RemoveBodyDependencies(this);
- });
- if (needToRestoreLinkset)
- {
- // If physical body dependencies were removed, restore them
- Linkset.RestoreBodyDependencies(this);
- }
- if (needToRestoreVehicle)
- {
- // If physical body dependencies were removed, restore them
- _vehicle.RestoreBodyDependencies(this);
- }
- // Make sure the properties are set on the new object
- UpdatePhysicalParameters();
- return;
- }
- // The physics engine says that properties have updated. Update same and inform
- // the world that things have changed.
- // TODO: do we really need to check for changed? Maybe just copy values and call RequestPhysicsterseUpdate()
- enum UpdatedProperties {
- Position = 1 << 0,
- Rotation = 1 << 1,
- Velocity = 1 << 2,
- Acceleration = 1 << 3,
- RotationalVel = 1 << 4
- }
- const float ROTATION_TOLERANCE = 0.01f;
- const float VELOCITY_TOLERANCE = 0.001f;
- const float POSITION_TOLERANCE = 0.05f;
- const float ACCELERATION_TOLERANCE = 0.01f;
- const float ROTATIONAL_VELOCITY_TOLERANCE = 0.01f;
- public override void UpdateProperties(EntityProperties entprop)
- {
- // Updates only for individual prims and for the root object of a linkset.
- if (Linkset.IsRoot(this))
- {
- // A temporary kludge to suppress the rotational effects introduced on vehicles by Bullet
- // TODO: handle physics introduced by Bullet with computed vehicle physics.
- if (_vehicle.IsActive)
- {
- entprop.RotationalVelocity = OMV.Vector3.Zero;
- }
- // Assign directly to the local variables so the normal set action does not happen
- _position = entprop.Position;
- _orientation = entprop.Rotation;
- _velocity = entprop.Velocity;
- _acceleration = entprop.Acceleration;
- _rotationalVelocity = entprop.RotationalVelocity;
- // The sanity check can change the velocity and/or position.
- if (PositionSanityCheck(true))
- {
- entprop.Position = _position;
- entprop.Velocity = _velocity;
- }
- // remember the current and last set values
- LastEntityProperties = CurrentEntityProperties;
- CurrentEntityProperties = entprop;
- OMV.Vector3 direction = OMV.Vector3.UnitX * _orientation;
- DetailLog("{0},BSPrim.UpdateProperties,call,pos={1},orient={2},dir={3},vel={4},rotVel={5}",
- LocalID, _position, _orientation, direction, _velocity, _rotationalVelocity);
- // BulletSimAPI.DumpRigidBody2(PhysicsScene.World.ptr, BSBody.ptr); // DEBUG DEBUG DEBUG
- base.RequestPhysicsterseUpdate();
- }
- /*
- else
- {
- // For debugging, report the movement of children
- DetailLog("{0},BSPrim.UpdateProperties,child,pos={1},orient={2},vel={3},accel={4},rotVel={5}",
- LocalID, entprop.Position, entprop.Rotation, entprop.Velocity,
- entprop.Acceleration, entprop.RotationalVelocity);
- }
- */
- // The linkset implimentation might want to know about this.
- Linkset.UpdateProperties(this);
- }
- }
- }
|