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);
 }
Example #2
0
 BulletShape CreatePhysicalMesh(BSScene physicsScene, BSPhysObject prim, 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);
         });
 }
Example #3
0
        public 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;
        }
Example #4
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));
 }
Example #5
0
 public static string UsefulPrimInfo(BSScene pScene, BSPhysObject prim)
 {
     StringBuilder buff = new StringBuilder(prim.PhysObjectName);
     buff.Append("/pos=");
     buff.Append(prim.RawPosition);
     if (pScene != null)
     {
         buff.Append("/rgn=");
         buff.Append(pScene.PhysicsSceneName);
     }
     return buff.ToString();
 }
Example #6
0
 // Get another reference to this shape.
 public abstract BSShape GetReference(BSScene pPhysicsScene, BSPhysObject pPrim);
Example #7
0
        public static BSShape GetReference(BSScene physicsScene, bool forceRebuild, BSPhysObject prim)
        {
            float lod;
            UInt64 newMeshKey = 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;

            lock (GImpacts)
            {
                if (GImpacts.TryGetValue(newMeshKey, out retGImpact))
                {
                    // Teh 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;
        }
 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;
 }
 public bool GetBodyAndShape(bool forceRebuild, BulletWorld sim, BSPhysObject prim)
 {
     return(GetBodyAndShape(forceRebuild, sim, prim, null));
 }
        // The simulation step is telling this object about a collision.
        // 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(uint collidingWith, BSPhysObject collidee,
            OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth)
        {
            bool ret = false;
            bool p2col = true;

            // We only need to test p2 for 'jump crouch purposes'
            if (TypeName == "BSCharacter" && collidee is BSPrim)
            {
                // Testing if the collision is at the feet of the avatar
                if ((Position.Z - contactPoint.Z) < (Size.Z * 0.5f))
                    p2col = false;
            }

            // The following lines make IsColliding(), CollidingGround() and CollidingObj work
            if (p2col)
                CollidingStep = PhysicsScene.SimulationStep;
            TrueCollidingStep = PhysicsScene.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;

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

                ret = true;
            }
            return ret;
        }
 public BSActorLockAxis (BSScene physicsScene, BSPhysObject pObj, string actorName)
     : base (physicsScene, pObj, actorName)
 {
     m_physicsScene.DetailLog ("{0},BSActorLockAxis,constructor", m_controllingPrim.LocalID);
     LockAxisConstraint = null;
 }
Example #12
0
 public BSActorSetTorque(BSScene physicsScene, BSPhysObject pObj, string actorName)
     : base(physicsScene, pObj, actorName)
 {
     m_torqueMotor = null;
     m_physicsScene.DetailLog("{0},BSActorSetTorque,constructor", m_controllingPrim.LocalID);
 }
 public BSActorLockAxis(BSScene physicsScene, BSPhysObject pObj, string actorName)
     : base(physicsScene, pObj, actorName)
 {
     m_physicsScene.DetailLog("{0},BSActorLockAxis,constructor", m_controllingPrim.LocalID);
     LockAxisConstraint = null;
 }
Example #14
0
 public BSActorMoveToTarget(BSScene physicsScene, BSPhysObject pObj, string actorName)
     : base(physicsScene, pObj, actorName)
 {
     m_targetMotor = null;
     m_physicsScene.DetailLog("{0},BSActorMoveToTarget,constructor", m_controllingPrim.LocalID);
 }
