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);
 }
Beispiel #2
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;
 }
Beispiel #3
0
    // Called to update/change the body and shape for an object.
    // The object has some shape and body on it. Here we decide if that is the correct shape
    //    for the current state of the object (static/dynamic/...).
    // If bodyCallback is not null, it is called if either the body or the shape are changed
    //    so dependencies (like constraints) can be removed before the physical object is dereferenced.
    // Return 'true' if either the body or the shape changed.
    // Called at taint-time.
    public bool GetBodyAndShape(bool forceRebuild, BulletWorld sim, BSPhysObject prim, PhysicalDestructionCallback bodyCallback)
    {
        m_physicsScene.AssertInTaintTime("BSShapeCollection.GetBodyAndShape");

        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 shape.
            // Returns 'true' of BSShape is changed to a new shape.
            bool newGeom = CreateGeom(forceRebuild, prim, bodyCallback);
            // 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
            // Returns 'true' if BSBody was changed.
            bool newBody = CreateBody((newGeom || forceRebuild), prim, m_physicsScene.World, bodyCallback);
            ret = newGeom || newBody;
        }
        DetailLog("{0},BSShapeCollection.GetBodyAndShape,taintExit,force={1},ret={2},body={3},shape={4}",
                                prim.LocalID, forceRebuild, ret, prim.PhysBody, prim.PhysShape);

        return ret;
    }
Beispiel #4
0
 // Called after a simulation step to post a collision with this object.
 // This returns 'true' if the collision has been queued and the SendCollisions call must
 //     be made at the end of the simulation step.
 public override bool Collide(uint collidingWith, BSPhysObject collidee,
                 OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth)
 {
     bool ret = false;
     // Ask the linkset if it wants to handle the collision
     if (!Linkset.HandleCollide(collidingWith, collidee, contactPoint, contactNormal, pentrationDepth))
     {
         // The linkset didn't handle it so pass the collision through normal processing
         ret = base.Collide(collidingWith, collidee, contactPoint, contactNormal, pentrationDepth);
     }
     return ret;
 }
Beispiel #5
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;
 }
Beispiel #6
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;
 }
Beispiel #7
0
    // Code that uses the mesher to create the index/vertices info for a trimesh shape.
    // This is used by the passed 'makeShape' call to create the Bullet mesh shape.
    // The actual build call is passed so this logic can be used by several of the shapes that use a
    //     simple mesh as their base shape.
    public static BulletShape CreatePhysicalMeshShape(BSScene physicsScene, BSPhysObject prim, System.UInt64 newMeshKey,
                                            PrimitiveBaseShape pbs, OMV.Vector3 size, float lod, CreateShapeCall makeShape)
    {
        BulletShape newShape = new BulletShape();

        IMesh meshData = null;
        lock (physicsScene.mesher)
        {
            meshData = physicsScene.mesher.CreateMesh(prim.PhysObjectName, pbs, size, lod,
                                            false,  // say it is not physical so a bounding box is not built
                                            false,   // do not cache the mesh and do not use previously built versions
                                            false,
                                            false
                                            );
        }

        if (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();
            int realIndicesIndex = indices.Length;
            float[] verticesAsFloats = meshData.getVertexListAsFloat();

            if (BSParam.ShouldRemoveZeroWidthTriangles)
            {
                // Remove degenerate triangles. These are triangles with two of the vertices
                //    are the same. This is complicated by the problem that vertices are not
                //    made unique in sculpties so we have to compare the values in the vertex.
                realIndicesIndex = 0;
                for (int tri = 0; tri < indices.Length; tri += 3)
                {
                    // Compute displacements into vertex array for each vertex of the triangle
                    int v1 = indices[tri + 0] * 3;
                    int v2 = indices[tri + 1] * 3;
                    int v3 = indices[tri + 2] * 3;
                // Check to see if any two of the vertices are the same
                    if (!( (  verticesAsFloats[v1 + 0] == verticesAsFloats[v2 + 0]
                           && verticesAsFloats[v1 + 1] == verticesAsFloats[v2 + 1]
                           && verticesAsFloats[v1 + 2] == verticesAsFloats[v2 + 2])
                        || (  verticesAsFloats[v2 + 0] == verticesAsFloats[v3 + 0]
                           && verticesAsFloats[v2 + 1] == verticesAsFloats[v3 + 1]
                           && verticesAsFloats[v2 + 2] == verticesAsFloats[v3 + 2])
                        || (  verticesAsFloats[v1 + 0] == verticesAsFloats[v3 + 0]
                           && verticesAsFloats[v1 + 1] == verticesAsFloats[v3 + 1]
                           && verticesAsFloats[v1 + 2] == verticesAsFloats[v3 + 2]) )
                    )
                    {
                        // None of the vertices of the triangles are the same. This is a good triangle;
                        indices[realIndicesIndex + 0] = indices[tri + 0];
                        indices[realIndicesIndex + 1] = indices[tri + 1];
                        indices[realIndicesIndex + 2] = indices[tri + 2];
                        realIndicesIndex += 3;
                    }
                }
            }
            physicsScene.DetailLog("{0},BSShapeMesh.CreatePhysicalMesh,key={1},origTri={2},realTri={3},numVerts={4}",
                        BSScene.DetailLogZero, newMeshKey.ToString("X"), indices.Length / 3, realIndicesIndex / 3, verticesAsFloats.Length / 3);

            if (realIndicesIndex != 0)
            {
                newShape = makeShape(physicsScene.World, realIndicesIndex, indices, verticesAsFloats.Length / 3, verticesAsFloats);
            }
            else
            {
                // Force the asset condition to 'failed' so we won't try to keep fetching and processing this mesh.
                prim.PrimAssetState = BSPhysObject.PrimAssetCondition.FailedMeshing;
                physicsScene.Logger.DebugFormat("{0} All mesh triangles degenerate. Prim={1}", LogHeader, UsefulPrimInfo(physicsScene, prim) );
                physicsScene.DetailLog("{0},BSShapeMesh.CreatePhysicalMesh,allDegenerate,key={1}", prim.LocalID, newMeshKey);
            }
        }
        newShape.shapeKey = newMeshKey;

        return newShape;
    }
