public override void ClientMoveAndDisplay(GameTime gameTime)
        {
            // OPTIONAL: We simply move our ghost objects around (without rotating them.....)==============
            if (m_ghostObject != null || m_pairCachingGhostObject != null)
            {
                rad += 0.005f;    // Bad (depends on PC speed)
                float sinRad = (float)Math.Sin(rad);
                float cosRad = (float)Math.Cos(rad);
                if (m_ghostObject != null)
                {
                    IndexedMatrix im = IndexedMatrix.CreateFromQuaternion(quatDeg45Y);
                    im._origin = new IndexedVector3(15 * cosRad, 5, -15 * sinRad);
                    m_ghostObject.SetWorldTransform(ref im);
                }
                if (m_pairCachingGhostObject != null)
                {
                    IndexedMatrix im = IndexedMatrix.CreateFromQuaternion(quatDeg45Y);
                    im._origin = new IndexedVector3(-15 * cosRad, 7, 15 * sinRad);
                    m_pairCachingGhostObject.SetWorldTransform(ref im);
                }
            }



            base.ClientMoveAndDisplay(gameTime);
            // NEW => Retrives the content from all ghost objects in the world and call ProcessObectsInsideGhostObjects(...) for each ====
            if (m_dynamicsWorld != null)
            {
                ObjectArray <CollisionObject> objsInsidePairCachingGhostObject = new ObjectArray <CollisionObject>(); // We might want this to be a member variable...
                ObjectArray <CollisionObject> pObjsInsideGhostObject           = null;                                // We will store a reference of the current array in this pointer
                ObjectArray <CollisionObject> objs = m_dynamicsWorld.GetCollisionObjectArray();
                for (int i = 0, sz = objs.Count; i < sz; i++)
                {
                    CollisionObject o  = objs[i];
                    GhostObject     go = GhostObject.Upcast(o);
                    if (go != null)
                    {
                        objsInsidePairCachingGhostObject.Resize(0);
                        PairCachingGhostObject pgo = go as PairCachingGhostObject;                      // No upcast functionality...
                        if (pgo != null)
                        {
                            GetCollidingObjectsInsidePairCachingGhostObject((DiscreteDynamicsWorld)m_dynamicsWorld, pgo, objsInsidePairCachingGhostObject);
                            pObjsInsideGhostObject = objsInsidePairCachingGhostObject;
                        }
                        else
                        {
                            pObjsInsideGhostObject = go.GetOverlappingPairs();                          // It's better not to try and copy the whole array, but to keep a reference to it!
                            // Side Note: btAlignedObjectArray < btCollisionObject* > objs = go.getOverlappingPairs(); (at the moment) makes my program crash on my system...
                            // Nevermind, that was the wrong way of doing it: btAlignedObjectArray < btCollisionObject* >& objs = go.getOverlappingPairs(); is much better.
                        }
                        // Here pObjsInsideGhostObject should be valid.

                        ProcessObectsInsideGhostObjects(pObjsInsideGhostObject, pgo != null);
                    }
                }
            }
        }
        //InplaceSolverIslandCallback operator=(InplaceSolverIslandCallback& other)
        //{
        //    Debug.Assert(false);
        //    //(void)other;
        //    return *this;
        //}


        public void Setup(ContactSolverInfo solverInfo, ObjectArray <TypedConstraint> sortedConstraints, int numConstraints, IDebugDraw debugDrawer)
        {
            Debug.Assert(solverInfo != null);
            m_solverInfo        = solverInfo;
            m_sortedConstraints = sortedConstraints;
            m_numConstraints    = numConstraints;
            m_debugDrawer       = debugDrawer;
            m_bodies.Resize(0);
            m_manifolds.Resize(0);
            m_constraints.Resize(0);
        }
Beispiel #3
0
 public static void Split(ObjectArray <DbvtNode> leaves, ObjectArray <DbvtNode> left, ObjectArray <DbvtNode> right, ref IndexedVector3 org, ref IndexedVector3 axis)
 {
     left.Resize(0);
     right.Resize(0);
     for (int i = 0, ni = leaves.Count; i < ni; ++i)
     {
         if (IndexedVector3.Dot(axis, leaves[i].volume.Center() - org) < 0)
         {
             left.Add(leaves[i]);
         }
         else
         {
             right.Add(leaves[i]);
         }
     }
 }