Example #15
0
        public static BSShape GetReference(BSScene physicsScene, bool forceRebuild, BSPhysObject prim)
        {
            float lod;
            UInt64 newHullKey = BSShape.ComputeShapeKey(prim.Size, prim.BaseShape, out lod);

            BSShapeHull retHull;
            bool foundHull = false;
            lock (Hulls)
                foundHull = Hulls.TryGetValue (newHullKey, out retHull);

            if (foundHull)
            {
                // 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.
                    lock(Hulls)
                        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;
        }
        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.
            // TODO: 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(PhysicsScene, prim, BSPhysicsShapeType.SHAPE_CAPSULE,
                                                                FixedShapeKey.KEY_CAPSULE);
                    ret       = true;
                    haveShape = true;
                    break;

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

                case AvatarShapeOvoid:
                    // Saddly, Bullet doesn't scale spheres so this doen't work as an avatar shape
                    prim.PhysShape = BSShapeNative.GetReference(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 = 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 doen'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(PhysicsScene, prim, BSPhysicsShapeType.SHAPE_SPHERE,
                                                                    FixedShapeKey.KEY_SPHERE);
                        ret = true;
                    }
                    if (DDetail)
                    {
                        DetailLog("{0},BSShapeCollection.CreateGeom,sphere,force={1},rebuild={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(PhysicsScene, prim, BSPhysicsShapeType.SHAPE_BOX,
                                                                    FixedShapeKey.KEY_BOX);
                        ret = true;
                    }
                    if (DDetail)
                    {
                        DetailLog("{0},BSShapeCollection.CreateGeom,box,force={1},rebuild={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);
        }
Example #17
0
        BulletShape CreatePhysicalHull(BSScene physicsScene, BSPhysObject prim, UInt64 newHullKey,
            PrimitiveBaseShape pbs, OMV.Vector3 size, float lod)
        {
            BulletShape newShape = new BulletShape();
            IMesh meshData;
            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 */);

                // 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 structure
                //      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);
                var 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();

                //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]);
                }