Beispiel #8
0
    public static BSShape GetReference(BSScene physicsScene, bool forceRebuild, BSPhysObject prim)
    {
        float lod;
        System.UInt64 newMeshKey = BSShape.ComputeShapeKey(prim.Size, prim.BaseShape, out lod);

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

                // Check to see if mesh 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.
                    // Also note that if meshing failed we put it in the mesh list as there is nothing else to do about the mesh.
                    Meshes.Add(newMeshKey, retMesh);
                }

                retMesh.physShapeInfo = newShape;
            }
        }
        physicsScene.DetailLog("{0},BSShapeMesh,getReference,mesh={1},size={2},lod={3}", prim.LocalID, retMesh, prim.Size, lod);
        return retMesh;
    }
Beispiel #9
0
 public override BSShape GetReference(BSScene pPhysicsScene, BSPhysObject pPrim)
 {
     // Native shapes are not shared so we return a new shape.
     BSShape ret = null;
     lock (physShapeInfo)
     {
         ret = new BSShapeNative(CreatePhysicalNativeShape(pPhysicsScene, pPrim,
                                     physShapeInfo.shapeType, (FixedShapeKey)physShapeInfo.shapeKey));
     }
     return ret;
 }
Beispiel #10
0
 public override BSShape GetReference(BSScene pPhysicsScene, BSPhysObject pPrim) { return new BSShapeNull();  }
Beispiel #11
0
    // return 'true' if the prim's shape was changed.
    private bool CreateGeomMeshOrHull(BSPhysObject prim, PhysicalDestructionCallback shapeCallback)
    {

        bool ret = false;
        // Note that if it's a native shape, the check for physical/non-physical is not
        //     made. Native shapes work in either case.
        if (prim.IsPhysical && BSParam.ShouldUseHullsForPhysicalObjects)
        {
            // Use a simple, single mesh convex hull shape if the object is simple enough
            BSShape potentialHull = null;

            PrimitiveBaseShape pbs = prim.BaseShape;
            // Use a simple, one section convex shape for prims that are probably convex (no cuts or twists)
            if (BSParam.ShouldUseSingleConvexHullForPrims
                && pbs != null
                && !pbs.SculptEntry
                && PrimHasNoCuts(pbs)
                )
            {
                potentialHull = BSShapeConvexHull.GetReference(m_physicsScene, false /* forceRebuild */, prim);
            }
            // Use the GImpact shape if it is a prim that has some concaveness
            if (potentialHull == null
                && BSParam.ShouldUseGImpactShapeForPrims
                && pbs != null
                && !pbs.SculptEntry
                )
            {
                    potentialHull = BSShapeGImpact.GetReference(m_physicsScene, false /* forceRebuild */, prim);
            }
            // If not any of the simple cases, just make a hull
            if (potentialHull == null)
            {
                potentialHull = BSShapeHull.GetReference(m_physicsScene, false /*forceRebuild*/, prim);
            }

            // If the current shape is not what is on the prim at the moment, time to change.
            if (!prim.PhysShape.HasPhysicalShape
                        || potentialHull.ShapeType != prim.PhysShape.ShapeType
                        || potentialHull.physShapeInfo.shapeKey != prim.PhysShape.physShapeInfo.shapeKey)
            {
                DereferenceExistingShape(prim, shapeCallback);
                prim.PhysShape = potentialHull;
                ret = true;
            }
            else
            {
                // The current shape on the prim is the correct one. We don't need the potential reference.
                potentialHull.Dereference(m_physicsScene);
            }
            if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,hull,shape={1}", prim.LocalID, prim.PhysShape);
        }
        else
        {
            // Non-physical objects should be just meshes.
            BSShape potentialMesh = BSShapeMesh.GetReference(m_physicsScene, false /*forceRebuild*/, prim);
            // If the current shape is not what is on the prim at the moment, time to change.
            if (!prim.PhysShape.HasPhysicalShape
                        || potentialMesh.ShapeType != prim.PhysShape.ShapeType
                        || potentialMesh.physShapeInfo.shapeKey != prim.PhysShape.physShapeInfo.shapeKey)
            {
                DereferenceExistingShape(prim, shapeCallback);
                prim.PhysShape = potentialMesh;
                ret = true;
            }
            else
            {
                // We don't need this reference to the mesh that is already being using.
                potentialMesh.Dereference(m_physicsScene);
            }
            if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,mesh,shape={1}", prim.LocalID, prim.PhysShape);
        }
        return ret;
    }
