private bool LoadLeafLump(Q3BSPDirEntry dir, BinaryReader fileReader) { int leafCount = dir.Length / Q3BSPConstants.sizeLeaf; leafs = new Q3BSPLeaf[leafCount]; for (int i = 0; i < leafCount; i++) { leafs[i] = Q3BSPLeaf.FromStream(fileReader); } bspLogger.WriteLine("No of leafs: " + leafCount); return(true); }
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); } }