// greythane - use the integer array instead of OS type vertex list
//                List<OMV.Vector3> vertices = meshData.getVertexList();
//                foreach (OMV.Vector3 vv in vertices)
//                {
//                    convVertices.Add(new float3(vv.X, vv.Y, vv.Z));
//                }
                var vertices = meshData.getVertexListAsFloat();
                var vertexCount = vertices.Length / 3;
                for (int i = 0; i < vertexCount; i++)
                {
                    convVertices.Add(new float3(vertices[3 * i + 0], vertices[3 * i + 1], vertices[3 * i + 2]));
                }

                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.Length, 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;
        }
        // return 'true' if the prim's shape was changed.
        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(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(PhysicsScene, false /* forceRebuild */, prim);
                }

                // If not any of the simple cases, just make a hull
                if (potentialHull == null)
                {
                    potentialHull = BSShapeHull.GetReference(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(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(PhysicsScene, false /* forceRebuld */, 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(PhysicsScene);
                }
                if (DDetail)
                {
                    DetailLog("{0},BSShapeCollection.CreateGeom,mesh,shape={1}", prim.LocalID, prim.PhysShape);
                }
            }
            return(ret);
        }
Example #19
0
 public override BSShape GetReference(BSScene physicsScene, BSPhysObject prim)
 {
     // Calling this reference means we want another handle to an existing shape
     //      (usually linksets) so return this copy.
     IncrementReference();
     return this;
 }
        // Called to update/change the body and shape for an object.
        // First checks the shape and updates that if necessary then makes
        //    sure the body is of the right type.
        // Return 'true' if either the body or the shape changed.
        // 'shapeCallback' and 'bodyCallback' are, if non-null, functions called just before
        //    the current shape or body is destroyed. This allows the caller to remove any
        //    higher level dependencies on the shape or body. Mostly used for LinkSets to
        //    remove the physical constraints before the body is destroyed.
        // Called at taint-time!!
        public bool GetBodyAndShape(bool forceRebuild, BulletWorld sim, BSPhysObject prim, PhysicalDestructionCallback bodyCallback)
        {
            PhysicsScene.AssertInTaintTime("BSShapeCollection.GetBodyAndShape");

            bool ret;

            // 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, 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;
        }
Example #21
0
 public static BSShape GetReference(BSPhysObject prim)
 {
     return new BSShapeNull();
 }
 public bool GetBodyAndShape(bool forceRebuild, BulletWorld sim, BSPhysObject prim)
 {
     return GetBodyAndShape(forceRebuild, sim, prim, null);
 }
Example #23
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.PrimAssetState != BSPhysObject.PrimAssetCondition.FailedAssetFetch
                    && prim.PrimAssetState != BSPhysObject.PrimAssetCondition.Waiting
                    && prim.BaseShape.SculptTexture != OMV.UUID.Zero
                )
                {
                    physicsScene.DetailLog("{0},BSShapeCollection.VerifyMeshCreated,fetchAsset", prim.LocalID);
                    // Multiple requestors will know we're waiting for this asset
                    prim.PrimAssetState = BSPhysObject.PrimAssetCondition.Waiting;

                    BSPhysObject xprim = prim;
                    Util.FireAndForget(delegate
                        {
                            BSPhysObject yprim = xprim; // probably not necessary, but, just in case.
                            physicsScene.Scene.AssetService.Get(yprim.BaseShape.SculptTexture.ToString(), null,
                                delegate(string id, Object sender, AssetBase asset)
                                {
                                    bool assetFound = false;
                                    string mismatchIDs = String.Empty; // DEBUG DEBUG
                                    if (asset != null && yprim.BaseShape.SculptEntry)
                                    {
                                        if (yprim.BaseShape.SculptTexture == 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.ForceBodyShapeRebuild(false /* inTaintTime */);
                                            assetFound = true;
                                        }
                                        else
                                        {
                                            mismatchIDs = yprim.BaseShape.SculptTexture + "/" + asset.ID;
                                        }
                                    }
                                    if (assetFound)
                                        yprim.PrimAssetState = BSPhysObject.PrimAssetCondition.Fetched;
                                    else
                                        yprim.PrimAssetState = BSPhysObject.PrimAssetCondition.FailedAssetFetch;
                                    physicsScene.DetailLog("{0},BSShapeCollection,fetchAssetCallback,found={1},isSculpt={2},ids={3}",
                                        yprim.LocalID, assetFound, yprim.BaseShape.SculptEntry, mismatchIDs);
                                });
                        });
                }
                else
                {
                    if (prim.PrimAssetState == BSPhysObject.PrimAssetCondition.FailedAssetFetch)
                    {
                        physicsScene.Logger.WarnFormat("{0} Mesh failed to fetch asset. obj={1}, texture={2}",
                            LogHeader, prim.PhysObjectName, 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;
        }
 // If the existing prim's shape is to be replaced, remove the tie to the existing shape
 //     before replacing it.
 void DereferenceExistingShape(BSPhysObject prim, PhysicalDestructionCallback shapeCallback)
 {
     if (prim.PhysShape.HasPhysicalShape)
     {
         if (shapeCallback != null)
             shapeCallback(prim.PhysBody, prim.PhysShape.physShapeInfo);
         prim.PhysShape.Dereference(PhysicsScene);
     }
     prim.PhysShape = new BSShapeNull();
 }
Example #25
0
 public override BSShape GetReference(BSScene pPhysicsScene, BSPhysObject pPrim) 
 {
     return new BSShapeNull(); 
 }
        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.
            // TODO: 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(PhysicsScene, prim, BSPhysicsShapeType.SHAPE_CAPSULE,
                            FixedShapeKey.KEY_CAPSULE);
                        ret = true;
                        haveShape = true;
                        break;
                    case AvatarShapeCube:
                        prim.PhysShape = BSShapeNative.GetReference(PhysicsScene, prim, BSPhysicsShapeType.SHAPE_BOX,
                            FixedShapeKey.KEY_CAPSULE);
                        ret = true;
                        haveShape = true;
                        break;
                    case AvatarShapeOvoid:
                        // Saddly, Bullet doesn't scale spheres so this doen't work as an avatar shape
                        prim.PhysShape = BSShapeNative.GetReference(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 = 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 doen'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(PhysicsScene, prim, BSPhysicsShapeType.SHAPE_SPHERE,
                            FixedShapeKey.KEY_SPHERE);
                        ret = true;
                    }
                    if (DDetail)
                        DetailLog("{0},BSShapeCollection.CreateGeom,sphere,force={1},rebuild={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(PhysicsScene, prim, BSPhysicsShapeType.SHAPE_BOX,
                            FixedShapeKey.KEY_BOX);
                        ret = true;
                    }
                    if (DDetail)
                        DetailLog("{0},BSShapeCollection.CreateGeom,box,force={1},rebuild={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;
        }
