Beispiel #1
0
        /// <summary>
        ///  Adds all triangles of node which intersect b to list result, returns exact intersection points in
        /// intersectionPoints. the function closestPointInTriangle() is used for computing triangle-sphere
        /// intersections.
        /// </summary>
        /// <param name="b"></param>
        /// <param name="node"></param>
        /// <param name="result"></param>
        private void nodeCollisions(BoundingSphere b, BspNode node, LinkedList <Face> result, LinkedList <Vector3> intersectionPoints)
        {
            float squaredBoundingSphereRadius = b.Radius * b.Radius;

            foreach (Face face in node.faces)
            {
                Vector3 pos1, pos2, pos3;
                pos1 = mLevelData.vertices[face.v1];
                pos2 = mLevelData.vertices[face.v2];
                pos3 = mLevelData.vertices[face.v3];

                // check collision with triangle bounding sphere first
                if (b.Intersects(face.boundingSphere) == false)
                {
                    continue;
                }

                Vector3 closestPoint = closestPointInTriangle(b.Center, pos1, pos2, pos3);
                float   squaredDist  = (closestPoint - b.Center).LengthSquared();
                if (squaredDist <= squaredBoundingSphereRadius)
                {
                    result.AddLast(face);
                    intersectionPoints.AddLast(closestPoint);
                }
            }
        }
Beispiel #2
0
        /// <summary>
        /// Recursive tree building procedure: reads separating planes from the file, builds up
        /// the tree in preorder.
        /// </summary>
        /// <param name="node">Node we are currently processing</param>
        /// <param name="file">Binary file to read separating planes from</param>
        /// <param name="numPlanesRemaining">Number of planes remaining</param>
        private void buildTree(ref BspNode node, BinaryReader file, ref uint numPlanesRemaining)
        {
            // no more planes remaining? append leaf node, stop recursion.
            if (numPlanesRemaining == 0)
            {
                node       = new BspNode();
                node.faces = new List <Face>();
                return;
            }

            // read separating plane data
            double x = file.ReadDouble();
            double y = file.ReadDouble();
            double z = file.ReadDouble();
            double d = file.ReadDouble();

            // one plane less to read
            numPlanesRemaining--;

            // did we reach a leaf?
            // in this case: create leaf node and stop this recursion on this branch
            if (x == 0.0 && y == 0.0 && z == 0.0 && d == 0.0)
            {
                node       = new BspNode();
                node.faces = new List <Face>();
                return;
            }

            // neither finished, nor leaf reached: create a new node, start two new
            // recursions to the left and right of the tree
            node = new BspNode(new Plane((float)x, (float)y, (float)z, (float)d));
            buildTree(ref node.pos, file, ref numPlanesRemaining);
            buildTree(ref node.neg, file, ref numPlanesRemaining);
        }
Beispiel #3
0
        /// <summary>
        /// Inserts the faces in the level geometry into the leafs of the tree. If a face
        /// intersects a separating plane,it is passed down on both sides of the plane.
        /// </summary>
        private void insertGeometryData()
        {
            // for each face
            foreach (Face face in mLevelData.faces)
            {
                Vector3 pos1 = mLevelData.vertices[face.v1];
                Vector3 pos2 = mLevelData.vertices[face.v2];
                Vector3 pos3 = mLevelData.vertices[face.v3];

                // create a list of nodes we have to process on our way to the leafs of the tree
                LinkedList <BspNode> toProcess = new LinkedList <BspNode>();
                toProcess.AddFirst(mRoot);

                // as long as we have nodes to process
                while (toProcess.Count > 0)
                {
                    // take first node
                    BspNode curNode = toProcess.First.Value;
                    toProcess.RemoveFirst();

                    // not leaf? propagate face to correct child node. (both nodes in case of intersection)
                    if (curNode.separatingPlane.Normal.X != 0.0f ||
                        curNode.separatingPlane.Normal.Y != 0.0f ||
                        curNode.separatingPlane.Normal.Z != 0.0f ||
                        curNode.separatingPlane.D != 0.0f)
                    {
                        // compute side each triangle vertex lies on
                        float side1 = Vector3.Dot(curNode.separatingPlane.Normal, pos1) + curNode.separatingPlane.D;
                        float side2 = Vector3.Dot(curNode.separatingPlane.Normal, pos2) + curNode.separatingPlane.D;
                        float side3 = Vector3.Dot(curNode.separatingPlane.Normal, pos3) + curNode.separatingPlane.D;


                        if (side1 > 0 && side2 > 0 && side3 > 0)
                        {
                            // all points on positive side? propagate to positive side
                            toProcess.AddLast(curNode.pos);
                        }
                        else if (side1 <= 0 && side2 <= 0 && side3 <= 0)
                        {
                            // all points on negative side?  propagate to negative side
                            toProcess.AddLast(curNode.neg);
                        }
                        else
                        {
                            // no luck, triangle intersects plane, we have to propagate it on both sides
                            toProcess.AddLast(curNode.pos);
                            toProcess.AddLast(curNode.neg);
                        }
                    }
                    else
                    {
                        curNode.faces.Add(face);
                    }
                }
            }
        }