Beispiel #12
0
    private bool CreateGeom(bool forceRebuild, BSPhysObject prim, PhysicalDestructionCallback shapeCallback)
    {
        bool ret = false;
        bool haveShape = false;
        bool nativeShapePossible = true;
        PrimitiveBaseShape pbs = prim.BaseShape;

        // Kludge to create the capsule for the avatar.
        // TDOD: Remove/redo this when BSShapeAvatar is working!!
        BSCharacter theChar = prim as BSCharacter;
        if (theChar != null)
        {
            DereferenceExistingShape(prim, shapeCallback);
            switch (BSParam.AvatarShape)
            {
                case AvatarShapeCapsule:
                    prim.PhysShape = BSShapeNative.GetReference(m_physicsScene, prim,
                                            BSPhysicsShapeType.SHAPE_CAPSULE, FixedShapeKey.KEY_CAPSULE);
                    ret = true;
                    haveShape = true;
                    break;
                case AvatarShapeCube:
                    prim.PhysShape = BSShapeNative.GetReference(m_physicsScene, prim,
                                            BSPhysicsShapeType.SHAPE_BOX, FixedShapeKey.KEY_CAPSULE);
                    ret = true;
                    haveShape = true;
                    break;
                case AvatarShapeOvoid:
                    // Saddly, Bullet doesn't scale spheres so this doesn't work as an avatar shape
                    prim.PhysShape = BSShapeNative.GetReference(m_physicsScene, prim,
                                            BSPhysicsShapeType.SHAPE_SPHERE, FixedShapeKey.KEY_CAPSULE);
                    ret = true;
                    haveShape = true;
                    break;
                case AvatarShapeMesh:
                    break;
                default:
                    break;
            }
        }

        // If the prim attributes are simple, this could be a simple Bullet native shape
        // Native shapes work whether to object is static or physical.
        if (!haveShape
                && nativeShapePossible
                && pbs != null
                && PrimHasNoCuts(pbs)
                && ( !pbs.SculptEntry || (pbs.SculptEntry && !BSParam.ShouldMeshSculptedPrim) )
            )
        {
            // Get the scale of any existing shape so we can see if the new shape is same native type and same size.
            OMV.Vector3 scaleOfExistingShape = OMV.Vector3.Zero;
            if (prim.PhysShape.HasPhysicalShape)
                scaleOfExistingShape = m_physicsScene.PE.GetLocalScaling(prim.PhysShape.physShapeInfo);

            if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,maybeNative,force={1},primScale={2},primSize={3},primShape={4}",
                        prim.LocalID, forceRebuild, prim.Scale, prim.Size, prim.PhysShape.physShapeInfo.shapeType);

            // It doesn't look like Bullet scales native spheres so make sure the scales are all equal
            if ((pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1)
                                && pbs.Scale.X == pbs.Scale.Y && pbs.Scale.Y == pbs.Scale.Z)
            {
                haveShape = true;
                if (forceRebuild
                        || prim.PhysShape.ShapeType != BSPhysicsShapeType.SHAPE_SPHERE
                    )
                {
                    DereferenceExistingShape(prim, shapeCallback);
                    prim.PhysShape = BSShapeNative.GetReference(m_physicsScene, prim,
                                            BSPhysicsShapeType.SHAPE_SPHERE, FixedShapeKey.KEY_SPHERE);
                    ret = true;
                }
                if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,sphere,force={1},rebuilt={2},shape={3}",
                                        prim.LocalID, forceRebuild, ret, prim.PhysShape);
            }
            // If we didn't make a sphere, maybe a box will work.
            if (!haveShape && pbs.ProfileShape == ProfileShape.Square && pbs.PathCurve == (byte)Extrusion.Straight)
            {
                haveShape = true;
                if (forceRebuild
                        || prim.Scale != scaleOfExistingShape
                        || prim.PhysShape.ShapeType != BSPhysicsShapeType.SHAPE_BOX
                        )
                {
                    DereferenceExistingShape(prim, shapeCallback);
                    prim.PhysShape = BSShapeNative.GetReference(m_physicsScene, prim,
                                            BSPhysicsShapeType.SHAPE_BOX, FixedShapeKey.KEY_BOX);
                    ret = true;
                }
                if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,box,force={1},rebuilt={2},shape={3}",
                                        prim.LocalID, forceRebuild, ret, prim.PhysShape);
            }
        }

        // If a simple shape is not happening, create a mesh and possibly a hull.
        if (!haveShape && pbs != null)
        {
            ret = CreateGeomMeshOrHull(prim, shapeCallback);
        }

        return ret;
    }
Beispiel #13
0
 // If the existing prim's shape is to be replaced, remove the tie to the existing shape
 //     before replacing it.
 private void DereferenceExistingShape(BSPhysObject prim, PhysicalDestructionCallback shapeCallback)
 {
     if (prim.PhysShape.HasPhysicalShape)
     {
         if (shapeCallback != null)
             shapeCallback(prim.PhysBody, prim.PhysShape.physShapeInfo);
         prim.PhysShape.Dereference(m_physicsScene);
     }
     prim.PhysShape = new BSShapeNull();
 }
Beispiel #14
0
 public bool GetBodyAndShape(bool forceRebuild, BulletWorld sim, BSPhysObject prim)
 {
     return GetBodyAndShape(forceRebuild, sim, prim, null);
 }
Beispiel #15
0
 public BSActorHover(BSScene physicsScene, BSPhysObject pObj, string actorName)
     : base(physicsScene, pObj, actorName)
 {
     m_hoverMotor = null;
     m_physicsScene.DetailLog("{0},BSActorHover,constructor", m_controllingPrim.LocalID);
 }
