// Create a linkset by creating a compound hull at the root prim that consists of all // the children. // NOTE: This does not allow proper collisions with the children prims so it is not a workable solution void CreateLinksetWithCompoundHull() { // If I am the root prim of a linkset, replace my physical shape with all the // pieces of the children. // All of the children should have called CreateGeom so they have a hull // in the physics engine already. Here we pull together all of those hulls // into one shape. int totalPrimsInLinkset = _childrenPrims.Count + 1; // m_log.DebugFormat("{0}: CreateLinkset. Root prim={1}, prims={2}", LogHeader, LocalID, totalPrimsInLinkset); ShapeData[] shapes = new ShapeData[totalPrimsInLinkset]; FillShapeInfo(out shapes[0]); int ii = 1; foreach (BSPrim prim in _childrenPrims) { // m_log.DebugFormat("{0}: CreateLinkset: adding prim {1}", LogHeader, prim.LocalID); prim.FillShapeInfo(out shapes[ii]); ii++; } BulletSimAPI.CreateLinkset(_scene.WorldID, totalPrimsInLinkset, shapes); }
public abstract BulletShape BuildNativeShape(BulletWorld world, ShapeData shapeData);
public static extern bool CreateObject(uint worldID, ShapeData shapeData);
public static extern IntPtr BuildNativeShape2(IntPtr world, ShapeData shapeData);
// Create a body object in Bullet. // Updates prim.BSBody with the information about the new body if one is created. // Returns 'true' if an object was actually created. // Called at taint-time. private bool CreateBody(bool forceRebuild, BSPrim prim, BulletSim sim, BulletShape shape, ShapeData shapeData, BodyDestructionCallback bodyCallback) { bool ret = false; // the mesh, hull or native shape must have already been created in Bullet bool mustRebuild = (prim.BSBody.ptr == IntPtr.Zero); // If there is an existing body, verify it's of an acceptable type. // If not a solid object, body is a GhostObject. Otherwise a RigidBody. if (!mustRebuild) { CollisionObjectTypes bodyType = (CollisionObjectTypes)BulletSimAPI.GetBodyType2(prim.BSBody.ptr); if (prim.IsSolid && bodyType != CollisionObjectTypes.CO_RIGID_BODY || !prim.IsSolid && bodyType != CollisionObjectTypes.CO_GHOST_OBJECT) { // If the collisionObject is not the correct type for solidness, rebuild what's there mustRebuild = true; } } if (mustRebuild || forceRebuild) { DereferenceBody(prim.BSBody, true, bodyCallback); BulletBody aBody; IntPtr bodyPtr = IntPtr.Zero; if (prim.IsSolid) { bodyPtr = BulletSimAPI.CreateBodyFromShape2(sim.ptr, shape.ptr, shapeData.ID, shapeData.Position, shapeData.Rotation); // DetailLog("{0},BSShapeCollection.CreateBody,mesh,ptr={1}", prim.LocalID, bodyPtr.ToString("X")); } else { bodyPtr = BulletSimAPI.CreateGhostFromShape2(sim.ptr, shape.ptr, shapeData.ID, shapeData.Position, shapeData.Rotation); // DetailLog("{0},BSShapeCollection.CreateBody,ghost,ptr={1}", prim.LocalID, bodyPtr.ToString("X")); } aBody = new BulletBody(shapeData.ID, bodyPtr); ReferenceBody(aBody, true); prim.BSBody = aBody; ret = true; } return ret; }
private BSShapeNative(BSScene physicsScene, BSPhysObject prim, BSPhysicsShapeType shapeType, FixedShapeKey shapeKey) { ShapeData nativeShapeData = new ShapeData(); nativeShapeData.Type = shapeType; nativeShapeData.ID = prim.LocalID; nativeShapeData.Scale = prim.Scale; nativeShapeData.Size = prim.Scale; nativeShapeData.MeshKey = (ulong)shapeKey; nativeShapeData.HullKey = (ulong)shapeKey; /* if (shapeType == BSPhysicsShapeType.SHAPE_CAPSULE) { ptr = PhysicsScene.PE.BuildCapsuleShape(physicsScene.World, 1f, 1f, prim.Scale); physicsScene.DetailLog("{0},BSShapeCollection.BuiletPhysicalNativeShape,capsule,scale={1}", prim.LocalID, prim.Scale); } else { ptr = PhysicsScene.PE.BuildNativeShape(physicsScene.World, nativeShapeData); } if (ptr == IntPtr.Zero) { physicsScene.Logger.ErrorFormat("{0} BuildPhysicalNativeShape failed. ID={1}, shape={2}", LogHeader, prim.LocalID, shapeType); } type = shapeType; key = (UInt64)shapeKey; */ }
private BulletShape BuildPhysicalNativeShape(ShapeData.PhysicsShapeType shapeType, ShapeData shapeData, ShapeData.FixedShapeKey shapeKey) { BulletShape newShape; // Need to make sure the passed shape information is for the native type. ShapeData nativeShapeData = shapeData; nativeShapeData.Type = shapeType; nativeShapeData.MeshKey = (ulong)shapeKey; nativeShapeData.HullKey = (ulong)shapeKey; if (shapeType == ShapeData.PhysicsShapeType.SHAPE_AVATAR) { newShape = new BulletShape( BulletSimAPI.BuildCapsuleShape2(PhysicsScene.World.ptr, 1f, 1f, nativeShapeData.Scale) , shapeType); DetailLog("{0},BSShapeCollection.BuiletPhysicalNativeShape,capsule,scale={1}", nativeShapeData.ID, nativeShapeData.Scale); } else { newShape = new BulletShape(BulletSimAPI.BuildNativeShape2(PhysicsScene.World.ptr, nativeShapeData), shapeType); } if (newShape.ptr == IntPtr.Zero) { PhysicsScene.Logger.ErrorFormat("{0} BuildPhysicalNativeShape failed. ID={1}, shape={2}", LogHeader, nativeShapeData.ID, nativeShapeData.Type); } newShape.shapeKey = (System.UInt64)shapeKey; newShape.isNativeShape = true; return newShape; }
// Create a hash of all the shape parameters to be used as a key // for this particular shape. private ulong ComputeShapeKey(ShapeData shapeData, PrimitiveBaseShape pbs, out float retLod) { // level of detail based on size and type of the object float lod = PhysicsScene.MeshLOD; if (pbs.SculptEntry) lod = PhysicsScene.SculptLOD; float maxAxis = Math.Max(shapeData.Size.X, Math.Max(shapeData.Size.Y, shapeData.Size.Z)); if (maxAxis > PhysicsScene.MeshMegaPrimThreshold) lod = PhysicsScene.MeshMegaPrimLOD; retLod = lod; return (ulong)pbs.GetMeshKey(shapeData.Size, lod); }
public BulletShape(IntPtr xx, ShapeData.PhysicsShapeType typ) { ptr = xx; type = typ; shapeKey = 0; isNativeShape = false; }
// Creates a native shape and assignes it to prim.BSShape. // "Native" shapes are never shared. they are created here and destroyed in DereferenceShape(). private bool GetReferenceToNativeShape(BSPhysObject prim, ShapeData shapeData, ShapeData.PhysicsShapeType shapeType, ShapeData.FixedShapeKey shapeKey, ShapeDestructionCallback shapeCallback) { // release any previous shape DereferenceShape(prim.BSShape, true, shapeCallback); shapeData.Type = shapeType; // Bullet native objects are scaled by the Bullet engine so pass the size in prim.Scale = shapeData.Size; shapeData.Scale = shapeData.Size; BulletShape newShape = BuildPhysicalNativeShape(shapeType, shapeData, shapeKey); // Don't need to do a 'ReferenceShape()' here because native shapes are not shared. DetailLog("{0},BSShapeCollection.AddNativeShapeToPrim,create,newshape={1},scale={2}", shapeData.ID, newShape, shapeData.Scale); prim.BSShape = newShape; return true; }
}// end CalculateMass #endregion Mass Calculation // Copy prim's info into the BulletSim shape description structure public void FillShapeInfo(out ShapeData shape) { shape.ID = LocalID; shape.Type = ShapeData.PhysicsShapeType.SHAPE_UNKNOWN; shape.Position = _position; shape.Rotation = _orientation; shape.Velocity = _velocity; shape.Size = _size; shape.Scale = Scale; shape.Mass = _isPhysical ? _mass : 0f; shape.Buoyancy = _buoyancy; shape.HullKey = 0; shape.MeshKey = 0; shape.Friction = _friction; shape.Restitution = _restitution; shape.Collidable = (!IsPhantom) ? ShapeData.numericTrue : ShapeData.numericFalse; shape.Static = _isPhysical ? ShapeData.numericFalse : ShapeData.numericTrue; shape.Solid = IsSolid ? ShapeData.numericFalse : ShapeData.numericTrue; }
public BSCharacter(uint localID, String avName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 size, bool isFlying) { base.BaseInitialize(parent_scene, localID, avName, "BSCharacter"); _physicsActorType = (int)ActorTypes.Agent; _position = pos; _size = size; _flying = isFlying; _orientation = OMV.Quaternion.Identity; _velocity = OMV.Vector3.Zero; _appliedVelocity = OMV.Vector3.Zero; _buoyancy = ComputeBuoyancyFromFlying(isFlying); _currentFriction = PhysicsScene.Params.avatarStandingFriction; _avatarDensity = PhysicsScene.Params.avatarDensity; // The dimensions of the avatar capsule are kept in the scale. // Physics creates a unit capsule which is scaled by the physics engine. ComputeAvatarScale(_size); // set _avatarVolume and _mass based on capsule size, _density and Scale ComputeAvatarVolumeAndMass(); DetailLog("{0},BSCharacter.create,call,size={1},scale={2},density={3},volume={4},mass={5}", LocalID, _size, Scale, _avatarDensity, _avatarVolume, MassRaw); ShapeData shapeData = new ShapeData(); shapeData.ID = LocalID; shapeData.Type = ShapeData.PhysicsShapeType.SHAPE_AVATAR; shapeData.Position = _position; shapeData.Rotation = _orientation; shapeData.Velocity = _velocity; shapeData.Size = Scale; // capsule is a native shape but scale is not just <1,1,1> shapeData.Scale = Scale; shapeData.Mass = _mass; shapeData.Buoyancy = _buoyancy; shapeData.Static = ShapeData.numericFalse; shapeData.Friction = PhysicsScene.Params.avatarStandingFriction; shapeData.Restitution = PhysicsScene.Params.avatarRestitution; // do actual create at taint time PhysicsScene.TaintedObject("BSCharacter.create", delegate() { DetailLog("{0},BSCharacter.create,taint", LocalID); // New body and shape into BSBody and BSShape PhysicsScene.Shapes.GetBodyAndShape(true, PhysicsScene.World, this, shapeData, null, null, null); SetPhysicalProperties(); }); return; }
// Create a hash of all the shape parameters to be used as a key // for this particular shape. private System.UInt64 ComputeShapeKey(ShapeData shapeData, PrimitiveBaseShape pbs, out float retLod) { // level of detail based on size and type of the object float lod = PhysicsScene.MeshLOD; if (pbs.SculptEntry) lod = PhysicsScene.SculptLOD; // Mega prims usually get more detail because one can interact with shape approximations at this size. float maxAxis = Math.Max(shapeData.Size.X, Math.Max(shapeData.Size.Y, shapeData.Size.Z)); if (maxAxis > PhysicsScene.MeshMegaPrimThreshold) lod = PhysicsScene.MeshMegaPrimLOD; retLod = lod; return pbs.GetMeshKey(shapeData.Size, lod); }
// See that hull shape exists in the physical world and update prim.BSShape. // We could be creating the hull because scale changed or whatever. private bool GetReferenceToHull(BSPrim prim, ShapeData shapeData, PrimitiveBaseShape pbs, ShapeDestructionCallback shapeCallback) { BulletShape newShape; float lod; ulong newHullKey = ComputeShapeKey(shapeData, pbs, out lod); // if the hull hasn't changed, don't rebuild it if (newHullKey == prim.BSShape.shapeKey && prim.BSShape.type == ShapeData.PhysicsShapeType.SHAPE_HULL) return false; DetailLog("{0},BSShapeCollection.CreateGeomHull,create,oldKey={1},newKey={2}", prim.LocalID, prim.BSShape.shapeKey.ToString("X"), newHullKey.ToString("X")); // Remove usage of the previous shape. Also removes reference to underlying mesh if it is a hull. DereferenceShape(prim.BSShape, true, shapeCallback); newShape = CreatePhysicalHull(prim.PhysObjectName, newHullKey, pbs, shapeData.Size, lod); ReferenceShape(newShape); // hulls are already scaled by the meshmerizer prim.Scale = new OMV.Vector3(1f, 1f, 1f); prim.BSShape = newShape; return true; // 'true' means a new shape has been added to this prim }
// For those who don't want the LOD private System.UInt64 ComputeShapeKey(ShapeData shapeData, PrimitiveBaseShape pbs) { float lod; return ComputeShapeKey(shapeData, pbs, out lod); }
// For those who don't want the LOD private ulong ComputeShapeKey(ShapeData shapeData, PrimitiveBaseShape pbs) { float lod; return ComputeShapeKey(shapeData, pbs, out lod); }
// The creation of a mesh or hull can fail if an underlying asset is not available. // There are two cases: 1) the asset is not in the cache and it needs to be fetched; // and 2) the asset cannot be converted (like decompressing JPEG2000s). // The first case causes the asset to be fetched. The second case just requires // us to not loop forever. // Called after creating a physical mesh or hull. If the physical shape was created, // just return. private BulletShape VerifyMeshCreated(BulletShape newShape, BSPhysObject prim, ShapeData shapeData, PrimitiveBaseShape pbs) { // If the shape was successfully created, nothing more to do if (newShape.ptr != IntPtr.Zero) return newShape; // If this mesh has an underlying asset and we have not failed getting it before, fetch the asset if (pbs.SculptEntry && !prim.LastAssetBuildFailed && pbs.SculptTexture != OMV.UUID.Zero) { prim.LastAssetBuildFailed = true; BSPhysObject xprim = prim; DetailLog("{0},BSShapeCollection.VerifyMeshCreated,fetchAsset,lID={1},lastFailed={2}", LogHeader, shapeData.ID.ToString("X"), prim.LastAssetBuildFailed); Util.FireAndForget(delegate { RequestAssetDelegate assetProvider = PhysicsScene.RequestAssetMethod; if (assetProvider != null) { BSPhysObject yprim = xprim; // probably not necessary, but, just in case. assetProvider(yprim.BaseShape.SculptTexture, delegate(AssetBase asset) { if (!yprim.BaseShape.SculptEntry) return; if (yprim.BaseShape.SculptTexture.ToString() != asset.ID) return; yprim.BaseShape.SculptData = asset.Data; // This will cause the prim to see that the filler shape is not the right // one and try again to build the object. // No race condition with the native sphere setting since the rebuild is at taint time. yprim.ForceBodyShapeRebuild(false); }); } }); } else { if (prim.LastAssetBuildFailed) { PhysicsScene.Logger.ErrorFormat("{0} Mesh failed to fetch asset. lID={1}, texture={2}", LogHeader, shapeData.ID, pbs.SculptTexture); } } // While we figure out the real problem, stick a simple native shape on the object. BulletShape fillinShape = BuildPhysicalNativeShape(ShapeData.PhysicsShapeType.SHAPE_BOX, shapeData, ShapeData.FixedShapeKey.KEY_BOX); return fillinShape; }
// Called to update/change the body and shape for an object. // First checks the shape and updates that if necessary then makes // sure the body is of the right type. // Return 'true' if either the body or the shape changed. // Called at taint-time!! public bool GetBodyAndShape(bool forceRebuild, BulletSim sim, BSPrim prim, ShapeData shapeData, PrimitiveBaseShape pbs, ShapeDestructionCallback shapeCallback, BodyDestructionCallback bodyCallback) { bool ret = false; // This lock could probably be pushed down lower but building shouldn't take long lock (m_collectionActivityLock) { // Do we have the correct geometry for this type of object? // Updates prim.BSShape with information/pointers to requested shape bool newGeom = CreateGeom(forceRebuild, prim, shapeData, pbs, shapeCallback); // If we had to select a new shape geometry for the object, // rebuild the body around it. // Updates prim.BSBody with information/pointers to requested body bool newBody = CreateBody((newGeom || forceRebuild), prim, PhysicsScene.World, prim.BSShape, shapeData, bodyCallback); ret = newGeom || newBody; } DetailLog("{0},BSShapeCollection.GetBodyAndShape,force={1},ret={2},body={3},shape={4}", prim.LocalID, forceRebuild, ret, prim.BSBody, prim.BSShape); return ret; }
private static BulletShape CreatePhysicalNativeShape(BSScene physicsScene, BSPhysObject prim, BSPhysicsShapeType shapeType, FixedShapeKey shapeKey) { BulletShape newShape; ShapeData nativeShapeData = new ShapeData(); nativeShapeData.Type = shapeType; nativeShapeData.ID = prim.LocalID; nativeShapeData.Scale = prim.Scale; nativeShapeData.Size = prim.Scale; nativeShapeData.MeshKey = (ulong)shapeKey; nativeShapeData.HullKey = (ulong)shapeKey; if (shapeType == BSPhysicsShapeType.SHAPE_CAPSULE) { newShape = physicsScene.PE.BuildCapsuleShape(physicsScene.World, 1f, 1f, prim.Scale); physicsScene.DetailLog("{0},BSShapeNative,capsule,scale={1}", prim.LocalID, prim.Scale); } else { newShape = physicsScene.PE.BuildNativeShape(physicsScene.World, nativeShapeData); } if (!newShape.HasPhysicalShape) { physicsScene.Logger.ErrorFormat("{0} BuildPhysicalNativeShape failed. ID={1}, shape={2}", LogHeader, prim.LocalID, shapeType); } newShape.shapeType = shapeType; newShape.isNativeShape = true; newShape.shapeKey = (UInt64)shapeKey; return newShape; }
private BulletShape BuildPhysicalNativeShape(BSPhysObject prim, BSPhysicsShapeType shapeType, FixedShapeKey shapeKey) { BulletShape newShape; // Need to make sure the passed shape information is for the native type. ShapeData nativeShapeData = new ShapeData(); nativeShapeData.Type = shapeType; nativeShapeData.ID = prim.LocalID; nativeShapeData.Scale = prim.Scale; nativeShapeData.Size = prim.Scale; // unneeded, I think. nativeShapeData.MeshKey = (ulong)shapeKey; nativeShapeData.HullKey = (ulong)shapeKey; if (shapeType == BSPhysicsShapeType.SHAPE_CAPSULE) { newShape = PhysicsScene.PE.BuildCapsuleShape(PhysicsScene.World, 1f, 1f, prim.Scale); if (DDetail) DetailLog("{0},BSShapeCollection.BuildPhysicalNativeShape,capsule,scale={1}", prim.LocalID, prim.Scale); } else { // Native shapes are scaled in Bullet so set the scaling to the size newShape = PhysicsScene.PE.BuildNativeShape(PhysicsScene.World, nativeShapeData); } if (!newShape.HasPhysicalShape) { PhysicsScene.Logger.ErrorFormat("{0} BuildPhysicalNativeShape failed. ID={1}, shape={2}", LogHeader, prim.LocalID, shapeType); } newShape.shapeKey = (System.UInt64)shapeKey; newShape.isNativeShape = true; return newShape; }
public BSCharacter(uint localID, String avName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 size, bool isFlying) { base.BaseInitialize(parent_scene, localID, avName, "BSCharacter"); _physicsActorType = (int)ActorTypes.Agent; _position = pos; _size = size; _flying = isFlying; _orientation = OMV.Quaternion.Identity; _velocity = OMV.Vector3.Zero; _buoyancy = ComputeBuoyancyFromFlying(isFlying); // The dimensions of the avatar capsule are kept in the scale. // Physics creates a unit capsule which is scaled by the physics engine. ComputeAvatarScale(_size); _avatarDensity = PhysicsScene.Params.avatarDensity; // set _avatarVolume and _mass based on capsule size, _density and _scale ComputeAvatarVolumeAndMass(); ShapeData shapeData = new ShapeData(); shapeData.ID = LocalID; shapeData.Type = ShapeData.PhysicsShapeType.SHAPE_AVATAR; shapeData.Position = _position; shapeData.Rotation = _orientation; shapeData.Velocity = _velocity; shapeData.Scale = _scale; shapeData.Mass = _mass; shapeData.Buoyancy = _buoyancy; shapeData.Static = ShapeData.numericFalse; shapeData.Friction = PhysicsScene.Params.avatarFriction; shapeData.Restitution = PhysicsScene.Params.avatarRestitution; // do actual create at taint time PhysicsScene.TaintedObject("BSCharacter.create", delegate() { DetailLog("{0},BSCharacter.create,taint", LocalID); BulletSimAPI.CreateObject(PhysicsScene.WorldID, shapeData); // Set the buoyancy for flying. This will be refactored when all the settings happen in C#. // If not set at creation, the avatar will stop flying when created after crossing a region boundry. BulletSimAPI.SetObjectBuoyancy(PhysicsScene.WorldID, LocalID, _buoyancy); BSBody = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(PhysicsScene.World.ptr, LocalID)); // This works here because CreateObject has already put the character into the physical world. BulletSimAPI.SetCollisionFilterMask2(BSBody.ptr, (uint)CollisionFilterGroups.AvatarFilter, (uint)CollisionFilterGroups.AvatarMask); }); return; }
public static extern void CreateLinkset(uint worldID, int objectCount, ShapeData[] shapeDatas);
// Create the geometry information in Bullet for later use. // The objects needs a hull if it's physical otherwise a mesh is enough. // No locking here because this is done when we know physics is not simulating. // if 'forceRebuild' is true, the geometry is rebuilt. Otherwise a previously built version is used. // Returns 'true' if the geometry was rebuilt. // Called at taint-time! private bool CreateGeom(bool forceRebuild, BSPrim prim, ShapeData shapeData, PrimitiveBaseShape pbs, ShapeDestructionCallback shapeCallback) { bool ret = false; bool haveShape = false; bool nativeShapePossible = true; // If the prim attributes are simple, this could be a simple Bullet native shape if (nativeShapePossible && ((pbs.SculptEntry && !PhysicsScene.ShouldMeshSculptedPrim) || (pbs.ProfileBegin == 0 && pbs.ProfileEnd == 0 && pbs.ProfileHollow == 0 && pbs.PathTwist == 0 && pbs.PathTwistBegin == 0 && pbs.PathBegin == 0 && pbs.PathEnd == 0 && pbs.PathTaperX == 0 && pbs.PathTaperY == 0 && pbs.PathScaleX == 100 && pbs.PathScaleY == 100 && pbs.PathShearX == 0 && pbs.PathShearY == 0) ) ) { if (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1) { haveShape = true; if (forceRebuild || prim.Scale != shapeData.Size || prim.BSShape.type != ShapeData.PhysicsShapeType.SHAPE_SPHERE ) { ret = GetReferenceToNativeShape(prim, shapeData, ShapeData.PhysicsShapeType.SHAPE_SPHERE, ShapeData.FixedShapeKey.KEY_SPHERE, shapeCallback); DetailLog("{0},BSShapeCollection.CreateGeom,sphere,force={1},shape={2}", prim.LocalID, forceRebuild, prim.BSShape); } } else { haveShape = true; if (forceRebuild || prim.Scale != shapeData.Size || prim.BSShape.type != ShapeData.PhysicsShapeType.SHAPE_BOX ) { ret = GetReferenceToNativeShape( prim, shapeData, ShapeData.PhysicsShapeType.SHAPE_BOX, ShapeData.FixedShapeKey.KEY_BOX, shapeCallback); DetailLog("{0},BSShapeCollection.CreateGeom,box,force={1},shape={2}", prim.LocalID, forceRebuild, prim.BSShape); } } } // If a simple shape is not happening, create a mesh and possibly a hull. // Note that if it's a native shape, the check for physical/non-physical is not // made. Native shapes are best used in either case. if (!haveShape) { if (prim.IsPhysical) { // Update prim.BSShape to reference a hull of this shape. ret = GetReferenceToHull(prim, shapeData, pbs, shapeCallback); DetailLog("{0},BSShapeCollection.CreateGeom,hull,shape={1},key={2}", shapeData.ID, prim.BSShape, prim.BSShape.shapeKey.ToString("X")); } else { ret = GetReferenceToMesh(prim, shapeData, pbs, shapeCallback); DetailLog("{0},BSShapeCollection.CreateGeom,mesh,shape={1},key={2}", shapeData.ID, prim.BSShape, prim.BSShape.shapeKey.ToString("X")); } } return ret; }
public override BulletShape BuildNativeShape(BulletWorld world, ShapeData shapeData) { BulletWorldUnman worldu = world as BulletWorldUnman; return new BulletShapeUnman(BSAPICPP.BuildNativeShape2(worldu.ptr, shapeData), shapeData.Type); }
// Creates a native shape and assignes it to prim.BSShape private bool GetReferenceToNativeShape( BSPrim prim, ShapeData shapeData, ShapeData.PhysicsShapeType shapeType, ShapeData.FixedShapeKey shapeKey, ShapeDestructionCallback shapeCallback) { BulletShape newShape; shapeData.Type = shapeType; // Bullet native objects are scaled by the Bullet engine so pass the size in prim.Scale = shapeData.Size; shapeData.Scale = shapeData.Size; // release any previous shape DereferenceShape(prim.BSShape, true, shapeCallback); // Native shapes are always built independently. newShape = new BulletShape(BulletSimAPI.BuildNativeShape2(PhysicsScene.World.ptr, shapeData), shapeType); newShape.shapeKey = (ulong)shapeKey; newShape.isNativeShape = true; // Don't need to do a 'ReferenceShape()' here because native shapes are not tracked. // DetailLog("{0},BSShapeCollection.AddNativeShapeToPrim,create,newshape={1}", shapeData.ID, newShape); prim.BSShape = newShape; return true; }
// Copy prim's info into the BulletSim shape description structure public void FillShapeInfo(out ShapeData shape) { shape.ID = _localID; shape.Type = _shapeType; shape.Position = _position; shape.Rotation = _orientation; shape.Velocity = _velocity; shape.Scale = _scale; shape.Mass = _isPhysical ? _mass : 0f; shape.Buoyancy = _buoyancy; shape.HullKey = _hullKey; shape.MeshKey = _meshKey; shape.Friction = _friction; shape.Restitution = _restitution; shape.Collidable = (!IsPhantom) ? ShapeData.numericTrue : ShapeData.numericFalse; shape.Static = _isPhysical ? ShapeData.numericFalse : ShapeData.numericTrue; }
// Builds a mesh shape in the physical world and updates prim.BSShape. // Dereferences previous shape in BSShape and adds a reference for this new shape. // Returns 'true' of a mesh was actually built. Otherwise . // Called at taint-time! private bool GetReferenceToMesh(BSPrim prim, ShapeData shapeData, PrimitiveBaseShape pbs, ShapeDestructionCallback shapeCallback) { BulletShape newShape = new BulletShape(IntPtr.Zero); float lod; ulong newMeshKey = ComputeShapeKey(shapeData, pbs, out lod); // if this new shape is the same as last time, don't recreate the mesh if (newMeshKey == prim.BSShape.shapeKey && prim.BSShape.type == ShapeData.PhysicsShapeType.SHAPE_MESH) return false; DetailLog("{0},BSShapeCollection.CreateGeomMesh,create,oldKey={1},newKey={2}", prim.LocalID, prim.BSShape.shapeKey.ToString("X"), newMeshKey.ToString("X")); // Since we're recreating new, get rid of the reference to the previous shape DereferenceShape(prim.BSShape, true, shapeCallback); newShape = CreatePhysicalMesh(prim.PhysObjectName, newMeshKey, pbs, shapeData.Size, lod); ReferenceShape(newShape); // meshes are already scaled by the meshmerizer prim.Scale = new OMV.Vector3(1f, 1f, 1f); prim.BSShape = newShape; return true; // 'true' means a new shape has been added to this prim }
public BSCharacter(uint localID, String avName, BSScene parent_scene, Vector3 pos, Vector3 size, bool isFlying) { _localID = localID; _avName = avName; _scene = parent_scene; _position = pos; _size = size; _flying = isFlying; _orientation = Quaternion.Identity; _velocity = Vector3.Zero; _buoyancy = isFlying ? 1f : 0f; _scale = new Vector3(1f, 1f, 1f); _density = _scene.Params.avatarDensity; ComputeAvatarVolumeAndMass(); // set _avatarVolume and _mass based on capsule size, _density and _scale ShapeData shapeData = new ShapeData(); shapeData.ID = _localID; shapeData.Type = ShapeData.PhysicsShapeType.SHAPE_AVATAR; shapeData.Position = _position; shapeData.Rotation = _orientation; shapeData.Velocity = _velocity; shapeData.Scale = _scale; shapeData.Mass = _mass; shapeData.Buoyancy = _buoyancy; shapeData.Static = ShapeData.numericFalse; shapeData.Friction = _scene.Params.avatarFriction; shapeData.Restitution = _scene.Params.defaultRestitution; // do actual create at taint time _scene.TaintedObject(delegate() { BulletSimAPI.CreateObject(parent_scene.WorldID, shapeData); }); return; }
public BSCharacter(uint localID, UUID avID, String avName, BSScene parent_scene, Vector3 pos, Quaternion rotation, Vector3 size, bool isFlying) { _localID = localID; _avID = avID; _avName = avName; _scene = parent_scene; _position = pos; _orientation = rotation; _size = size; _orientation = Quaternion.Identity; _velocity = Vector3.Zero; _scale = new Vector3(1f, 1f, 1f); float AVvolume = (float) (Math.PI*Math.Pow(_scene.Params.avatarCapsuleRadius, 2)*_scene.Params.avatarCapsuleHeight); _density = _scene.Params.avatarDensity; _mass = _density*AVvolume; _isPhysical = true; ShapeData shapeData = new ShapeData { ID = _localID, Type = ShapeData.PhysicsShapeType.SHAPE_AVATAR, Position = _position, Rotation = _orientation, Velocity = _velocity, Scale = _scale, Mass = _mass, Buoyancy = isFlying ? 1f : 0f, Static = ShapeData.numericFalse, Friction = _scene.Params.avatarFriction, Restitution = _scene.Params.defaultRestitution }; // do actual create at taint time _scene.TaintedObject(() => BulletSimAPI.CreateObject(parent_scene.WorldID, shapeData)); return; }