Пример #1
0
 public bool SetAxisEnable(int pIndex, bool pAxisEnable)
 {
     PhysicsScene.DetailLog("{0},BSConstraintSpring.SetEnable,obj1ID={1},obj2ID={2},indx={3},enable={4}",
                            m_body1.ID, m_body1.ID, m_body2.ID, pIndex, pAxisEnable);
     PhysicsScene.PE.SpringEnable(m_constraint, pIndex, BSParam.NumericBool(pAxisEnable));
     return(true);
 }
Пример #2
0
        // Set parameter on a specific or all instances.
        // Return 'false' if not able to set the parameter.
        // Setting the value in the m_params block will change the value the physics engine
        //   will use the next time since it's pinned and shared memory.
        // Some of the values require calling into the physics engine to get the new
        //   value activated ('terrainFriction' for instance).
        public bool SetPhysicsParameter(string parm, float val, uint localID)
        {
            bool ret = false;

            BSParam.ParameterDefn theParam;
            if (BSParam.TryGetParameter(parm, out theParam))
            {
                theParam.setter(this, parm, localID, val);
                ret = true;
            }
            return(ret);
        }
Пример #3
0
        // All default parameter values are set here. There should be no values set in the
        // variable definitions.
        private void GetInitialParameterValues(IConfigSource config)
        {
            ConfigurationParameters parms = new ConfigurationParameters();

            UnmanagedParams[0] = parms;

            BSParam.SetParameterDefaultValues(this);

            if (config != null)
            {
                // If there are specifications in the ini file, use those values
                IConfig pConfig = config.Configs["BulletSim"];
                if (pConfig != null)
                {
                    BSParam.SetParameterConfigurationValues(this, pConfig);

                    // There are two Bullet implementations to choose from
                    BulletEngineName = pConfig.GetString("BulletEngine", "BulletUnmanaged");

                    // Very detailed logging for physics debugging
                    // TODO: the boolean values can be moved to the normal parameter processing.
                    m_physicsLoggingEnabled      = pConfig.GetBoolean("PhysicsLoggingEnabled", false);
                    m_physicsLoggingDir          = pConfig.GetString("PhysicsLoggingDir", ".");
                    m_physicsLoggingPrefix       = pConfig.GetString("PhysicsLoggingPrefix", "physics-%REGIONNAME%-");
                    m_physicsLoggingFileMinutes  = pConfig.GetInt("PhysicsLoggingFileMinutes", 5);
                    m_physicsLoggingDoFlush      = pConfig.GetBoolean("PhysicsLoggingDoFlush", false);
                    m_physicsPhysicalDumpEnabled = pConfig.GetBoolean("PhysicsPhysicalDumpEnabled", false);
                    // Very detailed logging for vehicle debugging
                    VehicleLoggingEnabled         = pConfig.GetBoolean("VehicleLoggingEnabled", false);
                    VehiclePhysicalLoggingEnabled = pConfig.GetBoolean("VehiclePhysicalLoggingEnabled", false);

                    // Do any replacements in the parameters
                    m_physicsLoggingPrefix = m_physicsLoggingPrefix.Replace("%REGIONNAME%", RegionName);
                }
                else
                {
                    // Nothing in the configuration INI file so assume unmanaged and other defaults.
                    BulletEngineName        = "BulletUnmanaged";
                    m_physicsLoggingEnabled = false;
                    VehicleLoggingEnabled   = false;
                }

                // The material characteristics.
                BSMaterials.InitializeFromDefaults(Params);
                if (pConfig != null)
                {
                    // Let the user add new and interesting material property values.
                    BSMaterials.InitializefromParameters(pConfig);
                }
            }
        }
Пример #4
0
        // Get parameter.
        // Return 'false' if not able to get the parameter.
        public bool GetPhysicsParameter(string parm, out string value)
        {
            string val = String.Empty;
            bool   ret = false;

            BSParam.ParameterDefnBase theParam;
            if (BSParam.TryGetParameter(parm, out theParam))
            {
                val = theParam.GetValue(this);
                ret = true;
            }
            value = val;
            return(ret);
        }
