Esempio n. 1
0
        private bool LoadNodeLump(Q3BSPDirEntry dir, BinaryReader fileReader)
        {
            int nodeCount = dir.Length / Q3BSPConstants.sizeNode;

            nodes = new Q3BSPNode[nodeCount];

            for (int i = 0; i < nodeCount; i++)
            {
                nodes[i] = Q3BSPNode.FromStream(fileReader);
            }

            bspLogger.WriteLine("No of nodes: " + nodeCount);
            return(true);
        }
Esempio n. 2
0
        private void WalkNode(int nodeIndex, float startRatio, float endRatio, Vector3 startPosition, Vector3 endPosition, ref Q3BSPCollisionData cd)
        {
            // Is this a leaf?
            if (0 > nodeIndex)
            {
                Q3BSPLeaf leaf = leafs[-(nodeIndex + 1)];
                for (int i = 0; i < leaf.LeafBrushCount; i++)
                {
                    Q3BSPBrush brush = brushes[leafBrushes[leaf.StartLeafBrush + i]];
                    if (0 < brush.NumberOfSides &&
                        1 == (textureData[brush.TextureIndex].Contents & 1))
                    {
                        CheckBrush(ref brush, ref cd);
                    }
                }

                return;
            }

            // This is a node
            Q3BSPNode thisNode      = nodes[nodeIndex];
            Plane     thisPlane     = planes[thisNode.Plane];
            float     startDistance = Vector3.Dot(startPosition, thisPlane.Normal) - thisPlane.D;
            float     endDistance   = Vector3.Dot(endPosition, thisPlane.Normal) - thisPlane.D;
            float     offset        = 0;

            // Set offset for sphere-based collision
            if (cd.type == Q3BSPCollisionType.Sphere)
            {
                offset = cd.sphereRadius;
            }

            // Set offest for box-based collision
            if (cd.type == Q3BSPCollisionType.Box)
            {
                offset = Math.Abs(cd.boxExtents.X * thisPlane.Normal.X) + Math.Abs(cd.boxExtents.Y * thisPlane.Normal.Y) + Math.Abs(cd.boxExtents.Z * thisPlane.Normal.Z);
            }

            if (startDistance >= offset && endDistance >= offset)
            {
                // Both points are in front
                WalkNode(thisNode.Left, startRatio, endRatio, startPosition, endPosition, ref cd);
            }
            else if (startDistance < -offset && endDistance < -offset)
            {
                WalkNode(thisNode.Right, startRatio, endRatio, startPosition, endPosition, ref cd);
            }
            else
            {
                // The line spans the splitting plane
                int     side           = 0;
                float   fraction1      = 0.0f;
                float   fraction2      = 0.0f;
                float   middleFraction = 0.0f;
                Vector3 middlePosition = new Vector3();

                if (startDistance < endDistance)
                {
                    side = 1;
                    float inverseDistance = 1.0f / (startDistance - endDistance);
                    fraction1 = (startDistance - offset + Q3BSPConstants.Epsilon) * inverseDistance;
                    fraction2 = (startDistance + offset + Q3BSPConstants.Epsilon) * inverseDistance;
                }
                else if (endDistance < startDistance)
                {
                    side = 0;
                    float inverseDistance = 1.0f / (startDistance - endDistance);
                    fraction1 = (startDistance + offset + Q3BSPConstants.Epsilon) * inverseDistance;
                    fraction2 = (startDistance - offset - Q3BSPConstants.Epsilon) * inverseDistance;
                }
                else
                {
                    side      = 0;
                    fraction1 = 1.0f;
                    fraction2 = 0.0f;
                }

                if (fraction1 < 0.0f)
                {
                    fraction1 = 0.0f;
                }
                else if (fraction1 > 1.0f)
                {
                    fraction1 = 1.0f;
                }
                if (fraction2 < 0.0f)
                {
                    fraction2 = 0.0f;
                }
                else if (fraction2 > 1.0f)
                {
                    fraction2 = 1.0f;
                }

                middleFraction = startRatio + (endRatio - startRatio) * fraction1;
                middlePosition = startPosition + fraction1 * (endPosition - startPosition);

                int side1;
                int side2;
                if (0 == side)
                {
                    side1 = thisNode.Left;
                    side2 = thisNode.Right;
                }
                else
                {
                    side1 = thisNode.Right;
                    side2 = thisNode.Left;
                }

                WalkNode(side1, startRatio, middleFraction, startPosition, middlePosition, ref cd);

                middleFraction = startRatio + (endRatio - startRatio) * fraction2;
                middlePosition = startPosition + fraction2 * (endPosition - startPosition);

                WalkNode(side2, middleFraction, endRatio, middlePosition, endPosition, ref cd);
            }
        }