Ejemplo n.º 1
0
 public BSActorAvatarMove(BSScene physicsScene, BSPhysObject pObj, string actorName)
     : base(physicsScene, pObj, actorName)
 {
     m_velocityMotor = null;
     m_walkingUpStairs = 0;
     m_physicsScene.DetailLog("{0},BSActorAvatarMove,constructor", m_controllingPrim.LocalID);
 }
Ejemplo n.º 2
0
    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;
        RawPosition = pos;
        _size = size;
        Scale = size;   // prims are the size the user wants them to be (different for BSCharactes).
        RawOrientation = rotation;
        _buoyancy = 0f;
        RawVelocity = OMV.Vector3.Zero;
        _rotationalVelocity = OMV.Vector3.Zero;
        BaseShape = pbs;
        _isPhysical = pisPhysical;
        _isVolumeDetect = false;

        _mass = CalculateMass();

        DetailLog("{0},BSPrim.constructor,pbs={1}", LocalID, BSScene.PrimitiveBaseShapeToString(pbs));
        // DetailLog("{0},BSPrim.constructor,call", LocalID);
        // do the actual object creation at taint time
        PhysScene.TaintedObject(LocalID, "BSPrim.create", delegate()
        {
            // Make sure the object is being created with some sanity.
            ExtremeSanityCheck(true /* inTaintTime */);

            CreateGeomAndObject(true);

            CurrentCollisionFlags = PhysScene.PE.GetCollisionFlags(PhysBody);

            IsInitialized = true;
        });
    }
Ejemplo n.º 3
0
    // Create the correct type of linkset for this child
    public static BSLinkset Factory(BSScene physScene, BSPrimLinkable parent)
    {
        BSLinkset ret = null;

        switch (parent.LinksetType)
        {
            case LinksetImplementation.Constraint:
                ret = new BSLinksetConstraints(physScene, parent);
                break;
            case LinksetImplementation.Compound:
                ret = new BSLinksetCompound(physScene, parent);
                break;
            case LinksetImplementation.Manual:
                // ret = new BSLinksetManual(physScene, parent);
                break;
            default:
                ret = new BSLinksetCompound(physScene, parent);
                break;
        }
        if (ret == null)
        {
            physScene.Logger.ErrorFormat("[BULLETSIM LINKSET] Factory could not create linkset. Parent name={1}, ID={2}", parent.Name, parent.LocalID);
        }
        return ret;
    }
Ejemplo n.º 4
0
 public BSActorLockAxis(BSScene physicsScene, BSPhysObject pObj, string actorName)
     : base(physicsScene, pObj, actorName)
 {
     m_physicsScene.DetailLog("{0},BSActorLockAxis,constructor", m_controllingPrim.LocalID);
     LockAxisConstraint = null;
     HaveRegisteredForBeforeStepCallback = false;
 }
Ejemplo n.º 5
0
 public BSShapeCollection(BSScene physScene)
 {
     m_physicsScene = physScene;
     // Set the next to 'true' for very detailed shape update detailed logging (detailed details?)
     // While detailed debugging is still active, this is better than commenting out all the
     //     DetailLog statements. When debugging slows down, this and the protected logging
     //     statements can be commented/removed.
     DDetail = true;
 }
Ejemplo n.º 6
0
 public void TearDown()
 {
     if (PhysicsScene != null)
     {
         // The Dispose() will also free any physical objects in the scene
         PhysicsScene.Dispose();
         PhysicsScene = null;
     }
 }
Ejemplo n.º 7
0
 // Apply the specificed collision mask into the physical world
 public virtual bool ApplyCollisionMask(BSScene physicsScene)
 {
     // Should assert the body has been added to the physical world.
     // (The collision masks are stored in the collision proxy cache which only exists for
     //    a collision body that is in the world.)
     return physicsScene.PE.SetCollisionGroupMask(this,
                             BulletSimData.CollisionTypeMasks[collisionType].group,
                             BulletSimData.CollisionTypeMasks[collisionType].mask);
 }
Ejemplo n.º 8
0
    public BSPrimLinkable(uint localID, String primName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 size,
                       OMV.Quaternion rotation, PrimitiveBaseShape pbs, bool pisPhysical)
        : base(localID, primName, parent_scene, pos, size, rotation, pbs, pisPhysical)
    {
        // Default linkset implementation for this prim
        LinksetType = (BSLinkset.LinksetImplementation)BSParam.LinksetImplementation;

        Linkset = BSLinkset.Factory(PhysScene, this);

        Linkset.Refresh(this);
    }