Beispiel #16
0
        // return 'true' if the prim's shape was changed.
        private bool CreateGeomMeshOrHull(BSPhysObject prim, PhysicalDestructionCallback shapeCallback)
        {
            bool ret = false;

            // Note that if it's a native shape, the check for physical/non-physical is not
            //     made. Native shapes work in either case.
            if (prim.IsPhysical && BSParam.ShouldUseHullsForPhysicalObjects)
            {
                // Use a simple, single mesh convex hull shape if the object is simple enough
                BSShape potentialHull = null;

                PrimitiveBaseShape pbs = prim.BaseShape;
                // Use a simple, one section convex shape for prims that are probably convex (no cuts or twists)
                if (BSParam.ShouldUseSingleConvexHullForPrims &&
                    pbs != null &&
                    !pbs.SculptEntry &&
                    PrimHasNoCuts(pbs)
                    )
                {
                    potentialHull = BSShapeConvexHull.GetReference(m_physicsScene, false /* forceRebuild */, prim);
                }
                // Use the GImpact shape if it is a prim that has some concaveness
                if (potentialHull == null &&
                    BSParam.ShouldUseGImpactShapeForPrims &&
                    pbs != null &&
                    !pbs.SculptEntry
                    )
                {
                    potentialHull = BSShapeGImpact.GetReference(m_physicsScene, false /* forceRebuild */, prim);
                }
                // If not any of the simple cases, just make a hull
                if (potentialHull == null)
                {
                    potentialHull = BSShapeHull.GetReference(m_physicsScene, false /*forceRebuild*/, prim);
                }

                // If the current shape is not what is on the prim at the moment, time to change.
                if (!prim.PhysShape.HasPhysicalShape ||
                    potentialHull.ShapeType != prim.PhysShape.ShapeType ||
                    potentialHull.physShapeInfo.shapeKey != prim.PhysShape.physShapeInfo.shapeKey)
                {
                    DereferenceExistingShape(prim, shapeCallback);
                    prim.PhysShape = potentialHull;
                    ret            = true;
                }
                else
                {
                    // The current shape on the prim is the correct one. We don't need the potential reference.
                    potentialHull.Dereference(m_physicsScene);
                }
                if (DDetail)
                {
                    DetailLog("{0},BSShapeCollection.CreateGeom,hull,shape={1}", prim.LocalID, prim.PhysShape);
                }
            }
            else
            {
                // Non-physical objects should be just meshes.
                BSShape potentialMesh = BSShapeMesh.GetReference(m_physicsScene, false /*forceRebuild*/, prim);
                // If the current shape is not what is on the prim at the moment, time to change.
                if (!prim.PhysShape.HasPhysicalShape ||
                    potentialMesh.ShapeType != prim.PhysShape.ShapeType ||
                    potentialMesh.physShapeInfo.shapeKey != prim.PhysShape.physShapeInfo.shapeKey)
                {
                    DereferenceExistingShape(prim, shapeCallback);
                    prim.PhysShape = potentialMesh;
                    ret            = true;
                }
                else
                {
                    // We don't need this reference to the mesh that is already being using.
                    potentialMesh.Dereference(m_physicsScene);
                }
                if (DDetail)
                {
                    DetailLog("{0},BSShapeCollection.CreateGeom,mesh,shape={1}", prim.LocalID, prim.PhysShape);
                }
            }
            return(ret);
        }