Beispiel #4
0
        public static void CollideTTpersistentStack(DbvtNode root0,
                                                    DbvtNode root1,
                                                    ICollide collideable)
        {
            //CollideTT(root0, root1, collideable);
            //return;
            if (root0 != null && root1 != null)
            {
                int depth    = 1;
                int treshold = DOUBLE_STACKSIZE - 4;

                m_stkStack.Resize(DOUBLE_STACKSIZE);
                m_stkStack[0] = new sStkNN(root0, root1);
                do
                {
                    sStkNN p = m_stkStack[--depth];
                    if (depth > treshold)
                    {
                        m_stkStack.Resize(m_stkStack.Count * 2);
                        treshold = m_stkStack.Count - 4;
                    }
                    if (p.a == p.b)
                    {
                        if (p.a.IsInternal())
                        {
                            m_stkStack[depth++] = new sStkNN(p.a._children[0], p.a._children[0]);
                            m_stkStack[depth++] = new sStkNN(p.a._children[1], p.a._children[1]);
                            m_stkStack[depth++] = new sStkNN(p.a._children[0], p.a._children[1]);
                        }
                    }
                    else if (DbvtAabbMm.Intersect(ref p.a.volume, ref p.b.volume))
                    {
                        if (p.a.IsInternal())
                        {
                            if (p.b.IsInternal())
                            {
                                m_stkStack[depth++] = new sStkNN(p.a._children[0], p.b._children[0]);
                                m_stkStack[depth++] = new sStkNN(p.a._children[1], p.b._children[0]);
                                m_stkStack[depth++] = new sStkNN(p.a._children[0], p.b._children[1]);
                                m_stkStack[depth++] = new sStkNN(p.a._children[1], p.b._children[1]);
                            }
                            else
                            {
                                m_stkStack[depth++] = new sStkNN(p.a._children[0], p.b);
                                m_stkStack[depth++] = new sStkNN(p.a._children[1], p.b);
                            }
                        }
                        else
                        {
                            if (p.b.IsInternal())
                            {
                                m_stkStack[depth++] = new sStkNN(p.a, p.b._children[0]);
                                m_stkStack[depth++] = new sStkNN(p.a, p.b._children[1]);
                            }
                            else
                            {
                                collideable.Process(p.a, p.b);
                            }
                        }
                    }
                } while (depth > 0);
            }
        }