Ejemplo n.º 9
0
    public BSCharacter(
            uint localID, String avName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 vel, OMV.Vector3 size, bool isFlying)

            : base(parent_scene, localID, avName, "BSCharacter")
    {
        _physicsActorType = (int)ActorTypes.Agent;
        RawPosition = pos;        

        _flying = isFlying;
        RawOrientation = OMV.Quaternion.Identity;
        RawVelocity = vel;
        _buoyancy = ComputeBuoyancyFromFlying(isFlying);
        Friction = BSParam.AvatarStandingFriction;
        Density = BSParam.AvatarDensity;
        _isPhysical = true;

        // Old versions of ScenePresence passed only the height. If width and/or depth are zero,
        //     replace with the default values.
        _size = size;
        if (_size.X == 0f) _size.X = BSParam.AvatarCapsuleDepth;
        if (_size.Y == 0f) _size.Y = BSParam.AvatarCapsuleWidth;

        // The dimensions of the physical capsule are kept in the scale.
        // Physics creates a unit capsule which is scaled by the physics engine.
        Scale = 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},pos={6},vel={7}",
            LocalID, _size, Scale, Density, _avatarVolume, RawMass, pos, vel);

        // do actual creation in taint time
        PhysScene.TaintedObject(LocalID, "BSCharacter.create", delegate()
        {
            DetailLog("{0},BSCharacter.create,taint", LocalID);

            // New body and shape into PhysBody and PhysShape
            PhysScene.Shapes.GetBodyAndShape(true, PhysScene.World, this);

            // The avatar's movement is controlled by this motor that speeds up and slows down
            //    the avatar seeking to reach the motor's target speed.
            // This motor runs as a prestep action for the avatar so it will keep the avatar
            //    standing as well as moving. Destruction of the avatar will destroy the pre-step action.
            m_moveActor = new BSActorAvatarMove(PhysScene, this, AvatarMoveActorName);
            PhysicalActors.Add(AvatarMoveActorName, m_moveActor);

            SetPhysicalProperties();

            IsInitialized = true;
        });
        return;
    }
Ejemplo n.º 10
0
    // This minCoords and maxCoords passed in give the size of the terrain (min and max Z
    //         are the high and low points of the heightmap).
    public BSTerrainHeightmap(BSScene physicsScene, Vector3 regionBase, uint id, float[] initialMap,
                                                    Vector3 minCoords, Vector3 maxCoords)
        : base(physicsScene, regionBase, id)
    {
        m_mapInfo = new BulletHMapInfo(id, initialMap, maxCoords.X - minCoords.X, maxCoords.Y - minCoords.Y);
        m_mapInfo.minCoords = minCoords;
        m_mapInfo.maxCoords = maxCoords;
        m_mapInfo.minZ = minCoords.Z;
        m_mapInfo.maxZ = maxCoords.Z;
        m_mapInfo.terrainRegionBase = TerrainBase;

        // Don't have to free any previous since we just got here.
        BuildHeightmapTerrain();
    }
Ejemplo n.º 11
0
    protected BSPhysObject(BSScene parentScene, uint localID, string name, string typeName)
    {
        IsInitialized = false;

        PhysScene = parentScene;
        LocalID = localID;
        PhysObjectName = name;
        Name = name;    // PhysicsActor also has the name of the object. Someday consolidate.
        TypeName = typeName;

        // Oddity if object is destroyed and recreated very quickly it could still have the old body.
        if (!PhysBody.HasPhysicalBody)
            PhysBody = new BulletBody(localID);

        // Clean out anything that might be in the physical actor list.
        // Again, a workaround for destroying and recreating an object very quickly.
        PhysicalActors.Dispose();

        UserSetCenterOfMassDisplacement = null;

        PrimAssetState = PrimAssetCondition.Unknown;

        // Initialize variables kept in base.
        // Beware that these cause taints to be queued whch can cause race conditions on startup.
        GravModifier = 1.0f;
        Gravity = new OMV.Vector3(0f, 0f, BSParam.Gravity);
        HoverActive = false;

        // Default material type. Also sets Friction, Restitution and Density.
        SetMaterial((int)MaterialAttributes.Material.Wood);

        CollisionsLastTickStep = -1;

        SubscribedEventsMs = 0;
        // Crazy values that will never be true
        CollidingStep = BSScene.NotASimulationStep;
        CollidingGroundStep = BSScene.NotASimulationStep;
        CollisionAccumulation = BSScene.NotASimulationStep;
        ColliderIsMoving = false;
        CollisionScore = 0;

        // All axis free.
        LockedLinearAxis = LockedAxisFree;
        LockedAngularAxis = LockedAxisFree;
    }
Ejemplo n.º 12
0
 // Constructor to build a default, flat heightmap terrain.
 public BSTerrainHeightmap(BSScene physicsScene, Vector3 regionBase, uint id, Vector3 regionSize)
     : base(physicsScene, regionBase, id)
 {
     Vector3 minTerrainCoords = new Vector3(0f, 0f, BSTerrainManager.HEIGHT_INITIALIZATION - BSTerrainManager.HEIGHT_EQUAL_FUDGE);
     Vector3 maxTerrainCoords = new Vector3(regionSize.X, regionSize.Y, BSTerrainManager.HEIGHT_INITIALIZATION);
     int totalHeights = (int)maxTerrainCoords.X * (int)maxTerrainCoords.Y;
     float[] initialMap = new float[totalHeights];
     for (int ii = 0; ii < totalHeights; ii++)
     {
         initialMap[ii] = BSTerrainManager.HEIGHT_INITIALIZATION;
     }
     m_mapInfo = new BulletHMapInfo(id, initialMap, regionSize.X, regionSize.Y);
     m_mapInfo.minCoords = minTerrainCoords;
     m_mapInfo.maxCoords = maxTerrainCoords;
     m_mapInfo.terrainRegionBase = TerrainBase;
     // Don't have to free any previous since we just got here.
     BuildHeightmapTerrain();
 }