Beispiel #17
0
        private bool CreateGeom(bool forceRebuild, BSPhysObject prim, PhysicalDestructionCallback shapeCallback)
        {
            bool ret                 = false;
            bool haveShape           = false;
            bool nativeShapePossible = true;
            PrimitiveBaseShape pbs   = prim.BaseShape;

            // Kludge to create the capsule for the avatar.
            // TDOD: Remove/redo this when BSShapeAvatar is working!!
            BSCharacter theChar = prim as BSCharacter;

            if (theChar != null)
            {
                DereferenceExistingShape(prim, shapeCallback);
                switch (BSParam.AvatarShape)
                {
                case AvatarShapeCapsule:
                    prim.PhysShape = BSShapeNative.GetReference(m_physicsScene, prim,
                                                                BSPhysicsShapeType.SHAPE_CAPSULE, FixedShapeKey.KEY_CAPSULE);
                    ret       = true;
                    haveShape = true;
                    break;

                case AvatarShapeCube:
                    prim.PhysShape = BSShapeNative.GetReference(m_physicsScene, prim,
                                                                BSPhysicsShapeType.SHAPE_BOX, FixedShapeKey.KEY_CAPSULE);
                    ret       = true;
                    haveShape = true;
                    break;

                case AvatarShapeOvoid:
                    // Saddly, Bullet doesn't scale spheres so this doesn't work as an avatar shape
                    prim.PhysShape = BSShapeNative.GetReference(m_physicsScene, prim,
                                                                BSPhysicsShapeType.SHAPE_SPHERE, FixedShapeKey.KEY_CAPSULE);
                    ret       = true;
                    haveShape = true;
                    break;

                case AvatarShapeMesh:
                    break;

                default:
                    break;
                }
            }

            // If the prim attributes are simple, this could be a simple Bullet native shape
            // Native shapes work whether to object is static or physical.
            if (!haveShape &&
                nativeShapePossible &&
                pbs != null &&
                PrimHasNoCuts(pbs) &&
                (!pbs.SculptEntry || (pbs.SculptEntry && !BSParam.ShouldMeshSculptedPrim))
                )
            {
                // Get the scale of any existing shape so we can see if the new shape is same native type and same size.
                OMV.Vector3 scaleOfExistingShape = OMV.Vector3.Zero;
                if (prim.PhysShape.HasPhysicalShape)
                {
                    scaleOfExistingShape = m_physicsScene.PE.GetLocalScaling(prim.PhysShape.physShapeInfo);
                }

                if (DDetail)
                {
                    DetailLog("{0},BSShapeCollection.CreateGeom,maybeNative,force={1},primScale={2},primSize={3},primShape={4}",
                              prim.LocalID, forceRebuild, prim.Scale, prim.Size, prim.PhysShape.physShapeInfo.shapeType);
                }

                // It doesn't look like Bullet scales native spheres so make sure the scales are all equal
                if ((pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1) &&
                    pbs.Scale.X == pbs.Scale.Y && pbs.Scale.Y == pbs.Scale.Z)
                {
                    haveShape = true;
                    if (forceRebuild ||
                        prim.PhysShape.ShapeType != BSPhysicsShapeType.SHAPE_SPHERE
                        )
                    {
                        DereferenceExistingShape(prim, shapeCallback);
                        prim.PhysShape = BSShapeNative.GetReference(m_physicsScene, prim,
                                                                    BSPhysicsShapeType.SHAPE_SPHERE, FixedShapeKey.KEY_SPHERE);
                        ret = true;
                    }
                    if (DDetail)
                    {
                        DetailLog("{0},BSShapeCollection.CreateGeom,sphere,force={1},rebuilt={2},shape={3}",
                                  prim.LocalID, forceRebuild, ret, prim.PhysShape);
                    }
                }
                // If we didn't make a sphere, maybe a box will work.
                if (!haveShape && pbs.ProfileShape == ProfileShape.Square && pbs.PathCurve == (byte)Extrusion.Straight)
                {
                    haveShape = true;
                    if (forceRebuild ||
                        prim.Scale != scaleOfExistingShape ||
                        prim.PhysShape.ShapeType != BSPhysicsShapeType.SHAPE_BOX
                        )
                    {
                        DereferenceExistingShape(prim, shapeCallback);
                        prim.PhysShape = BSShapeNative.GetReference(m_physicsScene, prim,
                                                                    BSPhysicsShapeType.SHAPE_BOX, FixedShapeKey.KEY_BOX);
                        ret = true;
                    }
                    if (DDetail)
                    {
                        DetailLog("{0},BSShapeCollection.CreateGeom,box,force={1},rebuilt={2},shape={3}",
                                  prim.LocalID, forceRebuild, ret, prim.PhysShape);
                    }
                }
            }

            // If a simple shape is not happening, create a mesh and possibly a hull.
            if (!haveShape && pbs != null)
            {
                ret = CreateGeomMeshOrHull(prim, shapeCallback);
            }

            m_physicsScene.PE.ResetBroadphasePool(m_physicsScene.World); // DEBUG DEBUG

            return(ret);
        }
Beispiel #18
0
 public static String UsefulPrimInfo(BSScene pScene, BSPhysObject prim)
 {
     StringBuilder buff = new StringBuilder(prim.PhysObjectName);
     buff.Append("/pos=");
     buff.Append(prim.RawPosition.ToString());
     if (pScene != null)
     {
         buff.Append("/rgn=");
         buff.Append(pScene.PhysicsSceneName);
     }
     return buff.ToString();
 }
Beispiel #19
0
    // 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, BSPhysObject prim, BulletWorld sim, PhysicalDestructionCallback bodyCallback)
    {
        bool ret = false;

        // the mesh, hull or native shape must have already been created in Bullet
        bool mustRebuild = !prim.PhysBody.HasPhysicalBody;

        // 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)m_physicsScene.PE.GetBodyType(prim.PhysBody);
            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 (DDetail) DetailLog("{0},BSShapeCollection.CreateBody,forceRebuildBecauseChangingBodyType,bodyType={1}", prim.LocalID, bodyType);
            }
        }

        if (mustRebuild || forceRebuild)
        {
            // Free any old body
            DereferenceBody(prim.PhysBody, bodyCallback);

            BulletBody aBody;
            if (prim.IsSolid)
            {
                aBody = m_physicsScene.PE.CreateBodyFromShape(sim, prim.PhysShape.physShapeInfo, prim.LocalID, prim.RawPosition, prim.RawOrientation);
                if (DDetail) DetailLog("{0},BSShapeCollection.CreateBody,rigid,body={1}", prim.LocalID, aBody);
            }
            else
            {
                aBody = m_physicsScene.PE.CreateGhostFromShape(sim, prim.PhysShape.physShapeInfo, prim.LocalID, prim.RawPosition, prim.RawOrientation);
                if (DDetail) DetailLog("{0},BSShapeCollection.CreateBody,ghost,body={1}", prim.LocalID, aBody);
            }

            ReferenceBody(aBody);

            prim.PhysBody = aBody;

            ret = true;
        }

        return ret;
    }
Beispiel #20
0
 public static BSShape GetReference(BSScene physicsScene, BSPhysObject prim,
                                         BSPhysicsShapeType shapeType, FixedShapeKey shapeKey)
 {
     // Native shapes are not shared and are always built anew.
     return new BSShapeNative(CreatePhysicalNativeShape(physicsScene, prim, shapeType, shapeKey));
 }