Beispiel #5
0
        public static void CollideTT(DbvtNode root0, DbvtNode root1, ICollide collideable)
        {
            CollideTTCount++;
            Debug.Assert(CollideTTCount < 2);
            CollideTTStack.Clear();

            if (root0 != null && root1 != null)
            {
                int depth    = 1;
                int treshold = DOUBLE_STACKSIZE - 4;
                CollideTTStack[0] = new sStkNN(root0, root1);

                do
                {
                    sStkNN p = CollideTTStack[--depth];

                    if (depth > treshold)
                    {
                        CollideTTStack.Resize(CollideTTStack.Count * 2);
                        treshold = CollideTTStack.Count - 4;
                    }

                    if (p.a == p.b)
                    {
                        if (p.a.IsInternal())
                        {
                            CollideTTStack[depth++] = new sStkNN(p.a._children[0], p.a._children[0]);
                            CollideTTStack[depth++] = new sStkNN(p.a._children[1], p.a._children[1]);
                            CollideTTStack[depth++] = new sStkNN(p.a._children[0], p.a._children[1]);
                        }
                    }
                    else if (DbvtAabbMm.Intersect(ref p.a.volume, ref p.b.volume))
                    {
                        if (p.a.IsInternal())
                        {
                            if (p.b.IsInternal())
                            {
                                CollideTTStack[depth++] = new sStkNN(p.a._children[0], p.b._children[0]);
                                CollideTTStack[depth++] = new sStkNN(p.a._children[1], p.b._children[0]);
                                CollideTTStack[depth++] = new sStkNN(p.a._children[0], p.b._children[1]);
                                CollideTTStack[depth++] = new sStkNN(p.a._children[1], p.b._children[1]);
                            }
                            else
                            {
                                CollideTTStack[depth++] = new sStkNN(p.a._children[0], p.b);
                                CollideTTStack[depth++] = new sStkNN(p.a._children[1], p.b);
                            }
                        }
                        else
                        {
                            if (p.b.IsInternal())
                            {
                                CollideTTStack[depth++] = new sStkNN(p.a, p.b._children[0]);
                                CollideTTStack[depth++] = new sStkNN(p.a, p.b._children[1]);
                            }
                            else
                            {
                                collideable.Process(p.a, p.b);
                            }
                        }
                    }
                } while (depth > 0);
            }
            CollideTTCount--;
        }
        ///optional method mainly used to generate multiple contact points by clipping polyhedral features (faces/edges)
        public virtual bool InitializePolyhedralFeatures()
        {
#if USE_CONVEX_HULL_COMPUTER
            if (m_polyhedron != null)
            {
                m_polyhedron = null;
            }

            m_polyhedron = new ConvexPolyhedron();

            ObjectArray <IndexedVector3> tmpVertices = new ObjectArray <IndexedVector3>();
            for (int i = 0; i < GetNumVertices(); i++)
            {
                IndexedVector3 newVertex;
                GetVertex(i, out newVertex);
                tmpVertices.Add(newVertex);
            }

            ConvexHullComputer conv = new ConvexHullComputer();
            //conv.compute(&tmpVertices[0].getX(), sizeof(IndexedVector3),tmpVertices.Count,0.0f,0.0f);
            conv.Compute(tmpVertices, 0, tmpVertices.Count, 0.0f, 0.0f);



            ObjectArray <IndexedVector3> faceNormals = new ObjectArray <IndexedVector3>();
            int numFaces = conv.faces.size();
            faceNormals.Resize(numFaces);
            ConvexHullComputer convexUtil = conv;



            m_polyhedron.m_faces.Resize(numFaces);
            int numVertices = convexUtil.vertices.Count;
            m_polyhedron.m_vertices.Resize(numVertices);
            for (int p = 0; p < numVertices; p++)
            {
                m_polyhedron.m_vertices[p] = convexUtil.vertices[p];
            }

            for (int i = 0; i < numFaces; i++)
            {
                int face = convexUtil.faces[i];
                //printf("face=%d\n",face);
                Edge firstEdge = convexUtil.edges[face];
                Edge edge      = firstEdge;

                IndexedVector3[] edges = new IndexedVector3[3];
                int numEdges           = 0;
                //compute face normals

                float maxCross2  = 0.0f;
                int   chosenEdge = -1;

                do
                {
                    int src = edge.GetSourceVertex();
                    m_polyhedron.m_faces[i].m_indices.Add(src);
                    int            targ = edge.GetTargetVertex();
                    IndexedVector3 wa   = convexUtil.vertices[src];

                    IndexedVector3 wb      = convexUtil.vertices[targ];
                    IndexedVector3 newEdge = wb - wa;
                    newEdge.Normalize();
                    if (numEdges < 2)
                    {
                        edges[numEdges++] = newEdge;
                    }

                    edge = edge.GetNextEdgeOfFace();
                } while (edge != firstEdge);

                float planeEq = 1e30f;


                if (numEdges == 2)
                {
                    faceNormals[i] = IndexedVector3.Cross(edges[0], edges[1]);
                    faceNormals[i].Normalize();
                    m_polyhedron.m_faces[i].m_plane[0] = -faceNormals[i].X;
                    m_polyhedron.m_faces[i].m_plane[1] = -faceNormals[i].Y;
                    m_polyhedron.m_faces[i].m_plane[2] = -faceNormals[i].Z;
                    m_polyhedron.m_faces[i].m_plane[3] = planeEq;
                }
                else
                {
                    Debug.Assert(false);//degenerate?
                    faceNormals[i] = IndexedVector3.Zero;
                }

                for (int v = 0; v < m_polyhedron.m_faces[i].m_indices.Count; v++)
                {
                    float eq = IndexedVector3.Dot(m_polyhedron.m_vertices[m_polyhedron.m_faces[i].m_indices[v]], faceNormals[i]);
                    if (planeEq > eq)
                    {
                        planeEq = eq;
                    }
                }
                m_polyhedron.m_faces[i].m_plane[3] = planeEq;
            }


            if (m_polyhedron.m_faces.Count > 0 && conv.vertices.Count > 0)
            {
                for (int f = 0; f < m_polyhedron.m_faces.Count; f++)
                {
                    IndexedVector3 planeNormal = new IndexedVector3(m_polyhedron.m_faces[f].m_plane[0], m_polyhedron.m_faces[f].m_plane[1], m_polyhedron.m_faces[f].m_plane[2]);
                    float          planeEq     = m_polyhedron.m_faces[f].m_plane[3];

                    IndexedVector3 supVec = LocalGetSupportingVertex(-planeNormal);

                    if (IndexedVector3.Dot(supVec, planeNormal) < planeEq)
                    {
                        m_polyhedron.m_faces[f].m_plane[0] *= -1;
                        m_polyhedron.m_faces[f].m_plane[1] *= -1;
                        m_polyhedron.m_faces[f].m_plane[2] *= -1;
                        m_polyhedron.m_faces[f].m_plane[3] *= -1;
                        int numVerts = m_polyhedron.m_faces[f].m_indices.Count;
                        for (int v = 0; v < numVerts / 2; v++)
                        {
                            int temp = m_polyhedron.m_faces[f].m_indices[v];
                            m_polyhedron.m_faces[f].m_indices[v] = m_polyhedron.m_faces[f].m_indices[numVerts - 1 - v];
                            m_polyhedron.m_faces[f].m_indices[numVerts - 1 - v] = temp;
                        }
                    }
                }
            }



            m_polyhedron.Initialize();
#endif
            return(true);
        }