Ejemplo n.º 13
0
    // Convert the passed heightmap to mesh information suitable for CreateMeshShape2().
    // Return 'true' if successfully created.
    public static bool ConvertHeightmapToMesh( BSScene physicsScene,
                                float[] heightMap, int sizeX, int sizeY,    // parameters of incoming heightmap
                                Vector3 extentBase,                         // base to be added to all vertices
                                out int indicesCountO, out int[] indicesO,
                                out int verticesCountO, out float[] verticesO)
    {
        bool ret = false;

        int indicesCount = 0;
        int verticesCount = 0;
        int[] indices = new int[0];
        float[] vertices = new float[0];

        // Simple mesh creation which assumes magnification == 1.
        // TODO: do a more general solution that scales, adds new vertices and smoothes the result.

        // Create an array of vertices that is sizeX+1 by sizeY+1 (note the loop
        //    from zero to <= sizeX). The triangle indices are then generated as two triangles
        //    per heightmap point. There are sizeX by sizeY of these squares. The extra row and
        //    column of vertices are used to complete the triangles of the last row and column
        //    of the heightmap.
        try
        {
            // One vertice per heightmap value plus the vertices off the side and bottom edge.
            int totalVertices = (sizeX + 1) * (sizeY + 1);
            vertices = new float[totalVertices * 3];
            int totalIndices = sizeX * sizeY * 6;
            indices = new int[totalIndices];

            if (physicsScene != null)
                physicsScene.DetailLog("{0},BSTerrainMesh.ConvertHeightMapToMesh,totVert={1},totInd={2},extentBase={3}",
                                    BSScene.DetailLogZero, totalVertices, totalIndices, extentBase);
            float minHeight = float.MaxValue;
            // Note that sizeX+1 vertices are created since there is land between this and the next region.
            for (int yy = 0; yy <= sizeY; yy++)
            {
                for (int xx = 0; xx <= sizeX; xx++)     // Hint: the "<=" means we go around sizeX + 1 times
                {
                    int offset = yy * sizeX + xx;
                    // Extend the height with the height from the last row or column
                    if (yy == sizeY) offset -= sizeX;
                    if (xx == sizeX) offset -= 1;
                    float height = heightMap[offset];
                    minHeight = Math.Min(minHeight, height);
                    vertices[verticesCount + 0] = (float)xx + extentBase.X;
                    vertices[verticesCount + 1] = (float)yy + extentBase.Y;
                    vertices[verticesCount + 2] = height + extentBase.Z;
                    verticesCount += 3;
                }
            }
            verticesCount = verticesCount / 3;

            for (int yy = 0; yy < sizeY; yy++)
            {
                for (int xx = 0; xx < sizeX; xx++)
                {
                    int offset = yy * (sizeX + 1) + xx;
                    // Each vertices is presumed to be the upper left corner of a box of two triangles
                    indices[indicesCount + 0] = offset;
                    indices[indicesCount + 1] = offset + 1;
                    indices[indicesCount + 2] = offset + sizeX + 1; // accounting for the extra column
                    indices[indicesCount + 3] = offset + 1;
                    indices[indicesCount + 4] = offset + sizeX + 2;
                    indices[indicesCount + 5] = offset + sizeX + 1;
                    indicesCount += 6;
                }
            }

            ret = true;
        }
        catch (Exception e)
        {
            if (physicsScene != null)
                physicsScene.Logger.ErrorFormat("{0} Failed conversion of heightmap to mesh. For={1}/{2}, e={3}",
                                                LogHeader, physicsScene.RegionName, extentBase, e);
        }

        indicesCountO = indicesCount;
        indicesO = indices;
        verticesCountO = verticesCount;
        verticesO = vertices;

        return ret;
    }
Ejemplo n.º 14
0
 public BulletWorldXNA(uint id, BSScene physScene, DiscreteDynamicsWorld xx)
     : base(id, physScene)
 {
     world = xx;
 }
Ejemplo n.º 15
0
 public BSAPIXNA(string paramName, BSScene physScene)
 {
     PhysicsScene = physScene;
 }
Ejemplo n.º 16
0
 public override void Dereference(BSScene physicsScene)
 {
     lock (Hulls)
     {
         this.DecrementReference();
         physicsScene.DetailLog("{0},BSShapeHull.Dereference,shape={1}", BSScene.DetailLogZero, this);
         // TODO: schedule aging and destruction of unused meshes.
     }
 }
Ejemplo n.º 17
0
 public BSActorSetForce(BSScene physicsScene, BSPhysObject pObj, string actorName)
     : base(physicsScene, pObj, actorName)
 {
     m_forceMotor = null;
     m_physicsScene.DetailLog("{0},BSActorSetForce,constructor", m_controllingPrim.LocalID);
 }
Ejemplo n.º 18
0
 public override BSShape GetReference(BSScene pPhysicsScene, BSPhysObject pPrim)
 {
     BSShape ret = null;
     // If the underlying shape is native, the actual shape has not been build (waiting for asset)
     //     and we must create a copy of the native shape since they are never shared.
     if (physShapeInfo.HasPhysicalShape && physShapeInfo.isNativeShape)
     {
         // TODO: decide when the native shapes should be freed. Check in Dereference?
         ret = BSShapeNative.GetReference(pPhysicsScene, pPrim, BSPhysicsShapeType.SHAPE_BOX, FixedShapeKey.KEY_BOX);
     }
     else
     {
         // Another reference to this shape is just counted.
         IncrementReference();
         ret = this;
     }
     return ret;
 }