Beispiel #21
0
    public virtual bool Collide(uint collidingWith, BSPhysObject collidee,
                    OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth)
    {
        bool ret = false;

        // The following lines make IsColliding(), CollidingGround() and CollidingObj work
        CollidingStep = PhysScene.SimulationStep;
        if (collidingWith <= PhysScene.TerrainManager.HighestTerrainID)
        {
            CollidingGroundStep = PhysScene.SimulationStep;
        }
        else
        {
            CollidingObjectStep = PhysScene.SimulationStep;
        }

        CollisionAccumulation++;

        // For movement tests, remember if we are colliding with an object that is moving.
        ColliderIsMoving = collidee != null ? (collidee.RawVelocity != OMV.Vector3.Zero) : false;
        ColliderIsVolumeDetect = collidee != null ? (collidee.IsVolumeDetect) : false;

        // Make a collection of the collisions that happened the last simulation tick.
        // This is different than the collection created for sending up to the simulator as it is cleared every tick.
        if (CollisionsLastTickStep != PhysScene.SimulationStep)
        {
            CollisionsLastTick = new CollisionEventUpdate();
            CollisionsLastTickStep = PhysScene.SimulationStep;
        }
        CollisionsLastTick.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth));

        // If someone has subscribed for collision events log the collision so it will be reported up
        if (SubscribedEvents()) {
            lock (PhysScene.CollisionLock)
            {
                CollisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth));
            }
            DetailLog("{0},{1}.Collision.AddCollider,call,with={2},point={3},normal={4},depth={5},colliderMoving={6}",
                            LocalID, TypeName, collidingWith, contactPoint, contactNormal, pentrationDepth, ColliderIsMoving);

            ret = true;
        }
        return ret;
    }
Beispiel #22
0
    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;
    }
Beispiel #23
0
    public static BSShape GetReference(BSScene physicsScene, bool forceRebuild, BSPhysObject prim)
    {
        float lod;
        System.UInt64 newMeshKey = BSShape.ComputeShapeKey(prim.Size, prim.BaseShape, out lod);

        physicsScene.DetailLog("{0},BSShapeConvexHull,getReference,newKey={1},size={2},lod={3}",
                                prim.LocalID, newMeshKey.ToString("X"), prim.Size, lod);

        BSShapeConvexHull retConvexHull = null;
        lock (ConvexHulls)
        {
            if (ConvexHulls.TryGetValue(newMeshKey, out retConvexHull))
            {
                // The mesh has already been created. Return a new reference to same.
                retConvexHull.IncrementReference();
            }
            else
            {
                retConvexHull = new BSShapeConvexHull(new BulletShape());
                BulletShape convexShape = null;

                // Get a handle to a mesh to build the hull from
                BSShape baseMesh = BSShapeMesh.GetReference(physicsScene, false /* forceRebuild */, prim);
                if (baseMesh.physShapeInfo.isNativeShape)
                {
                    // We get here if the mesh was not creatable. Could be waiting for an asset from the disk.
                    // In the short term, we return the native shape and a later ForceBodyShapeRebuild should
                    //     get back to this code with a buildable mesh.
                    // TODO: not sure the temp native shape is freed when the mesh is rebuilt. When does this get freed?
                    convexShape = baseMesh.physShapeInfo;
                }
                else
                {
                    convexShape = physicsScene.PE.BuildConvexHullShapeFromMesh(physicsScene.World, baseMesh.physShapeInfo);
                    convexShape.shapeKey = newMeshKey;
                    ConvexHulls.Add(convexShape.shapeKey, retConvexHull);
                    physicsScene.DetailLog("{0},BSShapeConvexHull.GetReference,addingNewlyCreatedShape,shape={1}",
                                        BSScene.DetailLogZero, convexShape);
                }

                // Done with the base mesh
                baseMesh.Dereference(physicsScene);

                retConvexHull.physShapeInfo = convexShape;
            }
        }
        return retConvexHull;
    }
Beispiel #24
0
 private BulletShape CreatePhysicalMesh(BSScene physicsScene, BSPhysObject prim, System.UInt64 newMeshKey,
                                         PrimitiveBaseShape pbs, OMV.Vector3 size, float lod)
 {
     return BSShapeMesh.CreatePhysicalMeshShape(physicsScene, prim, newMeshKey, pbs, size, lod,
                         (w, iC, i, vC, v) =>
                         {
                             shapeInfo.Vertices = vC;
                             return physicsScene.PE.CreateMeshShape(w, iC, i, vC, v);
                         });
 }
Beispiel #25
0
    public static BSShape GetReference(BSScene physicsScene, bool forceRebuild, BSPhysObject prim)
    {
        float lod;
        System.UInt64 newMeshKey = BSShape.ComputeShapeKey(prim.Size, prim.BaseShape, out lod);

        physicsScene.DetailLog("{0},BSShapeGImpact,getReference,newKey={1},size={2},lod={3}",
                                prim.LocalID, newMeshKey.ToString("X"), prim.Size, lod);

        BSShapeGImpact retGImpact = null;
        lock (GImpacts)
        {
            if (GImpacts.TryGetValue(newMeshKey, out retGImpact))
            {
                // The mesh has already been created. Return a new reference to same.
                retGImpact.IncrementReference();
            }
            else
            {
                retGImpact = new BSShapeGImpact(new BulletShape());
                BulletShape newShape = retGImpact.CreatePhysicalGImpact(physicsScene, prim, newMeshKey, prim.BaseShape, prim.Size, lod);

                // Check to see if mesh was created (might require an asset).
                newShape = VerifyMeshCreated(physicsScene, newShape, prim);
                newShape.shapeKey = newMeshKey;
                if (!newShape.isNativeShape || prim.AssetFailed())
                {
                    // If a mesh was what was created, remember the built shape for later sharing.
                    // Also note that if meshing failed we put it in the mesh list as there is nothing
                    //         else to do about the mesh.
                    GImpacts.Add(newMeshKey, retGImpact);
                }

                retGImpact.physShapeInfo = newShape;
            }
        }
        return retGImpact;
    }