Beispiel #7
0
        // Portable static method: prerequisite call: m_dynamicsWorld.getBroadphase().getOverlappingPairCache().setInternalGhostPairCallback(new btGhostPairCallback()); 
        public static void GetCollidingObjectsInsidePairCachingGhostObject(DiscreteDynamicsWorld m_dynamicsWorld, PairCachingGhostObject m_pairCachingGhostObject, ObjectArray<CollisionObject> collisionArrayOut)
        {
            bool addOnlyObjectsWithNegativeDistance = true;	// With "false" things don't change much, and the code is a bit faster and cleaner...


            collisionArrayOut.Resize(0);
            if (m_pairCachingGhostObject == null || m_dynamicsWorld == null) return;

            //#define USE_PLAIN_COLLISION_WORLD // We dispatch all collision pairs of the ghost object every step (slow)
#if USE_PLAIN_COLLISION_WORLD
	//======================================================================================================
	// I thought this line was no longer needed, but it seems to be necessary (and I believe it's an expensive call):
	m_dynamicsWorld.getDispatcher().dispatchAllCollisionPairs(m_pairCachingGhostObject.getOverlappingPairCache(), m_dynamicsWorld.getDispatchInfo(), m_dynamicsWorld.getDispatcher());
	// Maybe the call can be automatically triggered by some other Bullet call (I'm almost sure I could comment it out in another demo I made long ago...)
	// So by now the general rule is: in real projects, simply comment it out and see if it works!
	//======================================================================================================
	// UPDATE: in dynamic worlds, the line above can be commented out and the broadphase pair can be retrieved through the call to findPair(...) below.
	// In collision worlds probably the above line is needed only if collision detection for all the bodies hasn't been made... This is something
	// I'm still not sure of... the general rule is to try to comment out the line above and try to use findPair(...) and see if it works whenever possible....
	//======================================================================================================
#endif //USE_PLAIN_COLLISION_WORLD

            ObjectArray<BroadphasePair> collisionPairs = m_pairCachingGhostObject.GetOverlappingPairCache().GetOverlappingPairArray();
            int numObjects = collisionPairs.Count;
            PersistentManifoldArray m_manifoldArray = new PersistentManifoldArray();
            bool added;
            for (int i = 0; i < numObjects; i++)
            {
                m_manifoldArray.Resize(0);

#if USE_PLAIN_COLLISION_WORLD
		const btBroadphasePair& collisionPair = collisionPairs[i];
		if (collisionPair.m_algorithm) collisionPair.m_algorithm.getAllContactManifolds(m_manifoldArray);
		else {	// THIS SHOULD NEVER HAPPEN, AND IF IT DOES, PLEASE RE-ENABLE the "call" a few lines above...
			printf("No collisionPair.m_algorithm - probably m_dynamicsWorld.getDispatcher().dispatchAllCollisionPairs(...) must be missing.\n");	
		}	
#else // USE_PLAIN_COLLISION_WORLD
                BroadphasePair cPair = collisionPairs[i];
                //unless we manually perform collision detection on this pair, the contacts are in the dynamics world paircache:
                BroadphasePair collisionPair = m_dynamicsWorld.GetPairCache().FindPair(cPair.m_pProxy0, cPair.m_pProxy1);
                if (collisionPair == null)
                {
                    continue;

                }
                if (collisionPair.m_algorithm != null)
                {
                    collisionPair.m_algorithm.GetAllContactManifolds(m_manifoldArray);
                }
                else
                {	// THIS SHOULD NEVER HAPPEN, AND IF IT DOES, PLEASE RE-ENABLE the "call" a few lines above...
                    //printf("No collisionPair.m_algorithm - probably m_dynamicsWorld.getDispatcher().dispatchAllCollisionPairs(...) must be missing.\n");	
                }
#endif //USE_PLAIN_COLLISION_WORLD

                added = false;
                for (int j = 0; j < m_manifoldArray.Count; j++)
                {
                    PersistentManifold manifold = m_manifoldArray[j];
                    // Here we are in the narrowphase, but can happen that manifold.getNumContacts()==0:
                    if (addOnlyObjectsWithNegativeDistance)
                    {
                        for (int p = 0, numContacts = manifold.GetNumContacts(); p < numContacts; p++)
                        {
                            ManifoldPoint pt = manifold.GetContactPoint(p);
                            if (pt.GetDistance() < 0.0)
                            {
                                // How can I be sure that the colObjs are all distinct ? I use the "added" flag.
                                collisionArrayOut.Add((CollisionObject)(manifold.GetBody0() == m_pairCachingGhostObject ? manifold.GetBody1() : manifold.GetBody0()));
                                added = true;
                                break;
                            }
                        }
                        if (added)
                        {
                            break;
                        }
                    }
                    else if (manifold.GetNumContacts() > 0)
                    {
                        collisionArrayOut.Add((CollisionObject)(manifold.GetBody0() == m_pairCachingGhostObject ? manifold.GetBody1() : manifold.GetBody0()));
                        break;
                    }
                }
            }
        }