Ejemplo n.º 19
0
 public BSTerrainMesh(BSScene physicsScene, Vector3 regionBase, uint id /* parameters for making mesh */)
     : base(physicsScene, regionBase, id)
 {
 }
Ejemplo n.º 20
0
    // Convert the passed heightmap to mesh information suitable for CreateMeshShape2().
    // Version that handles magnification.
    // Return 'true' if successfully created.
    public static bool ConvertHeightmapToMesh2( BSScene physicsScene,
                                float[] heightMap, int sizeX, int sizeY,    // parameters of incoming heightmap
                                int magnification,                          // number of vertices per heighmap step
                                Vector3 extent,                             // dimensions of the output mesh
                                Vector3 extentBase,                         // base to be added to all vertices
                                out int indicesCountO, out int[] indicesO,
                                out int verticesCountO, out float[] verticesO)
    {
        bool ret = false;

        int indicesCount = 0;
        int verticesCount = 0;
        int[] indices = new int[0];
        float[] vertices = new float[0];

        HeightMapGetter hmap = new HeightMapGetter(heightMap, sizeX, sizeY);

        // The vertices dimension of the output mesh
        int meshX = sizeX * magnification;
        int meshY = sizeY * magnification;
        // The output size of one mesh step
        float meshXStep = extent.X / meshX;
        float meshYStep = extent.Y / meshY;

        // Create an array of vertices that is meshX+1 by meshY+1 (note the loop
        //    from zero to <= meshX). The triangle indices are then generated as two triangles
        //    per heightmap point. There are meshX by meshY of these squares. The extra row and
        //    column of vertices are used to complete the triangles of the last row and column
        //    of the heightmap.
        try
        {
            // Vertices for the output heightmap plus one on the side and bottom to complete triangles
            int totalVertices = (meshX + 1) * (meshY + 1);
            vertices = new float[totalVertices * 3];
            int totalIndices = meshX * meshY * 6;
            indices = new int[totalIndices];

            if (physicsScene != null)
                physicsScene.DetailLog("{0},BSTerrainMesh.ConvertHeightMapToMesh2,inSize={1},outSize={2},totVert={3},totInd={4},extentBase={5}",
                                    BSScene.DetailLogZero, new Vector2(sizeX, sizeY), new Vector2(meshX, meshY),
                                    totalVertices, totalIndices, extentBase);

            float minHeight = float.MaxValue;
            // Note that sizeX+1 vertices are created since there is land between this and the next region.
            // Loop through the output vertices and compute the mediun height in between the input vertices
            for (int yy = 0; yy <= meshY; yy++)
            {
                for (int xx = 0; xx <= meshX; xx++)     // Hint: the "<=" means we go around sizeX + 1 times
                {
                    float offsetY = (float)yy * (float)sizeY / (float)meshY;     // The Y that is closest to the mesh point
                    int stepY = (int)offsetY;
                    float fractionalY = offsetY - (float)stepY;
                    float offsetX = (float)xx * (float)sizeX / (float)meshX;     // The X that is closest to the mesh point
                    int stepX = (int)offsetX;
                    float fractionalX = offsetX - (float)stepX;

                    // physicsScene.DetailLog("{0},BSTerrainMesh.ConvertHeightMapToMesh2,xx={1},yy={2},offX={3},stepX={4},fractX={5},offY={6},stepY={7},fractY={8}",
                    //                 BSScene.DetailLogZero, xx, yy, offsetX, stepX, fractionalX, offsetY, stepY, fractionalY);

                    // get the four corners of the heightmap square the mesh point is in
                    float heightUL = hmap.GetHeight(stepX    , stepY    );
                    float heightUR = hmap.GetHeight(stepX + 1, stepY    );
                    float heightLL = hmap.GetHeight(stepX    , stepY + 1);
                    float heightLR = hmap.GetHeight(stepX + 1, stepY + 1);

                    // bilinear interplolation
                    float height = heightUL * (1 - fractionalX) * (1 - fractionalY)
                                 + heightUR * fractionalX       * (1 - fractionalY)
                                 + heightLL * (1 - fractionalX) * fractionalY
                                 + heightLR * fractionalX       * fractionalY;

                    // physicsScene.DetailLog("{0},BSTerrainMesh.ConvertHeightMapToMesh2,heightUL={1},heightUR={2},heightLL={3},heightLR={4},heightMap={5}",
                    //                 BSScene.DetailLogZero, heightUL, heightUR, heightLL, heightLR, height);

                    minHeight = Math.Min(minHeight, height);

                    vertices[verticesCount + 0] = (float)xx * meshXStep + extentBase.X;
                    vertices[verticesCount + 1] = (float)yy * meshYStep + extentBase.Y;
                    vertices[verticesCount + 2] = height + extentBase.Z;
                    verticesCount += 3;
                }
            }
            // The number of vertices generated
            verticesCount /= 3;

            // Loop through all the heightmap squares and create indices for the two triangles for that square
            for (int yy = 0; yy < meshY; yy++)
            {
                for (int xx = 0; xx < meshX; xx++)
                {
                    int offset = yy * (meshX + 1) + xx;
                    // Each vertices is presumed to be the upper left corner of a box of two triangles
                    indices[indicesCount + 0] = offset;
                    indices[indicesCount + 1] = offset + 1;
                    indices[indicesCount + 2] = offset + meshX + 1; // accounting for the extra column
                    indices[indicesCount + 3] = offset + 1;
                    indices[indicesCount + 4] = offset + meshX + 2;
                    indices[indicesCount + 5] = offset + meshX + 1;
                    indicesCount += 6;
                }
            }

            ret = true;
        }
        catch (Exception e)
        {
            if (physicsScene != null)
                physicsScene.Logger.ErrorFormat("{0} Failed conversion of heightmap to mesh. For={1}/{2}, e={3}",
                                                LogHeader, physicsScene.RegionName, extentBase, e);
        }

        indicesCountO = indicesCount;
        indicesO = indices;
        verticesCountO = verticesCount;
        verticesO = vertices;

        return ret;
    }
