public void CreateBVH() { if (transform == null) { BoxCollider[] boxColliders = GameObject.FindObjectsOfType <BoxCollider>(); AABB[] aabbs = new AABB[boxColliders.Length]; for (int i = 0; i < boxColliders.Length; i++) { AABB aabb = boxColliders[i].box.OuterAABB(); aabbs[i] = aabb; } int count = 0; BVHNode root = BuildBVH(aabbs, 0, aabbs.Length, ref count); FlattenBVH(root, count); } else { Mesh mesh = transform.GetComponent <MeshFilter>().sharedMesh; AABB[] aabbs = new AABB[mesh.triangles.Length / 3]; for (int i = 0; i < aabbs.Length; i++) { AABB aabb = AABB.Default; aabb.triangle = i; aabb.Union(mesh.vertices[mesh.triangles[i * 3]]); aabb.Union(mesh.vertices[mesh.triangles[i * 3 + 1]]); aabb.Union(mesh.vertices[mesh.triangles[i * 3 + 2]]); aabbs[i] = aabb; } int count = 0; BVHNode root = BuildBVH(aabbs, 0, aabbs.Length, ref count); FlattenBVH(root, count); } }
// Extracts an easily processable BVH tree from the packed version in the mesh data public BVHNode getMeshBVH() { if (CompressedBVH.Size == 0 || CompressedBVH.GetArrayData() == null) { return(null); } BVHNode root = new BVHNode(); root.Min = new Vector3(BoundingBoxMin.X, BoundingBoxMin.Y, BoundingBoxMin.Z); root.Max = new Vector3(BoundingBoxMax.X, BoundingBoxMax.Y, BoundingBoxMax.Z); CompressedMeshBVHNode cnode = CompressedBVH.GetArrayData().Elements[0]; if ((cnode.IDX0 & 0x80) > 0) { root.Left = buildBVHTree(root.Min, root.Max, 1); root.Right = buildBVHTree(root.Min, root.Max, ((((uint)cnode.IDX0 & 0x7F) << 8) | (uint)cnode.IDX1) * 2); } else { root.IsTerminal = true; root.Index = (((uint)cnode.IDX0 & 0x7F) << 8) | (uint)cnode.IDX1; } return(root); }
//bvh Raycast public static bool RaycastBVH(Ray ray, BVHNode node, out float t) { //check if it hits model AABB even if (!RaycastAABB(ray, node.AABB, out t)) { return(false); } //loop through children and recursively raycast if (node.Children != null) { foreach (BVHNode child in node.Children) { if (RaycastBVH(ray, child, out t)) { return(true); } } } //if leaf node, raycast against triangles if (node.Triangles != null) { foreach (Triangle triangle in node.Triangles) { if (Collisions.RaycastTriangle(ray, triangle, out t)) { return(true); } } } //return false by default return(false); }
private void CornellSmoke() { Vector3D lookFrom = new Vector3D(278, 278, -800); Vector3D lookAt = new Vector3D(278, 278, 0); double diskToFocus = 10; double aperture = 0; double vfov = 40; camera = new Camera(lookFrom, lookAt, new Vector3D(0, 1, 0), vfov, (double)width / (double)height, aperture, diskToFocus, 0, 1); List <Hitable> list = new List <Hitable>(); Material red = new Lambertian(new ConstantTexture(new Vector3D(0.65, 0.05, 0.05))); Material white = new Lambertian(new ConstantTexture(new Vector3D(0.73, 0.73, 0.73))); Material green = new Lambertian(new ConstantTexture(new Vector3D(0.12, 0.45, 0.15))); Material light = new DiffuseLight(new ConstantTexture(new Vector3D(7, 7, 7))); list.Add(new XZRect(113, 443, 127, 432, 554, light)); list.Add(new FlipNormals(new YZRect(0, 555, 0, 555, 555, green))); list.Add(new YZRect(0, 555, 0, 555, 0, red)); list.Add(new FlipNormals(new XZRect(0, 555, 0, 555, 555, white))); list.Add(new XZRect(0, 555, 0, 555, 0, white)); list.Add(new FlipNormals(new XYRect(0, 555, 0, 555, 555, white))); Hitable b1 = new Translate(new RotateY(new Box(new Vector3D(0, 0, 0), new Vector3D(165, 165, 165), white), -18), new Vector3D(130, 0, 65)); Hitable b2 = new Translate(new RotateY(new Box(new Vector3D(0, 0, 0), new Vector3D(165, 330, 165), white), 15), new Vector3D(265, 0, 295)); list.Add(new ConstantMedium(b1, 0.01, new ConstantTexture(new Vector3D(1, 1, 1)))); list.Add(new ConstantMedium(b2, 0.01, new ConstantTexture(new Vector3D(0, 0, 0)))); BVHNode b = new BVHNode(list, list.Count, 0, 1); world.list.Add(b); }
public void Build(List <T> datas) { m_Root = null; Vector3 min = Vector3.one * double.MaxValue; Vector3 max = Vector3.one * double.MinValue; List <T> aabbDatas = new List <T>(datas.Count); for (int i = 0; i < datas.Count; i++) { if (datas[i] != null) { min = Vector3.Min(min, datas[i].GetBounds().min); max = Vector3.Max(max, datas[i].GetBounds().max); aabbDatas.Add(datas[i]); } } if (aabbDatas.Count > 0) { Bounds bounds = new Bounds((min + max) * 0.5, max - min); BuildInternal(aabbDatas, bounds); } }
private BVHNode BuildBVH(List <Triangle> triangles, int depth) { Bounds bounds = GetTrianglesBounds(triangles); if (depth == m_MaxDepth) { return(new BVHNode(triangles, bounds)); } AxisType atype = AxisType.X; if (bounds.size.y >= bounds.size.x && bounds.size.y >= bounds.size.z) { atype = AxisType.Y; } else if (bounds.size.z >= bounds.size.x && bounds.size.z >= bounds.size.y) { atype = AxisType.Z; } float value = GetSplitAxis(triangles, atype); List <Triangle> negative = new List <Triangle>(); List <Triangle> positive = new List <Triangle>(); for (int i = 0; i < triangles.Count; i++) { SplitTriangle(triangles[i], negative, positive, atype, value); } BVHNode left = BuildBVH(negative, depth + 1); BVHNode right = BuildBVH(positive, depth + 1); return(new BVHNode(left, right, bounds)); }
// Extracts an easily processable BVH tree from the packed version in the mesh data public BVHNode getChunkBVH() { if (nodes.Size == 0 || nodes.GetArrayData() == null) { return(null); } BVHNode root = new BVHNode(); root.Min = new Vector3(BoundingBoxMin.X, BoundingBoxMin.Y, BoundingBoxMin.Z); root.Max = new Vector3(BoundingBoxMax.X, BoundingBoxMax.Y, BoundingBoxMax.Z); CompressedChunkBVHNode cnode = nodes.GetArrayData().Elements[0]; if ((cnode.IDX & 0x01) > 0) { root.Left = buildBVHTree(root.Min, root.Max, 1); root.Right = buildBVHTree(root.Min, root.Max, (uint)cnode.IDX & 0xFE); } else { root.IsTerminal = true; root.Index = (uint)cnode.IDX / 2; } return(root); }
void Start() { Stopwatch sw = new Stopwatch(); sw.Start(); Scene scene = new Scene(true); bvhScene = new BVHScene(scene.triangles, scene.vertices); Debug.Log("bvhScene.triangles.Count = " + bvhScene.triangles.Count); Debug.Log(" ================================ "); var bvhData = new CPU_BVHData(bvhScene); CPU_SBVHBuilder.Build(bvhData); Debug.Log("bvhData.triangles.Count = " + bvhData.triIndices.Count); Debug.Log(" ================================ "); // debug gpu bvh GPU_BVHData gpuData = new GPU_BVHData().Generate(bvhData); Debug.Log("gpuData.nodes.Count = " + gpuData.nodes.Count); Debug.Log("gpuData.woopTris.Count = " + gpuData.woopTris.Count); Debug.Log("gpuData.triIndices.Count = " + gpuData.triIndices.Count); root = bvhData.root; sw.Stop(); string log = "Build successfully, time: " + sw.ElapsedMilliseconds + " ms"; Debug.Log(log); }
private void Final() { Vector3D lookFrom = new Vector3D(278, 278, -800); Vector3D lookAt = new Vector3D(278, 278, 0); float diskToFocus = 10; float aperture = 0; float vfov = 40; camera = new Camera(lookFrom, lookAt, new Vector3D(0, 1, 0), vfov, (float)width / (float)height, aperture, diskToFocus, 0, 1); List <Hitable> list = new List <Hitable>(); Material red = new Lambertian(new ConstantTexture(new Vector3D(0.65f, 0.05f, 0.05f))); Material white = new Lambertian(new ConstantTexture(new Vector3D(0.73f, 0.73f, 0.73f))); Material green = new Lambertian(new ConstantTexture(new Vector3D(0.12f, 0.45f, 0.15f))); Material light = new DiffuseLight(new ConstantTexture(new Vector3D(15, 15, 15))); list.Add(new FlipNormals(new XZRect(213, 343, 227, 332, 554, light))); list.Add(new FlipNormals(new YZRect(0, 555, 0, 555, 555, green))); list.Add(new YZRect(0, 555, 0, 555, 0, red)); list.Add(new FlipNormals(new XZRect(0, 555, 0, 555, 555, white))); list.Add(new XZRect(0, 555, 0, 555, 0, white)); list.Add(new FlipNormals(new XYRect(0, 555, 0, 555, 555, white))); list.Add(new Translate(new RotateY(new Box(new Vector3D(0, 0, 0), new Vector3D(165, 165, 165), white), -18), new Vector3D(130, 0, 65))); list.Add(new Translate(new RotateY(new Box(new Vector3D(0, 0, 0), new Vector3D(165, 330, 165), white), 15), new Vector3D(265, 0, 295))); BVHNode b = new BVHNode(list, list.Count, 0, 1); world.list.Add(b); }
// Extracts an easily processable BVH tree from the packed version in the mesh data public BVHNode GetTree() { if (CompressedTree.Size == 0 || CompressedTree.GetArrayData() == null) { return(null); } BVHNode root = new BVHNode(); root.Min = new Vector3(AABBMin.X, AABBMin.Y, AABBMin.Z); root.Max = new Vector3(AABBMax.X, AABBMax.Y, AABBMax.Z); StaticAABBNode cnode = CompressedTree.GetArrayData().Elements[0]; if ((cnode.IDX0 & 0x80) > 0) { root.Left = buildTree(root.Min, root.Max, 1); root.Right = buildTree(root.Min, root.Max, ((((uint)cnode.IDX0 & 0x7F) << 8) | (uint)cnode.IDX1) * 2); } else { root.IsTerminal = true; root.Index = (((uint)cnode.IDX0 & 0x7F) << 8) | (uint)cnode.IDX1; } return(root); }
private int FlattenTree(BVHNode node, ref int offset) { LBVH linearNode = new LBVH(); linearNode.min = node.boundingBox.min; linearNode.max = node.boundingBox.max; int myOffset = offset++; if (node.children == null) { int primitives = node.meshCount << 16; // int n = (int) (primitives >> 16); linearNode.primAndAxis = primitives; linearNode.offset = node.meshIndexStart; // Debug.Log(linearNode.offset); flatTree[myOffset] = linearNode; } else { linearNode.primAndAxis = node.splitAxis; //linearNode.primAndAxis |= (int) (linearNode.primAndAxis ^ 4294901760); FlattenTree(node.children[0], ref offset); linearNode.offset = FlattenTree(node.children[1], ref offset); flatTree[myOffset] = linearNode; } return(myOffset); }
private void InitScene() { int width = 2000; int height = 1000; bool isSky = true; Vector3D lookFrom = new Vector3D(13, 2, 3); Vector3D lookAt = new Vector3D(0, 0, 0); float diskToFocus = (lookFrom - lookAt).Length(); float aperture = 0; Camera camera = new Camera(lookFrom, lookAt, new Vector3D(0, 1, 0), 20, (float)width / (float)height, aperture, 0.7f * diskToFocus, 0, 1); Texture checker = new CheckerTexture( new ConstantTexture(new Vector3D(0.2f, 0.3f, 0.1f)), new ConstantTexture(new Vector3D(0.9f, 0.9f, 0.9f))); List <Hitable> list = new List <Hitable>(); list.Add(new Sphere(new Vector3D(0, -1000, 0), 1000, new Lambertian(checker))); for (int a = -11; a < 11; a++) { for (int b = -11; b < 11; b++) { double chooseMat = Mathf.Randomfloat(); Vector3D center = new Vector3D(a + 0.9f * Mathf.Randomfloat(), 0.2f, b + 0.9f * Mathf.Randomfloat()); if ((center - new Vector3D(4, 0.2f, 0)).Length() > 0.9) { if (chooseMat < 0.8) { list.Add(new MovingSphere(center, center + new Vector3D(0, 0.5f * Mathf.Randomfloat(), 0), 0, 1, 0.2f, new Lambertian(new ConstantTexture(new Vector3D( Mathf.Randomfloat() * Mathf.Randomfloat(), Mathf.Randomfloat() * Mathf.Randomfloat(), Mathf.Randomfloat() * Mathf.Randomfloat()))))); } else if (chooseMat < 0.95) { list.Add(new Sphere(center, 0.2f, new Metal(new Vector3D( 0.5f * (1 + Mathf.Randomfloat()), 0.5f * (1 + Mathf.Randomfloat()), 0.5f * (1 + Mathf.Randomfloat())), 0.5f * (1 + Mathf.Randomfloat())))); } else { list.Add(new Sphere(center, 0.2f, new Dielectric(1.5f))); } } } } list.Add(new Sphere(new Vector3D(0, 1, 0), 1, new Dielectric(1.5f))); list.Add(new Sphere(new Vector3D(-4, 1, 0), 1, new Lambertian(new ConstantTexture(new Vector3D(0.4f, 0.2f, 0.1f))))); list.Add(new Sphere(new Vector3D(4, 1, 0), 1, new Metal(new Vector3D(0.7f, 0.6f, 0.5f), 0))); BVHNode bb = new BVHNode(list, list.Count, 0, 1); HitableList world = new HitableList(); world.list.Add(bb); scene = new Scene(width, height, world, isSky, camera, 0, false); }
public override void Build(AABB aabb, List <Body> bodies) { potientialCollisionCount = 0; List <Body> sorted = new List <Body>(bodies); sorted.Sort((x, y) => x.position.x.CompareTo(y.position.y)); //sorted = bodies.OrderBy(body => body.position.x).ToList(); rootNode = new BVHNode(sorted); }
public BVHNode(BVHNode left, BVHNode right, Bounds bounds) { m_Left = left; m_Right = right; bounds = FixBounds(bounds); m_Bounds = bounds; }
public int BVHTreeToArrayDfs(BVHNode node, List <RTBVHNode> BVHTreeList, List <RTTriangle> triangleList, int listIndex) { if (node == null) { return(0); } if (node.left == null && node.right == null) { RTBVHNode tempNode = new RTBVHNode() { isLeaf = 1, startIndex = (uint)triangleList.Count, triangleCount = (uint)node.triangles.Count, subTreeCount = 0, }; BVHTreeList.Add(tempNode); foreach (Triangle tri in node.triangles) { RTTriangle tempTriangle = new RTTriangle() { v0 = tri.v0, v1 = tri.v1, v2 = tri.v2, normal = tri.normal, matIndex = tri.matIndex, }; triangleList.Add(tempTriangle); } return(1); } RTBVHNode tempNode2 = new RTBVHNode(); BVHTreeList.Add(tempNode2); int index = BVHTreeList.Count - 1; int leftCount = BVHTreeToArrayDfs(node.left, BVHTreeList, triangleList, listIndex + 1); int rightCount = BVHTreeToArrayDfs(node.right, BVHTreeList, triangleList, listIndex + 1); int count = leftCount + rightCount; RTBVHNode tempNode1 = new RTBVHNode() { isLeaf = 0, boundingBoxMin = node.bbox.min, boundingBoxMax = node.bbox.max, subTreeCount = (uint)count, }; BVHTreeList[index] = tempNode1; return(count + 1); }
public override void Build(AABB aabb, List <Body> bodies) { potentialColCount = 0; List <Body> sorted = new List <Body>(bodies); //sort along x axis sorted.Sort((x, y) => x.Position.x.CompareTo(y.Position.x)); rootNode = new BVHNode(sorted); }
public override void Build(AABB aabb, List <Body> bodies) { potentialCollisionCount = 0; List <Body> sorted = new List <Body>(bodies); // sort bodies along x-axis sorted.Sort((a, b) => (a.position.x.CompareTo(b.position.x))); // set sorted bodies to root bvh node rootNode = new BVHNode(sorted); }
void DrawBVH(BVHNode bvhNode) { if (bvhNode == null) { return; } bvhNode.aabb.DrawAABB(); DrawBVH(bvhNode.leftChild); DrawBVH(bvhNode.rightChild); }
//recursive private API private void RenderBVH(BVHNode node) { node.AABB.Render(); if (node.Children != null) { foreach (BVHNode child in node.Children) { RenderBVH(child); } } }
public void Split() { int length = bodies.Count; //< number of elements in bodies list>; int half = length / 2; //< half the length>; if (half >= 1) { left = new BVHNode(bodies.GetRange(0, half)); right = new BVHNode(bodies.GetRange(half, half + (length % 2))); bodies.Clear(); } }
public void InitChildren(BVHNode child0, BVHNode child1, int axis) { children = new BVHNode[2]; children[0] = child0; children[1] = child1; boundingBox = child0.boundingBox; boundingBox.Encapsulate(child1.boundingBox); meshIndexStart = -1; splitAxis = axis; }
//顺序存储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); }
public override void Build(AABB aabb, List <Body> bodies) { potentialCollisionCount = 0; List <Body> sorted = new List <Body>(bodies); // sort bodies along x-axis (position.x) //< https://stackoverflow.com/questions/24187287/c-sharp-listt-orderby-float-member>); sorted.Sort((bodyA, bodyB) => bodyA.position.x.CompareTo(bodyB.position.y)); // set sorted bodies to root bvh node rootNode = new BVHNode(sorted); }
private void Draw(BVHNode node) { if (node.children == null) { Gizmos.DrawWireCube(node.boundingBox.center, node.boundingBox.size); } else { Draw(node.children[0]); Draw(node.children[1]); } }
public override void Build(AABB aabb, List <Body> bodies) { potentialCollisionCount = 0; List <Body> sorted = new List <Body>(bodies); // sort bodies along x-axis (position.x) //collection.OrderBy(v => v.Value) //BroadPhase broadPhase = new BVH(); sorted.Sort((body, body2) => body.position.x.CompareTo(body2.position.x)); // set sorted bodies to root bvh node rootNode = new BVHNode(sorted); }
public void Split() { int length = bodies.Count; int half = length / 2; if (half >= 1) { left = new BVHNode(bodies.GetRange(0, half)); right = new BVHNode(bodies.GetRange(half, half + (length % 2))); bodies.Clear(); } }
public override void Build(AABB aabb, List <Body> bodies) { potentialCollisionCount = 0; List <Body> sorted = new List <Body>(bodies); // sort bodies along x-axis (position.x) /*< https://stackoverflow.com/questions/24187287/c-sharp-listt-orderby-float-member>*/ //sorted.Sort(); /*sorted = */ sorted.OrderBy(body => body.transform.position.x).ToList(); // set sorted bodies to root bvh node rootNode = new BVHNode(sorted); }
public BVHTree(List <Triangle> triangles, bool useBVHTree) { if (useBVHTree) { root = build(triangles, 0); } else { root = new BVHNode(); root.triangles = triangles; root.left = null; root.right = null; root.bbox = new BoundingBox(triangles); } }
private BVHNode GenerateHierarchy(List <T> boundsGeometries, List <uint> sortedMortons, int first, int last) { if (first == last) { return(new BVHNode(boundsGeometries[first])); } //查找分割平面位置 int split = FindSplit(sortedMortons, first, last); //将AABB列表根据分割平面分割成左右子树 BVHNode child1 = GenerateHierarchy(boundsGeometries, sortedMortons, first, split); BVHNode child2 = GenerateHierarchy(boundsGeometries, sortedMortons, split + 1, last); return(new BVHNode(child1, child2)); }
public void CreateBVH() { if (transform == null) { MeshFilter[] meshFilters = GameObject.FindObjectsOfType <MeshFilter>(); AABB[] aabbs = new AABB[meshFilters.Length]; for (int i = 0; i < meshFilters.Length; i++) { AABB aabb = new AABB(meshFilters[i].transform); aabb.UpdateAABB(AABBStructureMode.Compact); aabbs[i] = aabb; } root = BuildBVH(aabbs, 0, aabbs.Length); } }