private void OnDrawGizmosSelected() { //foreach(LinearBVHNode node in SceneParser._SceneData._BVHNodeList) //{ // Gizmos.color = Color.yellow; // Vector3 gizmoCenter = (node.bounds.pMax + node.bounds.pMin) / 2; // Vector3 gizmoDiff = (node.bounds.pMax - node.bounds.pMin); // Gizmos.DrawWireCube(gizmoCenter, gizmoDiff); //} for (int i = 0; i < level_count; i++) { LinearBVHNode node = SceneParser._SceneData._BVHNodeList[i]; Gizmos.color = new Color(1, 0, 0, 0.5f) + new Color(0, 1, 1, 0.5f) / level_count * i; if (i == level_count - 1) { Gizmos.color = Color.yellow; } Vector3 gizmoCenter = (node.bounds.pMax + node.bounds.pMin) / 2; Vector3 gizmoDiff = (node.bounds.pMax - node.bounds.pMin); Gizmos.DrawWireCube(gizmoCenter, gizmoDiff); } }
//顺序存储BVH void FlattenBVH(BVHNode root, int count) { bvhNodes = new LinearBVHNode[count]; for (int i = 0; i < count; i++) { bvhNodes[i] = new LinearBVHNode(); } int offset = 0; BuildFlattenBVH(root, ref offset); }
void BuildFlattenBVH(BVHNode bvhNode, ref int offset) { LinearBVHNode linearBVHNode = new LinearBVHNode(); linearBVHNode.aabb = bvhNode.aabb; linearBVHNode.axis = bvhNode.axis; if (bvhNode.triangles != null) { linearBVHNode.triangles = new int[bvhNode.triangles.Length]; for (int i = 0; i < linearBVHNode.triangles.Length; i++) { linearBVHNode.triangles[i] = bvhNode.triangles[i]; } } bvhNodes[offset] = linearBVHNode; if (bvhNode.left == null && bvhNode.right == null) { offset++; linearBVHNode.left = false; linearBVHNode.right = -1; } else { if (bvhNode.left != null) { linearBVHNode.left = true; offset++; BuildFlattenBVH(bvhNode.left, ref offset); linearBVHNode.right = offset; } if (bvhNode.right != null) { BuildFlattenBVH(bvhNode.right, ref offset); } } }
private int FlattenBVHTree(Node node, ref int offset) { if (node == null) { return -1; } nodes[offset] = new LinearBVHNode() { bbox = node.Bound }; var linearNode = nodes[offset]; int myOffset = (offset)++; if (node.nPrims > 0) { linearNode.primOffset = node.StartOffset; linearNode.nPrimitives = (byte)node.nPrims; } else { linearNode.axis = (byte)node.SplitAxis; linearNode.nPrimitives = 0; FlattenBVHTree(node.Left, ref offset); linearNode.secondChildOffset = FlattenBVHTree(node.Right, ref offset); } return myOffset; }
// Create MeshData and MeshBoundingBox of the object private void ParseSceneMesh(Transform meshObject) { MeshData newMeshData = new MeshData(); newMeshData._TriangleIndexStart = _SceneData._SizeOfTriangleList; newMeshData._VertexIndexStart = _SceneData._SizeOfVertexList; newMeshData._BVHNodeOffset = _SceneData._SizeOfBVHNodeList; Mesh mesh = meshObject.GetComponent <MeshFilter>().mesh; Vector3[] newVertexList = mesh.vertices; for (int i = 0; i < newVertexList.Length; i++) { newVertexList[i] = meshObject.rotation * newVertexList[i]; newVertexList[i] = meshObject.localScale.x * newVertexList[i]; newVertexList[i] = meshObject.position + newVertexList[i]; } _SceneData._VertexList.AddRange(newVertexList); _SceneData._SizeOfVertexList += mesh.vertexCount; List <Triangle> newMeshTriangles = new List <Triangle>(); List <BVHPrimitiveInfo> primitiveInfos = new List <BVHPrimitiveInfo>(); int iterator = 0; while (iterator < mesh.triangles.Length) { Triangle newTriangle = new Triangle(); // Set new triangles indices newTriangle.indices.x = mesh.triangles[iterator]; newTriangle.indices.y = mesh.triangles[iterator + 1]; newTriangle.indices.z = mesh.triangles[iterator + 2]; Vector3 p0 = newVertexList[(int)newTriangle.indices.x]; Vector3 p1 = newVertexList[(int)newTriangle.indices.y]; Vector3 p2 = newVertexList[(int)newTriangle.indices.z]; // Set new triangles bounds Bounds3 triBounds = new Bounds3(); triBounds.pMax = Vector3.Max(p0, p1); triBounds.pMax = Vector3.Max(triBounds.pMax, p2); triBounds.pMin = Vector3.Min(p0, p1); triBounds.pMin = Vector3.Min(triBounds.pMin, p2); BVHPrimitiveInfo newInfo = new BVHPrimitiveInfo(newMeshTriangles.Count, triBounds); primitiveInfos.Add(newInfo); iterator += 3; newMeshTriangles.Add(newTriangle); } BVHAcc BVHAccObj = new BVHAcc(ref primitiveInfos); foreach (LinearBVHNode node in BVHAccObj.LinearBVHArr) { LinearBVHNode newLinearNode = new LinearBVHNode(); newLinearNode.bounds = node.bounds; newLinearNode.primitiveOffset = node.primitiveOffset; newLinearNode.secondChildOffset = node.secondChildOffset; //Debug.Log("Primitiveoffset: " + node.primitiveOffset); //Debug.Log("SecondChildoffset: " + node.secondChildOffset); _SceneData._BVHNodeList.Add(newLinearNode); _SceneData._SizeOfBVHNodeList++; } _SceneData._TriangleList.AddRange(newMeshTriangles); _SceneData._SizeOfTriangleList = _SceneData._TriangleList.Count; newMeshData._TriangleIndexEnd = _SceneData._SizeOfTriangleList; AddMaterialData(meshObject); newMeshData._MaterialID = _SceneData._MaterialCount - 1; _SceneData._MeshDataList.Add(newMeshData); _SceneData._MeshCount++; //Debug.Log("Mesh Count: " + _SceneData._MeshCount); //Debug.Log("BVHNode Count: " + _SceneData._SizeOfBVHNodeList); //Debug.Log("BVHNode offset: " + _SceneData._MeshDataList[0]._BVHNodeOffset); }
public override bool RayDetection(Ray ray, RaycastHit hitInfo) { if (transform != null) { ray.Transform(transform.worldToLocalMatrix); } bool[] dirIsNeg = new bool[3] { ray.direction.x < 0, ray.direction.y < 0, ray.direction.z < 0 }; Stack <int> s = new Stack <int>(); s.Push(0); bool hit = false; while (s.Count > 0) { int idx = s.Pop(); LinearBVHNode linearBVHNode = bvhNodes[idx]; if (linearBVHNode.aabb.RayDetection(ray)) { if (!linearBVHNode.left && linearBVHNode.right == -1) { if (transform != null) { Mesh mesh = transform.GetComponent <MeshFilter>().sharedMesh; for (int i = 0; i < linearBVHNode.triangles.Length; i++) { int triangle = linearBVHNode.triangles[i]; hit |= ray.Raycast(mesh.vertices[mesh.triangles[triangle * 3]], mesh.vertices[mesh.triangles[triangle * 3 + 1]], mesh.vertices[mesh.triangles[triangle * 3 + 2]]); } } else { hit |= linearBVHNode.aabb.transform.GetComponent <BoxCollider>().box .RayDetection(ray, hitInfo); } } if (dirIsNeg[linearBVHNode.axis]) { if (linearBVHNode.left) { s.Push(++idx); } if (linearBVHNode.right != -1) { s.Push(linearBVHNode.right); } } else { if (linearBVHNode.right != -1) { s.Push(linearBVHNode.right); } if (linearBVHNode.left) { s.Push(++idx); } } } } if (transform != null) { ray.Transform(transform.localToWorldMatrix); if (hit) { hitInfo.point = ray.origin + ray.direction * ray.distance; hitInfo.transform = transform; } } return(hit); }