/// <summary>
 /// This overrides the result for a single pair of materials. It's
 /// recommended that you add all materials first. Order of ids
 /// doesn't matter
 /// </summary>
 /// <param name="id1"></param>
 /// <param name="id2"></param>
 /// <param name="pairProperties"></param>
 public void SetMaterialPairProperties(int id1, int id2, MaterialPairProperties pairProperties)
 {
     int key01 = id1 << 16 | id2;
     int key10 = id2 << 16 | id1;
     materialPairs[key01] = materialPairs[key10] = pairProperties;
 }
        /// <summary>
        /// This adds/overrides a material, and sets all the pairs for
        /// existing materials using some sensible heuristic
        /// </summary>
        /// <param name="id"></param>
        /// <param name="properties"></param>
        public void SetMaterialProperties(int id, MaterialProperties properties)
        {
            materials[id] = properties;

            foreach (KeyValuePair<int, MaterialProperties> it in materials)
            {
                int otherID = it.Key;
                MaterialProperties mat = it.Value;

                int key01 = otherID << 16 | id;
                int key10 = id << 16 | otherID;
                materialPairs[key01] = materialPairs[key10] =
                    new MaterialPairProperties(properties.Elasticity * mat.Elasticity,
                        properties.StaticRoughness * mat.StaticRoughness,
                        properties.DynamicRoughness * mat.DynamicRoughness);
            }
        }
        private unsafe void Init(CollDetectInfo info, Vector3 dirToBody0, SmallCollPointInfo* pointInfos, int numPointInfos)
        {
            this.SkinInfo = info;
            this.dirToBody0 = dirToBody0;

            int ID0 = info.Skin0.GetMaterialID(info.IndexPrim0);
            int ID1 = info.Skin1.GetMaterialID(info.IndexPrim1);

            MaterialTable matTable = info.Skin0.CollisionSystem.MaterialTable;

            if (ID0 == (int)MaterialTable.MaterialID.UserDefined || (int)ID1 == (int)MaterialTable.MaterialID.UserDefined)
            {
                MaterialProperties prop0, prop1;

                if (ID0 == (int)MaterialTable.MaterialID.UserDefined)
                    prop0 = info.Skin0.GetMaterialProperties(info.IndexPrim0);
                else
                    prop0 = matTable.GetMaterialProperties(ID0);

                if (ID1 == (int)MaterialTable.MaterialID.UserDefined)
                    prop1 = info.Skin1.GetMaterialProperties(info.IndexPrim1);
                else
                    prop1 = matTable.GetMaterialProperties(ID1);

                MatPairProperties.Restitution = prop0.Elasticity * prop1.Elasticity;
                MatPairProperties.StaticFriction = prop0.StaticRoughness * prop1.StaticRoughness;
                MatPairProperties.DynamicFriction = prop0.DynamicRoughness * prop1.DynamicRoughness;
            }
            else
            {
                MatPairProperties = matTable.GetPairProperties(ID0, ID1);
            }

            numPointInfos = (numPointInfos > MaxCollisionPoints) ? MaxCollisionPoints : numPointInfos;

            NumCollPts = 0;
            for (int i = 0; i < numPointInfos; ++i)
            {
                if (freePtInfos.Count == 0)
                {
                    freePtInfos.Push(new CollPointInfo());
                }
                this.PointInfo[NumCollPts] = freePtInfos.Pop();
                this.PointInfo[NumCollPts++].Init( ref pointInfos[i] );
            }
        }