Beispiel #8
0
        public override void ClientMoveAndDisplay(GameTime gameTime)
        {
	        // OPTIONAL: We simply move our ghost objects around (without rotating them.....)==============
	        if (m_ghostObject != null || m_pairCachingGhostObject != null)	
            {
                rad+=0.005f;	// Bad (depends on PC speed)
		        float  sinRad = (float)Math.Sin(rad);
		        float  cosRad = (float)Math.Cos(rad);
		        if (m_ghostObject != null)	
                {
                    IndexedMatrix im = IndexedMatrix.CreateFromQuaternion(quatDeg45Y);
                    im._origin = new IndexedVector3(15*cosRad,5,-15*sinRad);
			        m_ghostObject.SetWorldTransform(ref im);
		        }
		        if (m_pairCachingGhostObject != null)	
                {
                    IndexedMatrix im = IndexedMatrix.CreateFromQuaternion(quatDeg45Y);
                    im._origin = new IndexedVector3(-15*cosRad,7,15*sinRad);
			        m_pairCachingGhostObject.SetWorldTransform(ref im);
		        }	
	        }



            base.ClientMoveAndDisplay(gameTime);
	        // NEW => Retrives the content from all ghost objects in the world and call ProcessObectsInsideGhostObjects(...) for each ====		
	        if (m_dynamicsWorld != null)
	        {
                ObjectArray < CollisionObject > objsInsidePairCachingGhostObject = new ObjectArray<CollisionObject>();	// We might want this to be a member variable...							
		        ObjectArray < CollisionObject >  pObjsInsideGhostObject = null;		// We will store a reference of the current array in this pointer
		        ObjectArray < CollisionObject > objs  = m_dynamicsWorld.GetCollisionObjectArray();
		        for (int i=0,sz=objs.Count;i<sz;i++)	
                {
			        CollisionObject o = objs[i];
			        GhostObject go = GhostObject.Upcast(o);
			        if (go != null)	
                    {
				        objsInsidePairCachingGhostObject.Resize(0);
				        PairCachingGhostObject pgo = go as PairCachingGhostObject;	// No upcast functionality...
				        if (pgo != null)	
                        {
					        GetCollidingObjectsInsidePairCachingGhostObject((DiscreteDynamicsWorld)m_dynamicsWorld,pgo,objsInsidePairCachingGhostObject);
					        pObjsInsideGhostObject = objsInsidePairCachingGhostObject;
				        }
				        else 
                        {
					        pObjsInsideGhostObject = go.GetOverlappingPairs();	// It's better not to try and copy the whole array, but to keep a reference to it!
					        // Side Note: btAlignedObjectArray < btCollisionObject* > objs = go.getOverlappingPairs(); (at the moment) makes my program crash on my system...
					        // Nevermind, that was the wrong way of doing it: btAlignedObjectArray < btCollisionObject* >& objs = go.getOverlappingPairs(); is much better.
				        }	
				        // Here pObjsInsideGhostObject should be valid.
				
				        ProcessObectsInsideGhostObjects(pObjsInsideGhostObject,pgo != null);
			        }
		
		        }	
	        }

        }
 public static void Split(ObjectArray<DbvtNode> leaves, ObjectArray<DbvtNode> left, ObjectArray<DbvtNode> right, ref IndexedVector3 org, ref IndexedVector3 axis)
 {
     left.Resize(0);
     right.Resize(0);
     for (int i = 0, ni = leaves.Count; i < ni; ++i)
     {
         if (IndexedVector3.Dot(axis, leaves[i].volume.Center() - org) < 0)
         {
             left.Add(leaves[i]);
         }
         else
         {
             right.Add(leaves[i]);
         }
     }
 }
        ///optional method mainly used to generate multiple contact points by clipping polyhedral features (faces/edges)
        public virtual bool InitializePolyhedralFeatures()
        {
#if USE_CONVEX_HULL_COMPUTER
            if (m_polyhedron != null)
            {
                m_polyhedron = null;
            }

            m_polyhedron = new ConvexPolyhedron();

            ObjectArray<IndexedVector3> tmpVertices = new ObjectArray<IndexedVector3>();
            for (int i = 0; i < GetNumVertices(); i++)
            {
                IndexedVector3 newVertex;
                GetVertex(i, out newVertex);
                tmpVertices.Add(newVertex);
            }

            ConvexHullComputer conv = new ConvexHullComputer();
            //conv.compute(&tmpVertices[0].getX(), sizeof(IndexedVector3),tmpVertices.Count,0.0f,0.0f);
            conv.Compute(tmpVertices, 0, tmpVertices.Count, 0.0f, 0.0f);



            ObjectArray<IndexedVector3> faceNormals = new ObjectArray<IndexedVector3>();
            int numFaces = conv.faces.size();
            faceNormals.Resize(numFaces);
            ConvexHullComputer convexUtil = conv;



            m_polyhedron.m_faces.Resize(numFaces);
            int numVertices = convexUtil.vertices.Count;
            m_polyhedron.m_vertices.Resize(numVertices);
            for (int p = 0; p < numVertices; p++)
            {
                m_polyhedron.m_vertices[p] = convexUtil.vertices[p];
            }

            for (int i = 0; i < numFaces; i++)
            {
                int face = convexUtil.faces[i];
                //printf("face=%d\n",face);
                Edge firstEdge = convexUtil.edges[face];
                Edge edge = firstEdge;

                IndexedVector3[] edges = new IndexedVector3[3];
                int numEdges = 0;
                //compute face normals

                float maxCross2 = 0.0f;
                int chosenEdge = -1;

                do
                {
                    int src = edge.GetSourceVertex();
                    m_polyhedron.m_faces[i].m_indices.Add(src);
                    int targ = edge.GetTargetVertex();
                    IndexedVector3 wa = convexUtil.vertices[src];

                    IndexedVector3 wb = convexUtil.vertices[targ];
                    IndexedVector3 newEdge = wb - wa;
                    newEdge.Normalize();
                    if (numEdges < 2)
                    {
                        edges[numEdges++] = newEdge;
                    }

                    edge = edge.GetNextEdgeOfFace();
                } while (edge != firstEdge);

                float planeEq = 1e30f;


                if (numEdges == 2)
                {
                    faceNormals[i] = IndexedVector3.Cross(edges[0], edges[1]);
                    faceNormals[i].Normalize();
                    m_polyhedron.m_faces[i].m_plane[0] = -faceNormals[i].X;
                    m_polyhedron.m_faces[i].m_plane[1] = -faceNormals[i].Y;
                    m_polyhedron.m_faces[i].m_plane[2] = -faceNormals[i].Z;
                    m_polyhedron.m_faces[i].m_plane[3] = planeEq;

                }
                else
                {
                    Debug.Assert(false);//degenerate?
                    faceNormals[i] = IndexedVector3.Zero;
                }

                for (int v = 0; v < m_polyhedron.m_faces[i].m_indices.Count; v++)
                {
                    float eq = IndexedVector3.Dot(m_polyhedron.m_vertices[m_polyhedron.m_faces[i].m_indices[v]], faceNormals[i]);
                    if (planeEq > eq)
                    {
                        planeEq = eq;
                    }
                }
                m_polyhedron.m_faces[i].m_plane[3] = planeEq;
            }


            if (m_polyhedron.m_faces.Count > 0 && conv.vertices.Count > 0)
            {

                for (int f = 0; f < m_polyhedron.m_faces.Count; f++)
                {

                    IndexedVector3 planeNormal = new IndexedVector3(m_polyhedron.m_faces[f].m_plane[0], m_polyhedron.m_faces[f].m_plane[1], m_polyhedron.m_faces[f].m_plane[2]);
                    float planeEq = m_polyhedron.m_faces[f].m_plane[3];

                    IndexedVector3 supVec = LocalGetSupportingVertex(-planeNormal);

                    if (IndexedVector3.Dot(supVec, planeNormal) < planeEq)
                    {
                        m_polyhedron.m_faces[f].m_plane[0] *= -1;
                        m_polyhedron.m_faces[f].m_plane[1] *= -1;
                        m_polyhedron.m_faces[f].m_plane[2] *= -1;
                        m_polyhedron.m_faces[f].m_plane[3] *= -1;
                        int numVerts = m_polyhedron.m_faces[f].m_indices.Count;
                        for (int v = 0; v < numVerts / 2; v++)
                        {
                            int temp = m_polyhedron.m_faces[f].m_indices[v];
                            m_polyhedron.m_faces[f].m_indices[v] = m_polyhedron.m_faces[f].m_indices[numVerts - 1 - v];
                            m_polyhedron.m_faces[f].m_indices[numVerts - 1 - v] = temp;
                        }
                    }
                }
            }



            m_polyhedron.Initialize();

#endif
            return true;

        }