Ejemplo n.º 21
0
 public BSLinksetConstraints(BSScene scene, BSPrimLinkable parent) : base(scene, parent)
 {
     LinksetImpl = LinksetImplementation.Constraint;
 }
Ejemplo n.º 22
0
    // Dereferencing a compound shape releases the hold on all the child shapes.
    public override void Dereference(BSScene physicsScene)
    {
        lock (physShapeInfo)
        {
            this.DecrementReference();
            physicsScene.DetailLog("{0},BSShapeCompound.Dereference,shape={1}", BSScene.DetailLogZero, this);
            if (referenceCount <= 0)
            {
                if (!physicsScene.PE.IsCompound(physShapeInfo))
                {
                    // Failed the sanity check!!
                    physicsScene.Logger.ErrorFormat("{0} Attempt to free a compound shape that is not compound!! type={1}, ptr={2}",
                                                LogHeader, physShapeInfo.shapeType, physShapeInfo.AddrString);
                    physicsScene.DetailLog("{0},BSShapeCollection.DereferenceCompound,notACompoundShape,type={1},ptr={2}",
                                                BSScene.DetailLogZero, physShapeInfo.shapeType, physShapeInfo.AddrString);
                    return;
                }

                int numChildren = physicsScene.PE.GetNumberOfCompoundChildren(physShapeInfo);
                physicsScene.DetailLog("{0},BSShapeCollection.DereferenceCompound,shape={1},children={2}",
                                        BSScene.DetailLogZero, physShapeInfo, numChildren);

                // Loop through all the children dereferencing each.
                for (int ii = numChildren - 1; ii >= 0; ii--)
                {
                    BulletShape childShape = physicsScene.PE.RemoveChildShapeFromCompoundShapeIndex(physShapeInfo, ii);
                    DereferenceAnonCollisionShape(physicsScene, childShape);
                }

                lock (CompoundShapes)
                    CompoundShapes.Remove(physShapeInfo.AddrString);
                physicsScene.PE.DeleteCollisionShape(physicsScene.World, physShapeInfo);
            }
        }
    }
Ejemplo n.º 23
0
 public override BSShape GetReference(BSScene physicsScene, BSPhysObject prim)
 {
     // Calling this reference means we want another handle to an existing compound shape
     //     (usually linksets) so return this copy.
     IncrementReference();
     return this;
 }
Ejemplo n.º 24
0
 public static BSShape GetReference(BSScene physicsScene)
 {
     // Base compound shapes are not shared so this returns a raw shape.
     // A built compound shape can be reused in linksets.
     BSShapeCompound ret = new BSShapeCompound(CreatePhysicalCompoundShape(physicsScene));
     CompoundShapes.Add(ret.AddrString, ret);
     return ret;
 }