Example #27
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;
 }
        // return 'true' if the prim's shape was changed.
        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(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(PhysicsScene, false /* forceRebuild */, prim);
                }

                // If not any of the simple cases, just make a hull
                if (potentialHull == null)
                {
                    potentialHull = BSShapeHull.GetReference(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(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(PhysicsScene, false /* forceRebuld */, 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(PhysicsScene);
                }
                if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,mesh,shape={1}", prim.LocalID, prim.PhysShape);
            }
            return ret;
        }
Example #29
0
        public static BSShape GetReference(BSScene physicsScene, bool forceRebuild, BSPhysObject prim)
        {
            float lod;
            UInt64 newMeshKey = BSShape.ComputeShapeKey(prim.Size, prim.BaseShape, out lod);

            BSShapeMesh retMesh;
            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;
        }
        // Create a body object in Bullet,
        // Update 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.
        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) 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 = 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 = 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;
        }
Example #31
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, UInt64 newMeshKey,
            PrimitiveBaseShape pbs, OMV.Vector3 size, float lod, CreateShapeCall makeShape)
        {
            BulletShape newShape = new BulletShape();

            IMesh meshData;
            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
                    );
            }

            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;
        }
Example #32
0
        // TODO!!! public virtual bool ShouldReportPropertyUpdates
        
        // Called after a simulation step to post a collision with this object.
        // Return 'true' if linkset processed the collision. 'false' says the linkset didn't have
        //     anything to add for the collision and it should be passed through normal processing.
        // Default processing for a linkset.
        public virtual bool HandleCollide(uint collidingWith, BSPhysObject collidee,
                                    OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth)
        {
            bool ret = false;

            // prims in the same linkset cannot collide with each other
            BSPrimLinkable convCollidee = collidee as BSPrimLinkable;
            if (convCollidee != null && (LinksetID == convCollidee.Linkset.LinksetID))
            {
                // By returning 'true', we tell the caller the collision has been 'handled' so it won't
                //     do anything about this collision and thus, effectivily, ignoring the collision.
                ret = true;
            }
            else
            {
                // Not a collision between members of the linkset. Must be a real collision.
                // So the linkset root can know if there is a collision anywhere in the linkset.
                LinksetRoot.SomeCollisionSimulationStep = PhysicsScene.SimulationStep;
            }

            return ret;
        }
Example #33
0
 public override BSShape GetReference(BSScene pPhysicsScene, BSPhysObject pPrim)
 {
     BSShape ret;
     // 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;
 }
Example #34
0
        public static BSShape GetReference(BSScene physicsScene, bool forceRebuild, BSPhysObject prim)
        {
            float lod;
            UInt64 newMeshKey = 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;

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

                // Get a handle to a mesh to buld 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;
                    lock (ConvexHulls)
                        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;
        }
 public BSActorSetTorque(BSScene physicsScene, BSPhysObject pObj, string actorName)
     : base(physicsScene, pObj, actorName)
 {
     m_torqueMotor = null;
     m_physicsScene.DetailLog("{0},BSActorSetTorque,constructor", m_controllingPrim.LocalID);
 }
 public BSActorMoveToTarget(BSScene physicsScene, BSPhysObject pObj, string actorName)
     : base(physicsScene, pObj, actorName)
 {
     m_targetMotor = null;
     m_physicsScene.DetailLog("{0},BSActorMoveToTarget,constructor", m_controllingPrim.LocalID);
 }