Beispiel #26
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;
    }
Beispiel #27
0
 public static BSShape GetReference(BSPhysObject prim)
 {
     return new BSShapeNull();
 }
Beispiel #28
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;
    }
 public BSActorMoveToTarget(BSScene physicsScene, BSPhysObject pObj, string actorName)
     : base(physicsScene, pObj, actorName)
 {
     m_targetMotor = null;
     m_physicsScene.DetailLog("{0},BSActorMoveToTarget,constructor", m_controllingPrim.LocalID);
 }
Beispiel #30
0
        // The simulation step is telling this object about a collision.
        // I'm the 'collider', the thing I'm colliding with is the 'collidee'.
        // Return 'true' if a collision was processed and should be sent up.
        // Return 'false' if this object is not enabled/subscribed/appropriate for or has already seen this collision.
        // Called at taint time from within the Step() function
        public virtual bool Collide(BSPhysObject collidee, OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth)
        {
            bool ret = false;

            // if 'collidee' is null, that means it is terrain
            uint collideeLocalID = (collidee == null) ? BSScene.TERRAIN_ID : collidee.LocalID;

            // All terrain goes by the TERRAIN_ID id when passed up as a collision
            if (collideeLocalID <= PhysScene.TerrainManager.HighestTerrainID)
            {
                collideeLocalID = BSScene.TERRAIN_ID;
            }

            // The following lines make IsColliding(), CollidingGround() and CollidingObj work
            CollidingStep = PhysScene.SimulationStep;
            if (collideeLocalID == BSScene.TERRAIN_ID)
            {
                CollidingGroundStep = PhysScene.SimulationStep;
            }
            else
            {
                CollidingObjectStep = PhysScene.SimulationStep;
            }

            CollisionAccumulation++;

            // For movement tests, if the collider is me, remember if we are colliding with an object that is moving.
            // Here the 'collider'/'collidee' thing gets messed up. In the larger context, when something is checking
            //     if the thing it is colliding with is moving, for instance, it asks if the its collider is moving.
            ColliderIsMoving       = collidee != null ? (collidee.RawVelocity != OMV.Vector3.Zero || collidee.RotationalVelocity != OMV.Vector3.Zero) : false;
            ColliderIsVolumeDetect = collidee != null ? (collidee.IsVolumeDetect) : false;


            // Make a collection of the collisions that happened the last simulation tick.
            // This is different than the collection created for sending up to the simulator as it is cleared every tick.
            if (CollisionsLastTickStep != PhysScene.SimulationStep)
            {
                CollisionsLastTick     = new CollisionEventUpdate();
                CollisionsLastTickStep = PhysScene.SimulationStep;
            }
            CollisionsLastTick.AddCollider(collideeLocalID, new ContactPoint(contactPoint, contactNormal, pentrationDepth));

            // If someone has subscribed for collision events log the collision so it will be reported up
            if (SubscribedEvents())
            {
                ContactPoint newContact = new ContactPoint(contactPoint, contactNormal, pentrationDepth);

                // Collision sound requires a velocity to know it should happen. This is a lot of computation for a little used feature.
                OMV.Vector3 relvel = OMV.Vector3.Zero;
                if (IsPhysical)
                {
                    relvel = RawVelocity;
                }
                if (collidee != null && collidee.IsPhysical)
                {
                    relvel -= collidee.RawVelocity;
                }
                newContact.RelativeSpeed = -OMV.Vector3.Dot(relvel, contactNormal);
                // DetailLog("{0},{1}.Collision.AddCollider,vel={2},contee.vel={3},relvel={4},relspeed={5}",
                //         LocalID, TypeName, RawVelocity, (collidee == null ? OMV.Vector3.Zero : collidee.RawVelocity), relvel, newContact.RelativeSpeed);

                lock (PhysScene.CollisionLock)
                {
                    CollisionCollection.AddCollider(collideeLocalID, newContact);
                }
                DetailLog("{0},{1}.Collision.AddCollider,call,with={2},point={3},normal={4},depth={5},speed={6},colliderMoving={7}",
                          LocalID, TypeName, collideeLocalID, contactPoint, contactNormal, pentrationDepth,
                          newContact.RelativeSpeed, ColliderIsMoving);

                ret = true;
            }
            return(ret);
        }
Beispiel #31
0
 // Get another reference to this shape.
 public abstract BSShape GetReference(BSScene pPhysicsScene, BSPhysObject pPrim);
Beispiel #32
0
 public bool GetBodyAndShape(bool forceRebuild, BulletWorld sim, BSPhysObject prim)
 {
     return(GetBodyAndShape(forceRebuild, sim, prim, null));
 }
Beispiel #33
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);
 }