Ejemplo n.º 25
0
    private BulletShape CreatePhysicalHull(BSScene physicsScene, BSPhysObject prim, System.UInt64 newHullKey,
                                            PrimitiveBaseShape pbs, OMV.Vector3 size, float lod)
    {
        BulletShape newShape = new BulletShape();

        IMesh meshData = null;
        List<List<OMV.Vector3>> allHulls = null;
        lock (physicsScene.mesher)
        {
            // Pass true for physicalness as this prevents the creation of bounding box which is not needed
            meshData = physicsScene.mesher.CreateMesh(prim.PhysObjectName, pbs, size, lod, true /* isPhysical */, false /* shouldCache */, false, false);

            // If we should use the asset's hull info, fetch it out of the locked mesher
            if (meshData != null && BSParam.ShouldUseAssetHulls)
            {
                Meshmerizer realMesher = physicsScene.mesher as Meshmerizer;
                if (realMesher != null)
                {
                    allHulls = realMesher.GetConvexHulls(size);
                }
                if (allHulls == null)
                {
                    physicsScene.DetailLog("{0},BSShapeHull.CreatePhysicalHull,assetHulls,noAssetHull", prim.LocalID);
                }
            }
        }

        // If there is hull data in the mesh asset, build the hull from that
        if (allHulls != null && BSParam.ShouldUseAssetHulls)
        {
            int hullCount = allHulls.Count;
            shapeInfo.HullCount = hullCount;
            int totalVertices = 1;      // include one for the count of the hulls
            // Using the structure described for HACD hulls, create the memory sturcture
            //     to pass the hull data to the creater.
            foreach (List<OMV.Vector3> hullVerts in allHulls)
            {
                totalVertices += 4;                     // add four for the vertex count and centroid
                totalVertices += hullVerts.Count * 3;   // one vertex is three dimensions
            }
            float[] convHulls = new float[totalVertices];

            convHulls[0] = (float)hullCount;
            int jj = 1;
            int hullIndex = 0;
            foreach (List<OMV.Vector3> hullVerts in allHulls)
            {
                convHulls[jj + 0] = hullVerts.Count;
                convHulls[jj + 1] = 0f;   // centroid x,y,z
                convHulls[jj + 2] = 0f;
                convHulls[jj + 3] = 0f;
                jj += 4;
                foreach (OMV.Vector3 oneVert in hullVerts)
                {
                    convHulls[jj + 0] = oneVert.X;
                    convHulls[jj + 1] = oneVert.Y;
                    convHulls[jj + 2] = oneVert.Z;
                    jj += 3;
                }
                shapeInfo.SetVerticesPerHull(hullIndex, hullVerts.Count);
                hullIndex++;
            }

            // create the hull data structure in Bullet
            newShape = physicsScene.PE.CreateHullShape(physicsScene.World, hullCount, convHulls);

            physicsScene.DetailLog("{0},BSShapeHull.CreatePhysicalHull,assetHulls,hulls={1},totVert={2},shape={3}",
                                        prim.LocalID, hullCount, totalVertices, newShape);
        }

        // If no hull specified in the asset and we should use Bullet's HACD approximation...
        if (!newShape.HasPhysicalShape && BSParam.ShouldUseBulletHACD)
        {
            // Build the hull shape from an existing mesh shape.
            // The mesh should have already been created in Bullet.
            physicsScene.DetailLog("{0},BSShapeHull.CreatePhysicalHull,bulletHACD,entry", prim.LocalID);
            BSShape meshShape = BSShapeMesh.GetReference(physicsScene, true, prim);

            if (meshShape.physShapeInfo.HasPhysicalShape)
            {
                HACDParams parms = new HACDParams();
                parms.maxVerticesPerHull = BSParam.BHullMaxVerticesPerHull;
                parms.minClusters = BSParam.BHullMinClusters;
                parms.compacityWeight = BSParam.BHullCompacityWeight;
                parms.volumeWeight = BSParam.BHullVolumeWeight;
                parms.concavity = BSParam.BHullConcavity;
                parms.addExtraDistPoints = BSParam.NumericBool(BSParam.BHullAddExtraDistPoints);
                parms.addNeighboursDistPoints = BSParam.NumericBool(BSParam.BHullAddNeighboursDistPoints);
                parms.addFacesPoints = BSParam.NumericBool(BSParam.BHullAddFacesPoints);
                parms.shouldAdjustCollisionMargin = BSParam.NumericBool(BSParam.BHullShouldAdjustCollisionMargin);
                parms.whichHACD = 0;    // Use the HACD routine that comes with Bullet

                physicsScene.DetailLog("{0},BSShapeHull.CreatePhysicalHull,hullFromMesh,beforeCall", prim.LocalID, newShape.HasPhysicalShape);
                newShape = physicsScene.PE.BuildHullShapeFromMesh(physicsScene.World, meshShape.physShapeInfo, parms);
                physicsScene.DetailLog("{0},BSShapeHull.CreatePhysicalHull,hullFromMesh,shape={1}", prim.LocalID, newShape);

                // Now done with the mesh shape.
                shapeInfo.HullCount = 1;
                BSShapeMesh maybeMesh = meshShape as BSShapeMesh;
                if (maybeMesh != null)
                    shapeInfo.SetVerticesPerHull(0, maybeMesh.shapeInfo.Vertices);
                meshShape.Dereference(physicsScene);
            }
            physicsScene.DetailLog("{0},BSShapeHull.CreatePhysicalHull,bulletHACD,exit,hasBody={1}", prim.LocalID, newShape.HasPhysicalShape);
        }

        // If no other hull specifications, use our HACD hull approximation.
        if (!newShape.HasPhysicalShape && meshData != null)
        {
            if (prim.PrimAssetState == BSPhysObject.PrimAssetCondition.Fetched)
            {
                // Release the fetched asset data once it has been used.
                pbs.SculptData = new byte[0];
                prim.PrimAssetState = BSPhysObject.PrimAssetCondition.Unknown;
            }

            int[] indices = meshData.getIndexListAsInt();
            List<OMV.Vector3> vertices = meshData.getVertexList();

            //format conversion from IMesh format to DecompDesc format
            List<int> convIndices = new List<int>();
            List<float3> convVertices = new List<float3>();
            for (int ii = 0; ii < indices.GetLength(0); ii++)
            {
                convIndices.Add(indices[ii]);
            }
            foreach (OMV.Vector3 vv in vertices)
            {
                convVertices.Add(new float3(vv.X, vv.Y, vv.Z));
            }

            uint maxDepthSplit = (uint)BSParam.CSHullMaxDepthSplit;
            if (BSParam.CSHullMaxDepthSplit != BSParam.CSHullMaxDepthSplitForSimpleShapes)
            {
                // Simple primitive shapes we know are convex so they are better implemented with
                //    fewer hulls.
                // Check for simple shape (prim without cuts) and reduce split parameter if so.
                if (BSShapeCollection.PrimHasNoCuts(pbs))
                {
                    maxDepthSplit = (uint)BSParam.CSHullMaxDepthSplitForSimpleShapes;
                }
            }

            // setup and do convex hull conversion
            m_hulls = new List<ConvexResult>();
            DecompDesc dcomp = new DecompDesc();
            dcomp.mIndices = convIndices;
            dcomp.mVertices = convVertices;
            dcomp.mDepth = maxDepthSplit;
            dcomp.mCpercent = BSParam.CSHullConcavityThresholdPercent;
            dcomp.mPpercent = BSParam.CSHullVolumeConservationThresholdPercent;
            dcomp.mMaxVertices = (uint)BSParam.CSHullMaxVertices;
            dcomp.mSkinWidth = BSParam.CSHullMaxSkinWidth;
            ConvexBuilder convexBuilder = new ConvexBuilder(HullReturn);
            // create the hull into the _hulls variable
            convexBuilder.process(dcomp);

            physicsScene.DetailLog("{0},BSShapeCollection.CreatePhysicalHull,key={1},inVert={2},inInd={3},split={4},hulls={5}",
                                BSScene.DetailLogZero, newHullKey, indices.GetLength(0), vertices.Count, maxDepthSplit, m_hulls.Count);

            // Convert the vertices and indices for passing to unmanaged.
            // The hull information is passed as a large floating point array.
            // The format is:
            //  convHulls[0] = number of hulls
            //  convHulls[1] = number of vertices in first hull
            //  convHulls[2] = hull centroid X coordinate
            //  convHulls[3] = hull centroid Y coordinate
            //  convHulls[4] = hull centroid Z coordinate
            //  convHulls[5] = first hull vertex X
            //  convHulls[6] = first hull vertex Y
            //  convHulls[7] = first hull vertex Z
            //  convHulls[8] = second hull vertex X
            //  ...
            //  convHulls[n] = number of vertices in second hull
            //  convHulls[n+1] = second hull centroid X coordinate
            //  ...
            //
            // TODO: is is very inefficient. Someday change the convex hull generator to return
            //   data structures that do not need to be converted in order to pass to Bullet.
            //   And maybe put the values directly into pinned memory rather than marshaling.
            int hullCount = m_hulls.Count;
            int totalVertices = 1;          // include one for the count of the hulls
            foreach (ConvexResult cr in m_hulls)
            {
                totalVertices += 4;                         // add four for the vertex count and centroid
                totalVertices += cr.HullIndices.Count * 3;  // we pass just triangles
            }
            float[] convHulls = new float[totalVertices];

            convHulls[0] = (float)hullCount;
            int jj = 1;
            foreach (ConvexResult cr in m_hulls)
            {
                // copy vertices for index access
                float3[] verts = new float3[cr.HullVertices.Count];
                int kk = 0;
                foreach (float3 ff in cr.HullVertices)
                {
                    verts[kk++] = ff;
                }

                // add to the array one hull's worth of data
                convHulls[jj++] = cr.HullIndices.Count;
                convHulls[jj++] = 0f;   // centroid x,y,z
                convHulls[jj++] = 0f;
                convHulls[jj++] = 0f;
                foreach (int ind in cr.HullIndices)
                {
                    convHulls[jj++] = verts[ind].x;
                    convHulls[jj++] = verts[ind].y;
                    convHulls[jj++] = verts[ind].z;
                }
            }
            // create the hull data structure in Bullet
            newShape = physicsScene.PE.CreateHullShape(physicsScene.World, hullCount, convHulls);
        }
        newShape.shapeKey = newHullKey;
        return newShape;
    }