Пример #5
0
        // Get parameter.
        // Return 'false' if not able to get the parameter.
        public bool GetPhysicsParameter(string parm, out float value)
        {
            float val = 0f;
            bool  ret = false;

            BSParam.ParameterDefn theParam;
            if (BSParam.TryGetParameter(parm, out theParam))
            {
                val = theParam.getter(this);
                ret = true;
            }
            value = val;
            return(ret);
        }
Пример #6
0
        // Set parameter on a specific or all instances.
        // Return 'false' if not able to set the parameter.
        // Setting the value in the m_params block will change the value the physics engine
        //   will use the next time since it's pinned and shared memory.
        // Some of the values require calling into the physics engine to get the new
        //   value activated ('terrainFriction' for instance).
        public bool SetPhysicsParameter(string parm, string val, uint localID)
        {
            bool ret = false;

            BSParam.ParameterDefnBase theParam;
            if (BSParam.TryGetParameter(parm, out theParam))
            {
                // Set the value in the C# code
                theParam.SetValue(this, val);

                // Optionally set the parameter in the unmanaged code
                if (theParam.HasSetOnObject)
                {
                    // update all the localIDs specified
                    // If the local ID is APPLY_TO_NONE, just change the default value
                    // If the localID is APPLY_TO_ALL change the default value and apply the new value to all the lIDs
                    // If the localID is a specific object, apply the parameter change to only that object
                    List <uint> objectIDs = new List <uint>();
                    switch (localID)
                    {
                    case PhysParameterEntry.APPLY_TO_NONE:
                        // This will cause a call into the physical world if some operation is specified (SetOnObject).
                        objectIDs.Add(TERRAIN_ID);
                        TaintedUpdateParameter(parm, objectIDs, val);
                        break;

                    case PhysParameterEntry.APPLY_TO_ALL:
                        lock (PhysObjects) objectIDs = new List <uint>(PhysObjects.Keys);
                        TaintedUpdateParameter(parm, objectIDs, val);
                        break;

                    default:
                        // setting only one localID
                        objectIDs.Add(localID);
                        TaintedUpdateParameter(parm, objectIDs, val);
                        break;
                    }
                }

                ret = true;
            }
            return(ret);
        }
Пример #7
0
        // Reset this constraint making sure it has all its internal structures
        //    recomputed and is enabled and ready to go.
        public virtual bool RecomputeConstraintVariables(float mass)
        {
            bool ret = false;

            if (m_enabled)
            {
                ret = CalculateTransforms();
                if (ret)
                {
                    // Setting an object's mass to zero (making it static like when it's selected)
                    //     automatically disables the constraints.
                    // If the link is enabled, be sure to set the constraint itself to enabled.
                    BulletSimAPI.SetConstraintEnable2(m_constraint.ptr, BSParam.NumericBool(true));
                }
                else
                {
                    m_world.physicsScene.Logger.ErrorFormat("{0} CalculateTransforms failed. A={1}, B={2}", LogHeader, Body1.ID, Body2.ID);
                }
            }
            return(ret);
        }
Пример #8
0
        // schedule the actual updating of the paramter to when the phys engine is not busy
        private void TaintedUpdateParameter(string parm, List <uint> lIDs, float val)
        {
            float       xval  = val;
            List <uint> xlIDs = lIDs;
            string      xparm = parm;

            TaintedObject("BSScene.UpdateParameterSet", delegate() {
                BSParam.ParameterDefn thisParam;
                if (BSParam.TryGetParameter(xparm, out thisParam))
                {
                    if (thisParam.onObject != null)
                    {
                        foreach (uint lID in xlIDs)
                        {
                            BSPhysObject theObject = null;
                            PhysObjects.TryGetValue(lID, out theObject);
                            thisParam.onObject(this, theObject, xval);
                        }
                    }
                }
            });
        }