Beispiel #11
0
        public virtual void CalculateOverlappingPairs(IDispatcher dispatcher)
        {
            if (m_pairCache.HasDeferredRemoval())
            {
                ObjectArray <BroadphasePair> overlappingPairArray = m_pairCache.GetOverlappingPairArray();

                //perform a sort, to find duplicates and to sort 'invalid' pairs to the end
                overlappingPairArray.QuickSort(new BroadphasePairQuickSort());
                //overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair);
                m_invalidPair = 0;

                BroadphasePair previousPair = new BroadphasePair();

                for (int i = 0; i < overlappingPairArray.Count; i++)
                {
                    BroadphasePair pair = overlappingPairArray[i];

                    bool isDuplicate = pair.Equals(previousPair);

                    // MAN - not sure if this should be a deep copy or not...
                    previousPair = pair;

                    bool needsRemoval = false;

                    if (!isDuplicate)
                    {
                        ///important to use an AABB test that is consistent with the broadphase
                        bool hasOverlap = TestAabbOverlap(pair.m_pProxy0, pair.m_pProxy1);

                        if (hasOverlap)
                        {
                            needsRemoval = false;//callback.processOverlap(pair);
                        }
                        else
                        {
                            needsRemoval = true;
                        }
                    }
                    else
                    {
                        //remove duplicate
                        needsRemoval = true;
                        //should have no algorithm
                        Debug.Assert(pair.m_algorithm == null);
                    }

                    if (needsRemoval)
                    {
                        m_pairCache.CleanOverlappingPair(pair, dispatcher);

                        //		m_overlappingPairArray.swap(i,m_overlappingPairArray.size()-1);
                        //		m_overlappingPairArray.pop_back();
                        pair.m_pProxy0 = null;
                        pair.m_pProxy1 = null;
                        m_invalidPair++;
                        OverlappingPairCacheGlobals.gOverlappingPairs--;
                    }
                }

                ///if you don't like to skip the invalid pairs in the array, execute following code:
#if CLEAN_INVALID_PAIRS
                overlappingPairArray.QuickSort(new BroadphasePairQuickSort());

                overlappingPairArray.Resize(overlappingPairArray.Count - m_invalidPair);
                m_invalidPair = 0;
#endif//CLEAN_INVALID_PAIRS

                //printf("overlappingPairArray.size()=%d\n",overlappingPairArray.size());
            }
        }
        // Portable static method: prerequisite call: m_dynamicsWorld.getBroadphase().getOverlappingPairCache().setInternalGhostPairCallback(new btGhostPairCallback());
        public static void GetCollidingObjectsInsidePairCachingGhostObject(DiscreteDynamicsWorld m_dynamicsWorld, PairCachingGhostObject m_pairCachingGhostObject, ObjectArray <CollisionObject> collisionArrayOut)
        {
            bool addOnlyObjectsWithNegativeDistance = true;     // With "false" things don't change much, and the code is a bit faster and cleaner...


            collisionArrayOut.Resize(0);
            if (m_pairCachingGhostObject == null || m_dynamicsWorld == null)
            {
                return;
            }

            //#define USE_PLAIN_COLLISION_WORLD // We dispatch all collision pairs of the ghost object every step (slow)
#if USE_PLAIN_COLLISION_WORLD
            //======================================================================================================
            // I thought this line was no longer needed, but it seems to be necessary (and I believe it's an expensive call):
            m_dynamicsWorld.getDispatcher().dispatchAllCollisionPairs(m_pairCachingGhostObject.getOverlappingPairCache(), m_dynamicsWorld.getDispatchInfo(), m_dynamicsWorld.getDispatcher());
            // Maybe the call can be automatically triggered by some other Bullet call (I'm almost sure I could comment it out in another demo I made long ago...)
            // So by now the general rule is: in real projects, simply comment it out and see if it works!
            //======================================================================================================
            // UPDATE: in dynamic worlds, the line above can be commented out and the broadphase pair can be retrieved through the call to findPair(...) below.
            // In collision worlds probably the above line is needed only if collision detection for all the bodies hasn't been made... This is something
            // I'm still not sure of... the general rule is to try to comment out the line above and try to use findPair(...) and see if it works whenever possible....
            //======================================================================================================
#endif //USE_PLAIN_COLLISION_WORLD

            ObjectArray <BroadphasePair> collisionPairs = m_pairCachingGhostObject.GetOverlappingPairCache().GetOverlappingPairArray();
            int numObjects = collisionPairs.Count;
            PersistentManifoldArray m_manifoldArray = new PersistentManifoldArray();
            bool added;
            for (int i = 0; i < numObjects; i++)
            {
                m_manifoldArray.Resize(0);

#if USE_PLAIN_COLLISION_WORLD
                const btBroadphasePair& collisionPair = collisionPairs[i];
                if (collisionPair.m_algorithm)
                {
                    collisionPair.m_algorithm.getAllContactManifolds(m_manifoldArray);
                }
                else    // THIS SHOULD NEVER HAPPEN, AND IF IT DOES, PLEASE RE-ENABLE the "call" a few lines above...
                {
                    printf("No collisionPair.m_algorithm - probably m_dynamicsWorld.getDispatcher().dispatchAllCollisionPairs(...) must be missing.\n");
                }
#else // USE_PLAIN_COLLISION_WORLD
                BroadphasePair cPair = collisionPairs[i];
                //unless we manually perform collision detection on this pair, the contacts are in the dynamics world paircache:
                BroadphasePair collisionPair = m_dynamicsWorld.GetPairCache().FindPair(cPair.m_pProxy0, cPair.m_pProxy1);
                if (collisionPair == null)
                {
                    continue;
                }
                if (collisionPair.m_algorithm != null)
                {
                    collisionPair.m_algorithm.GetAllContactManifolds(m_manifoldArray);
                }
                else
                {       // THIS SHOULD NEVER HAPPEN, AND IF IT DOES, PLEASE RE-ENABLE the "call" a few lines above...
                    //printf("No collisionPair.m_algorithm - probably m_dynamicsWorld.getDispatcher().dispatchAllCollisionPairs(...) must be missing.\n");
                }
#endif //USE_PLAIN_COLLISION_WORLD

                added = false;
                for (int j = 0; j < m_manifoldArray.Count; j++)
                {
                    PersistentManifold manifold = m_manifoldArray[j];
                    // Here we are in the narrowphase, but can happen that manifold.getNumContacts()==0:
                    if (addOnlyObjectsWithNegativeDistance)
                    {
                        for (int p = 0, numContacts = manifold.GetNumContacts(); p < numContacts; p++)
                        {
                            ManifoldPoint pt = manifold.GetContactPoint(p);
                            if (pt.GetDistance() < 0.0)
                            {
                                // How can I be sure that the colObjs are all distinct ? I use the "added" flag.
                                collisionArrayOut.Add((CollisionObject)(manifold.GetBody0() == m_pairCachingGhostObject ? manifold.GetBody1() : manifold.GetBody0()));
                                added = true;
                                break;
                            }
                        }
                        if (added)
                        {
                            break;
                        }
                    }
                    else if (manifold.GetNumContacts() > 0)
                    {
                        collisionArrayOut.Add((CollisionObject)(manifold.GetBody0() == m_pairCachingGhostObject ? manifold.GetBody1() : manifold.GetBody0()));
                        break;
                    }
                }
            }
        }