public MeshRay TraceRay(Vector3 start, Vector3 dir) { MeshRay ray = new MeshRay(); ray.distance = float.PositiveInfinity; TraceRecursive(0, start, dir, ref ray); ray.hit = ray.distance != float.PositiveInfinity; return(ray); }
public MeshRay TraceRaySlow(Vector3 start, Vector3 dir) { float minT, minU, minV, minW, minS; minT = minU = minV = minW = minS = float.PositiveInfinity; float t, u, v, w, s; bool hit = false; int minIndex = 0; for (int i = 0; i < NumFaces; ++i) { Vector3 a = Vertices[Indices[i * 3 + 0]]; Vector3 b = Vertices[Indices[i * 3 + 1]]; Vector3 c = Vertices[Indices[i * 3 + 2]]; if (IntersectRayTriTwoSided(start, dir, a, b, c, out t, out u, out v, out w, out s)) { if (t < minT) { minT = t; minU = u; minV = v; minW = w; minS = s; minIndex = i; hit = true; } } } MeshRay ray = new MeshRay(); ray.distance = minT; ray.u = minU; ray.v = minV; ray.w = minW; ray.faceSign = minS; ray.faceIndex = minIndex; ray.hit = hit; return(ray); }
private void TraceRecursive(int nodeIndex, Vector3 start, Vector3 dir, ref MeshRay ray) { AABBNode node = Nodes[nodeIndex]; if (node.Faces == null) { // find closest node AABBNode leftChild = Nodes[node.Children + 0]; AABBNode rightChild = Nodes[node.Children + 1]; float[] dist = new float[] { float.PositiveInfinity, float.PositiveInfinity }; IntersectRayAABB(start, dir, leftChild.Bounds.Min, leftChild.Bounds.Max, out dist[0]); IntersectRayAABB(start, dir, rightChild.Bounds.Min, rightChild.Bounds.Max, out dist[1]); int closest = 0; int furthest = 1; if (dist[1] < dist[0]) { closest = 1; furthest = 0; } if (dist[closest] < ray.distance) { TraceRecursive(node.Children + closest, start, dir, ref ray); } if (dist[furthest] < ray.distance) { TraceRecursive(node.Children + furthest, start, dir, ref ray); } } else { float t, u, v, w, s; for (int i = 0; i < node.Faces.Length; ++i) { int indexStart = node.Faces[i] * 3; Vector3 a = Vertices[Indices[indexStart + 0]]; Vector3 b = Vertices[Indices[indexStart + 1]]; Vector3 c = Vertices[Indices[indexStart + 2]]; if (IntersectRayTriTwoSided(start, dir, a, b, c, out t, out u, out v, out w, out s)) { if (t < ray.distance) { ray.distance = t; ray.u = u; ray.v = v; ray.w = w; ray.faceSign = s; ray.faceIndex = node.Faces[i]; } } } } }
public void Voxelize(IList <Vector3> vertices, IList <int> indices, Box3 bounds) { Array.Clear(Voxels, 0, Voxels.Length); // build an aabb tree of the mesh MeshRayTracer tree = new MeshRayTracer(vertices, indices); Bounds = tree.GetBounds(); // parity count method, single pass Vector3 extents = bounds.Size; Vector3 delta = new Vector3(extents.x / Width, extents.y / Height, extents.z / Depth); Vector3 offset = new Vector3(0.5f / Width, 0.5f / Height, 0.5f / Depth); float eps = 1e-7f * extents.z; for (int x = 0; x < Width; ++x) { for (int y = 0; y < Height; ++y) { bool inside = false; Vector3 rayDir = new Vector3(0.0f, 0.0f, 1.0f); // z-coord starts somewhat outside bounds Vector3 rayStart = bounds.Min + new Vector3(x * delta.x + offset.x, y * delta.y + offset.y, -0.0f * extents.z); while (true) { MeshRay ray = tree.TraceRay(rayStart, rayDir); if (ray.hit) { // calculate cell in which intersection occurred float zpos = rayStart.z + ray.distance * rayDir.z; float zhit = (zpos - bounds.Min.z) / delta.z; int z = (int)((rayStart.z - bounds.Min.z) / delta.z); int zend = (int)Math.Min(zhit, Depth - 1); if (inside) { for (int k = z; k <= zend; ++k) { Voxels[x, y, k] = 1; Count++; } } inside = !inside; rayStart += rayDir * (ray.distance + eps); } else { break; } } } } //end }