Ejemplo n.º 26
0
 public BSTerrainMesh(BSScene physicsScene, Vector3 regionBase, uint id, Vector3 regionSize)
     : base(physicsScene, regionBase, id)
 {
 }
 public BSActorMoveToTarget(BSScene physicsScene, BSPhysObject pObj, string actorName)
     : base(physicsScene, pObj, actorName)
 {
     m_targetMotor = null;
     m_physicsScene.DetailLog("{0},BSActorMoveToTarget,constructor", m_controllingPrim.LocalID);
 }
Ejemplo n.º 28
0
    // Create terrain mesh from a heightmap.
    public BSTerrainMesh(BSScene physicsScene, Vector3 regionBase, uint id, float[] initialMap,
                                                    Vector3 minCoords, Vector3 maxCoords)
        : base(physicsScene, regionBase, id)
    {
        int indicesCount;
        int[] indices;
        int verticesCount;
        float[] vertices;

        m_savedHeightMap = initialMap;

        m_sizeX = (int)(maxCoords.X - minCoords.X);
        m_sizeY = (int)(maxCoords.Y - minCoords.Y);

        bool meshCreationSuccess = false;
        if (BSParam.TerrainMeshMagnification == 1)
        {
            // If a magnification of one, use the old routine that is tried and true.
            meshCreationSuccess = BSTerrainMesh.ConvertHeightmapToMesh(m_physicsScene,
                                            initialMap, m_sizeX, m_sizeY,       // input size
                                            Vector3.Zero,                       // base for mesh
                                            out indicesCount, out indices, out verticesCount, out vertices);
        }
        else
        {
            // Other magnifications use the newer routine
            meshCreationSuccess = BSTerrainMesh.ConvertHeightmapToMesh2(m_physicsScene,
                                            initialMap, m_sizeX, m_sizeY,       // input size
                                            BSParam.TerrainMeshMagnification,
                                            physicsScene.TerrainManager.DefaultRegionSize,
                                            Vector3.Zero,                       // base for mesh
                                            out indicesCount, out indices, out verticesCount, out vertices);
        }
        if (!meshCreationSuccess)
        {
            // DISASTER!!
            m_physicsScene.DetailLog("{0},BSTerrainMesh.create,failedConversionOfHeightmap,id={1}", BSScene.DetailLogZero, ID);
            m_physicsScene.Logger.ErrorFormat("{0} Failed conversion of heightmap to mesh! base={1}", LogHeader, TerrainBase);
            // Something is very messed up and a crash is in our future.
            return;
        }

        m_physicsScene.DetailLog("{0},BSTerrainMesh.create,meshed,id={1},indices={2},indSz={3},vertices={4},vertSz={5}",
                                BSScene.DetailLogZero, ID, indicesCount, indices.Length, verticesCount, vertices.Length);

        m_terrainShape = m_physicsScene.PE.CreateMeshShape(m_physicsScene.World, indicesCount, indices, verticesCount, vertices);
        if (!m_terrainShape.HasPhysicalShape)
        {
            // DISASTER!!
            m_physicsScene.DetailLog("{0},BSTerrainMesh.create,failedCreationOfShape,id={1}", BSScene.DetailLogZero, ID);
            m_physicsScene.Logger.ErrorFormat("{0} Failed creation of terrain mesh! base={1}", LogHeader, TerrainBase);
            // Something is very messed up and a crash is in our future.
            return;
        }

        Vector3 pos = regionBase;
        Quaternion rot = Quaternion.Identity;

        m_terrainBody = m_physicsScene.PE.CreateBodyWithDefaultMotionState(m_terrainShape, ID, pos, rot);
        if (!m_terrainBody.HasPhysicalBody)
        {
            // DISASTER!!
            m_physicsScene.Logger.ErrorFormat("{0} Failed creation of terrain body! base={1}", LogHeader, TerrainBase);
            // Something is very messed up and a crash is in our future.
            return;
        }
        physicsScene.PE.SetShapeCollisionMargin(m_terrainShape, BSParam.TerrainCollisionMargin);

        // Set current terrain attributes
        m_physicsScene.PE.SetFriction(m_terrainBody, BSParam.TerrainFriction);
        m_physicsScene.PE.SetHitFraction(m_terrainBody, BSParam.TerrainHitFraction);
        m_physicsScene.PE.SetRestitution(m_terrainBody, BSParam.TerrainRestitution);
        m_physicsScene.PE.SetContactProcessingThreshold(m_terrainBody, BSParam.TerrainContactProcessingThreshold);
        m_physicsScene.PE.SetCollisionFlags(m_terrainBody, CollisionFlags.CF_STATIC_OBJECT);

        // Static objects are not very massive.
        m_physicsScene.PE.SetMassProps(m_terrainBody, 0f, Vector3.Zero);

        // Put the new terrain to the world of physical objects
        m_physicsScene.PE.AddObjectToWorld(m_physicsScene.World, m_terrainBody);

        // Redo its bounding box now that it is in the world
        m_physicsScene.PE.UpdateSingleAabb(m_physicsScene.World, m_terrainBody);

        m_terrainBody.collisionType = CollisionType.Terrain;
        m_terrainBody.ApplyCollisionMask(m_physicsScene);

        if (BSParam.UseSingleSidedMeshes)
        {
            m_physicsScene.DetailLog("{0},BSTerrainMesh.settingCustomMaterial,id={1}", BSScene.DetailLogZero, id);
            m_physicsScene.PE.AddToCollisionFlags(m_terrainBody, CollisionFlags.CF_CUSTOM_MATERIAL_CALLBACK);
        }

        // Make it so the terrain will not move or be considered for movement.
        m_physicsScene.PE.ForceActivationState(m_terrainBody, ActivationState.DISABLE_SIMULATION);
    }