Пример #9
0
        // All default parameter values are set here. There should be no values set in the
        // variable definitions.
        private void GetInitialParameterValues(IConfigSource config)
        {
            ConfigurationParameters parms = new ConfigurationParameters();

            UnmanagedParams[0] = parms;

            BSParam.SetParameterDefaultValues(this);

            if (config != null)
            {
                // If there are specifications in the ini file, use those values
                IConfig pConfig = config.Configs["BulletSim"];
                if (pConfig != null)
                {
                    BSParam.SetParameterConfigurationValues(this, pConfig);

                    // Very detailed logging for physics debugging
                    m_physicsLoggingEnabled     = pConfig.GetBoolean("PhysicsLoggingEnabled", false);
                    m_physicsLoggingDir         = pConfig.GetString("PhysicsLoggingDir", ".");
                    m_physicsLoggingPrefix      = pConfig.GetString("PhysicsLoggingPrefix", "physics-%REGIONNAME%-");
                    m_physicsLoggingFileMinutes = pConfig.GetInt("PhysicsLoggingFileMinutes", 5);
                    m_physicsLoggingDoFlush     = pConfig.GetBoolean("PhysicsLoggingDoFlush", false);
                    // Very detailed logging for vehicle debugging
                    VehicleLoggingEnabled         = pConfig.GetBoolean("VehicleLoggingEnabled", false);
                    VehiclePhysicalLoggingEnabled = pConfig.GetBoolean("VehiclePhysicalLoggingEnabled", false);

                    // Do any replacements in the parameters
                    m_physicsLoggingPrefix = m_physicsLoggingPrefix.Replace("%REGIONNAME%", RegionName);
                }

                // The material characteristics.
                BSMaterials.InitializeFromDefaults(Params);
                if (pConfig != null)
                {
                    // Let the user add new and interesting material property values.
                    BSMaterials.InitializefromParameters(pConfig);
                }
            }
        }
Пример #10
0
        // schedule the actual updating of the paramter to when the phys engine is not busy
        private void TaintedUpdateParameter(string parm, List <uint> lIDs, string val)
        {
            string      xval  = val;
            List <uint> xlIDs = lIDs;
            string      xparm = parm;

            TaintedObject("BSScene.UpdateParameterSet", delegate() {
                BSParam.ParameterDefnBase thisParam;
                if (BSParam.TryGetParameter(xparm, out thisParam))
                {
                    if (thisParam.HasSetOnObject)
                    {
                        foreach (uint lID in xlIDs)
                        {
                            BSPhysObject theObject = null;
                            if (PhysObjects.TryGetValue(lID, out theObject))
                            {
                                thisParam.SetOnObject(this, theObject);
                            }
                        }
                    }
                }
            });
        }