Beispiel #34
0
    // 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 failed decompression of JPEG2000s).
    //     The first case causes the asset to be fetched. The second case requires
    //     us to not loop forever.
    // Called after creating a physical mesh or hull. If the physical shape was created,
    //     just return.
    public static BulletShape VerifyMeshCreated(BSScene physicsScene, BulletShape newShape, BSPhysObject prim)
    {
        // If the shape was successfully created, nothing more to do
        if (newShape.HasPhysicalShape)
            return newShape;

        // VerifyMeshCreated is called after trying to create the mesh. If we think the asset had been
        //    fetched but we end up here again, the meshing of the asset must have failed.
        // Prevent trying to keep fetching the mesh by declaring failure.
        if (prim.PrimAssetState == BSPhysObject.PrimAssetCondition.Fetched)
        {
            prim.PrimAssetState = BSPhysObject.PrimAssetCondition.FailedMeshing;
            physicsScene.Logger.WarnFormat("{0} Fetched asset would not mesh. prim={1}, texture={2}",
                                            LogHeader, UsefulPrimInfo(physicsScene, prim), prim.BaseShape.SculptTexture);
            physicsScene.DetailLog("{0},BSShape.VerifyMeshCreated,setFailed,prim={1},tex={2}",
                                            prim.LocalID, UsefulPrimInfo(physicsScene, prim), prim.BaseShape.SculptTexture);
        }
        else
        {
            // If this mesh has an underlying asset and we have not failed getting it before, fetch the asset
            if (prim.BaseShape.SculptEntry
                && !prim.AssetFailed()
                && prim.PrimAssetState != BSPhysObject.PrimAssetCondition.Waiting
                && prim.BaseShape.SculptTexture != OMV.UUID.Zero
                )
            {
                physicsScene.DetailLog("{0},BSShape.VerifyMeshCreated,fetchAsset,objNam={1},tex={2}",
                                            prim.LocalID, prim.PhysObjectName, prim.BaseShape.SculptTexture);
                // Multiple requestors will know we're waiting for this asset
                prim.PrimAssetState = BSPhysObject.PrimAssetCondition.Waiting;

                BSPhysObject xprim = prim;
                RequestAssetDelegate assetProvider = physicsScene.RequestAssetMethod;
                if (assetProvider != null)
                {
                    BSPhysObject yprim = xprim; // probably not necessary, but, just in case.
                    assetProvider(yprim.BaseShape.SculptTexture, delegate(AssetBase asset)
                    {
                        // physicsScene.DetailLog("{0},BSShape.VerifyMeshCreated,assetProviderCallback", xprim.LocalID);
                        bool assetFound = false;
                        string mismatchIDs = String.Empty;  // DEBUG DEBUG
                        if (asset != null && yprim.BaseShape.SculptEntry)
                        {
                            if (yprim.BaseShape.SculptTexture.ToString() == asset.ID)
                            {
                                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 normal shape setting since the rebuild is at taint time.
                                yprim.PrimAssetState = BSPhysObject.PrimAssetCondition.Fetched;
                                yprim.ForceBodyShapeRebuild(false /* inTaintTime */);
                                assetFound = true;
                            }
                            else
                            {
                                mismatchIDs = yprim.BaseShape.SculptTexture.ToString() + "/" + asset.ID;
                            }
                        }
                        if (!assetFound)
                        {
                            yprim.PrimAssetState = BSPhysObject.PrimAssetCondition.FailedAssetFetch;
                        }
                        physicsScene.DetailLog("{0},BSShape.VerifyMeshCreated,fetchAssetCallback,found={1},isSculpt={2},ids={3}",
                                    yprim.LocalID, assetFound, yprim.BaseShape.SculptEntry, mismatchIDs );
                    });
                }
                else
                {
                    xprim.PrimAssetState = BSPhysObject.PrimAssetCondition.FailedAssetFetch;
                    physicsScene.Logger.ErrorFormat("{0} Physical object requires asset but no asset provider. Name={1}",
                                                LogHeader, physicsScene.PhysicsSceneName);
                }
            }
            else
            {
                if (prim.PrimAssetState == BSPhysObject.PrimAssetCondition.FailedAssetFetch)
                {
                    physicsScene.Logger.WarnFormat("{0} Mesh failed to fetch asset. prim={1}, texture={2}",
                                                LogHeader, UsefulPrimInfo(physicsScene, prim), prim.BaseShape.SculptTexture);
                    physicsScene.DetailLog("{0},BSShape.VerifyMeshCreated,wasFailed,prim={1},tex={2}",
                                                prim.LocalID, UsefulPrimInfo(physicsScene, prim), prim.BaseShape.SculptTexture);
                }
                if (prim.PrimAssetState == BSPhysObject.PrimAssetCondition.FailedMeshing)
                {
                    physicsScene.Logger.WarnFormat("{0} Mesh asset would not mesh. prim={1}, texture={2}",
                                                LogHeader, UsefulPrimInfo(physicsScene, prim), prim.BaseShape.SculptTexture);
                    physicsScene.DetailLog("{0},BSShape.VerifyMeshCreated,wasFailedMeshing,prim={1},tex={2}",
                                                prim.LocalID, UsefulPrimInfo(physicsScene, prim), prim.BaseShape.SculptTexture);
                }
            }
         }

        // While we wait for the mesh defining asset to be loaded, stick in a simple box for the object.
        BSShape fillShape = BSShapeNative.GetReference(physicsScene, prim, BSPhysicsShapeType.SHAPE_BOX, FixedShapeKey.KEY_BOX);
        physicsScene.DetailLog("{0},BSShape.VerifyMeshCreated,boxTempShape", prim.LocalID);

        return fillShape.physShapeInfo;
     }