Beispiel #4
0
        /// <summary>
        /// Returns the raw number of triangles actually checked for collision
        /// (all triangles in all nodes that are reached)
        /// </summary>
        /// <param name="b"></param>
        /// <param name="result"></param>
        public void checkedFaces(BoundingSphere b, LinkedList <Face> result)
        {
            LinkedList <BspNode> toProcess = new LinkedList <BspNode>();

            toProcess.AddLast(mRoot);

            while (toProcess.Count > 0)
            {
                BspNode curNode = toProcess.First.Value;
                toProcess.RemoveFirst();

                if (curNode.separatingPlane.Normal.X == 0.0f &&
                    curNode.separatingPlane.Normal.Y == 0.0f &&
                    curNode.separatingPlane.Normal.Z == 0.0f &&
                    curNode.separatingPlane.D == 0.0f)
                {
                    foreach (Face f in curNode.faces)
                    {
                        result.AddLast(f);
                    }
                }

                else
                {
                    PlaneIntersectionType side = curNode.separatingPlane.Intersects(b);

                    if (side == PlaneIntersectionType.Back)
                    {
                        toProcess.AddLast(curNode.neg);
                    }
                    else if (side == PlaneIntersectionType.Front)
                    {
                        toProcess.AddLast(curNode.pos);
                    }
                    else
                    {
                        toProcess.AddLast(curNode.pos);
                        toProcess.AddLast(curNode.neg);
                    }
                }
            }
        }
Beispiel #5
0
        /// <summary>
        /// Computes all triangles colliding with the given bounding sphere
        /// </summary>
        /// <param name="b">Bounding sphere to be checked for collision</param>
        /// <param name="collidingFaces">Colliding faces are added to this list (may contain duplicates!)</param>
        /// <param name="collisionPoints">For each colliding face, the exact collision points is added to this list</param>
        public void collisions(BoundingSphere b, LinkedList <Face> collidingFaces, LinkedList <Vector3> collisionPoints)
        {
            LinkedList <BspNode> toProcess = new LinkedList <BspNode>();

            toProcess.AddLast(mRoot);

            while (toProcess.Count > 0)
            {
                BspNode curNode = toProcess.First.Value;
                toProcess.RemoveFirst();

                // have we reached a leaf? check all triangles in leaf for collisions
                if (curNode.separatingPlane.Normal.X == 0.0f &&
                    curNode.separatingPlane.Normal.Y == 0.0f &&
                    curNode.separatingPlane.Normal.Z == 0.0f &&
                    curNode.separatingPlane.D == 0.0f)
                {
                    nodeCollisions(b, curNode, collidingFaces, collisionPoints);
                }

                else
                {
                    // propagate bounding sphere down the tree
                    PlaneIntersectionType side = curNode.separatingPlane.Intersects(b);

                    if (side == PlaneIntersectionType.Back)
                    {
                        toProcess.AddLast(curNode.neg);
                    }
                    else if (side == PlaneIntersectionType.Front)
                    {
                        toProcess.AddLast(curNode.pos);
                    }
                    else
                    {
                        toProcess.AddLast(curNode.pos);
                        toProcess.AddLast(curNode.neg);
                    }
                }
            }
        }
Beispiel #6
0
        /// <summary>
        ///  Adds all triangles of node which intersect b to list result, returns exact intersection points in 
        /// intersectionPoints. the function closestPointInTriangle() is used for computing triangle-sphere
        /// intersections.
        /// </summary>
        /// <param name="b"></param>
        /// <param name="node"></param>
        /// <param name="result"></param>
        private void nodeCollisions(BoundingSphere b, BspNode node, LinkedList<Face> result, LinkedList<Vector3> intersectionPoints)
        {
            float squaredBoundingSphereRadius = b.Radius * b.Radius;

            foreach (Face face in node.faces)
            {
                Vector3 pos1, pos2, pos3;
                pos1 = mLevelData.vertices[face.v1];
                pos2 = mLevelData.vertices[face.v2];
                pos3 = mLevelData.vertices[face.v3];

                // check collision with triangle bounding sphere first
                if (b.Intersects(face.boundingSphere) == false)
                    continue;

                Vector3 closestPoint = closestPointInTriangle(b.Center, pos1, pos2, pos3);
                float squaredDist = (closestPoint - b.Center).LengthSquared();
                if (squaredDist <= squaredBoundingSphereRadius)
                {
                    result.AddLast(face);
                    intersectionPoints.AddLast(closestPoint);
                }

            }
        }
Beispiel #7
0
        /// <summary>
        /// Recursive tree building procedure: reads separating planes from the file, builds up
        /// the tree in preorder. 
        /// </summary>
        /// <param name="node">Node we are currently processing</param>
        /// <param name="file">Binary file to read separating planes from</param>
        /// <param name="numPlanesRemaining">Number of planes remaining</param>
        private void buildTree(ref BspNode node, BinaryReader file, ref uint numPlanesRemaining)
        {
            // no more planes remaining? append leaf node, stop recursion.
            if (numPlanesRemaining == 0)
            {
                node = new BspNode();
                node.faces = new List<Face>();
                return;
            }

            // read separating plane data
            double x = file.ReadDouble();
            double y = file.ReadDouble();
            double z = file.ReadDouble();
            double d = file.ReadDouble();

            // one plane less to read
            numPlanesRemaining--;

            // did we reach a leaf?
            // in this case: create leaf node and stop this recursion on this branch
            if (x == 0.0 && y == 0.0 && z == 0.0 && d == 0.0)
            {
                node = new BspNode();
                node.faces = new List<Face>();
                return;
            }

            // neither finished, nor leaf reached: create a new node, start two new
            // recursions to the left and right of the tree
            node = new BspNode(new Plane((float)x, (float)y, (float)z, (float)d));
            buildTree(ref node.pos, file, ref numPlanesRemaining);
            buildTree(ref node.neg, file, ref numPlanesRemaining);
        }