Пример #11
0
        private BSConstraint BuildConstraint(BSPhysObject rootPrim, BSPhysObject childPrim)
        {
            // Zero motion for children so they don't interpolate
            childPrim.ZeroMotion(true);

            // Relative position normalized to the root prim
            // Essentually a vector pointing from center of rootPrim to center of childPrim
            OMV.Vector3 childRelativePosition = childPrim.Position - rootPrim.Position;

            // real world coordinate of midpoint between the two objects
            OMV.Vector3 midPoint = rootPrim.Position + (childRelativePosition / 2);

            DetailLog("{0},BSLinksetConstraint.BuildConstraint,taint,root={1},rBody={2},child={3},cBody={4},rLoc={5},cLoc={6},midLoc={7}",
                      rootPrim.LocalID,
                      rootPrim.LocalID, rootPrim.PhysBody.AddrString,
                      childPrim.LocalID, childPrim.PhysBody.AddrString,
                      rootPrim.Position, childPrim.Position, midPoint);

            // create a constraint that allows no freedom of movement between the two objects
            // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818

            BSConstraint6Dof constrain = new BSConstraint6Dof(
                PhysicsScene.World, rootPrim.PhysBody, childPrim.PhysBody, midPoint, true, true);

            // PhysicsScene.World, childPrim.BSBody, rootPrim.BSBody, midPoint, true, true );

            /* NOTE: below is an attempt to build constraint with full frame computation, etc.
             *     Using the midpoint is easier since it lets the Bullet code manipulate the transforms
             *     of the objects.
             * Code left for future programmers.
             * // ==================================================================================
             * // relative position normalized to the root prim
             * OMV.Quaternion invThisOrientation = OMV.Quaternion.Inverse(rootPrim.Orientation);
             * OMV.Vector3 childRelativePosition = (childPrim.Position - rootPrim.Position) * invThisOrientation;
             *
             * // relative rotation of the child to the parent
             * OMV.Quaternion childRelativeRotation = invThisOrientation * childPrim.Orientation;
             * OMV.Quaternion inverseChildRelativeRotation = OMV.Quaternion.Inverse(childRelativeRotation);
             *
             * DetailLog("{0},BSLinksetConstraint.PhysicallyLinkAChildToRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID);
             * BS6DofConstraint constrain = new BS6DofConstraint(
             *              PhysicsScene.World, rootPrim.Body, childPrim.Body,
             *              OMV.Vector3.Zero,
             *              OMV.Quaternion.Inverse(rootPrim.Orientation),
             *              OMV.Vector3.Zero,
             *              OMV.Quaternion.Inverse(childPrim.Orientation),
             *              true,
             *              true
             *              );
             * // ==================================================================================
             */

            PhysicsScene.Constraints.AddConstraint(constrain);

            // zero linear and angular limits makes the objects unable to move in relation to each other
            constrain.SetLinearLimits(OMV.Vector3.Zero, OMV.Vector3.Zero);
            constrain.SetAngularLimits(OMV.Vector3.Zero, OMV.Vector3.Zero);

            // tweek the constraint to increase stability
            constrain.UseFrameOffset(BSParam.BoolNumeric(BSParam.LinkConstraintUseFrameOffset));
            constrain.TranslationalLimitMotor(BSParam.BoolNumeric(BSParam.LinkConstraintEnableTransMotor),
                                              BSParam.LinkConstraintTransMotorMaxVel,
                                              BSParam.LinkConstraintTransMotorMaxForce);
            constrain.SetCFMAndERP(BSParam.LinkConstraintCFM, BSParam.LinkConstraintERP);
            if (BSParam.LinkConstraintSolverIterations != 0f)
            {
                constrain.SetSolverIterations(BSParam.LinkConstraintSolverIterations);
            }
            return(constrain);
        }
Пример #12
0
 // Get the list of parameters this physics engine supports
 public PhysParameterEntry[] GetParameterList()
 {
     BSParam.BuildParameterTable();
     return(BSParam.SettableParameters);
 }
Пример #13
0
    private BulletShape CreatePhysicalHull(BSScene physicsScene, BSPhysObject prim, System.UInt64 newHullKey,
                                           PrimitiveBaseShape pbs, OMV.Vector3 size, float lod)
    {
        BulletShape newShape = new BulletShape();
        IntPtr      hullPtr  = IntPtr.Zero;

        if (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,shouldUseBulletHACD,entry", prim.LocalID);
            BSShape meshShape = BSShapeMesh.GetReference(physicsScene, true, prim);

            if (meshShape.physShapeInfo.HasPhysicalShape)
            {
                HACDParams parms;
                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);

                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,hasBody={1}", prim.LocalID, newShape.HasPhysicalShape);

                // Now done with the mesh shape.
                meshShape.Dereference(physicsScene);
            }
            physicsScene.DetailLog("{0},BSShapeHull.CreatePhysicalHull,shouldUseBulletHACD,exit,hasBody={1}", prim.LocalID, newShape.HasPhysicalShape);
        }
        if (!newShape.HasPhysicalShape)
        {
            // Build a new hull in the physical world using the C# HACD algorigthm.
            // Pass true for physicalness as this prevents the creation of bounding box which is not needed
            IMesh meshData = physicsScene.mesher.CreateMesh(prim.PhysObjectName, pbs, size, lod, true /* isPhysical */, false /* shouldCache */);
            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();
                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);
    }