Ejemplo n.º 29
0
    public static BSShape GetReference(BSScene physicsScene, bool forceRebuild, BSPhysObject prim)
    {
        float lod;
        System.UInt64 newHullKey = BSShape.ComputeShapeKey(prim.Size, prim.BaseShape, out lod);

        BSShapeHull retHull = null;
        lock (Hulls)
        {
            if (Hulls.TryGetValue(newHullKey, out retHull))
            {
                // The mesh has already been created. Return a new reference to same.
                retHull.IncrementReference();
            }
            else
            {
                retHull = new BSShapeHull(new BulletShape());
                // An instance of this mesh has not been created. Build and remember same.
                BulletShape newShape = retHull.CreatePhysicalHull(physicsScene, prim, newHullKey, prim.BaseShape, prim.Size, lod);

                // Check to see if hull was created (might require an asset).
                newShape = VerifyMeshCreated(physicsScene, newShape, prim);
                if (!newShape.isNativeShape || prim.AssetFailed())
                {
                    // If a mesh was what was created, remember the built shape for later sharing.
                    Hulls.Add(newHullKey, retHull);
                }
                retHull.physShapeInfo = newShape;
            }
        }
        physicsScene.DetailLog("{0},BSShapeHull,getReference,hull={1},size={2},lod={3}", prim.LocalID, retHull, prim.Size, lod);
        return retHull;
    }