private bool Raycast(MeshTreeRaycast raycast, ref TreeNode node, Vector3 extents, int posX, int posZ, int width, ref MeshTreeRaycast.TemporaryParam param, uint order) { extents.y = node.m_yExtent; var halfWidth = 0.5f * width; float distance; if ( !raycast.BoundsHitTest( new Vector3(m_scale.x * (posX + halfWidth), node.m_yCenter, m_scale.z * (posZ + halfWidth)), extents, param, out distance)) { return(false); } if (node.m_childIndex < 0) { var hit = false; for (int z = posZ, zEnd = posZ + width; z < zEnd; ++z) { for (int x = posX, xEnd = posX + width; x < xEnd; ++x) { var v0 = new Vector3(m_scale.x * x, m_heightMap[z, x], m_scale.z * z); var v1 = new Vector3(m_scale.x * (x + 1), m_heightMap[z, x + 1], m_scale.z * z); var v2 = new Vector3(m_scale.x * x, m_heightMap[z + 1, x], m_scale.z * (z + 1)); var v3 = new Vector3(m_scale.x * (x + 1), m_heightMap[z + 1, x + 1], m_scale.z * (z + 1)); if (raycast.TriangleHitTest(v0, v2, v3)) { hit = true; } if (raycast.TriangleHitTest(v0, v3, v1)) { hit = true; } } } return(hit); } width /= 2; extents.x *= 0.5f; extents.z *= 0.5f; for (var i = 0; i < 4; ++i) { var n = (order >> (i * 4)) & 0xF; var x = posX; var z = posZ; if ((n & 1) != 0) { x += width; } if ((n & 2) != 0) { z += width; } if (Raycast(raycast, ref m_treeNodes[node.m_childIndex + n], extents, x, z, width, ref param, order)) { return(true); } } return(false); }
private bool Raycast(MeshTreeRaycast raycast, ref TreeNode node, Vector3 center, Vector3 extents, ref MeshTreeRaycast.TemporaryParam param, uint order) { float distance; if (!raycast.BoundsHitTest(center, extents, param, out distance)) { return(false); } if (node.m_childIndex < 0) { if (node.m_triangles == null || node.m_triangles.Length == 0) { return(false); } var hit = false; for (var i = 0; i < node.m_triangles.Length; ++i) { var tri = node.m_triangles[i]; if (raycast.TriangleHitTest(m_vertices[m_indices[tri]], m_vertices[m_indices[tri + 1]], m_vertices[m_indices[tri + 2]])) { hit = true; } } return(hit); } var collapseFlags = node.collapseFlags; var halfExtents = extents; if (collapseFlags != 0) { uint flags = 0xff; var collapsedOrder = order; var indexShift = 0; uint shiftMask = 0; if ((collapseFlags & 0x1) != 0) { collapsedOrder &= ~0x11111111u; flags &= 0x55; indexShift = 1; } else { halfExtents.x *= 0.5f; } if ((collapseFlags & 0x2) != 0) { collapsedOrder &= ~0x22222222u; flags &= 0x33; shiftMask = 1u >> indexShift; ++indexShift; } else { halfExtents.y *= 0.5f; } if ((collapseFlags & 0x4) != 0) { collapsedOrder &= ~0x44444444u; flags &= 0x0F; } else { halfExtents.z *= 0.5f; } center = center - extents + halfExtents; for (var i = 0; i < 8 && flags != 0; ++i, flags >>= 1) { var p = center; if ((flags & 1) != 0) { var n = (collapsedOrder >> (4 * i)) & 0xF; if ((n & 1) != 0) { p.x += extents.x; } if ((n & 2) != 0) { p.y += extents.y; } if ((n & 4) != 0) { p.z += extents.z; } var index = (int)(node.childIndex + ((n >> indexShift) | (n & shiftMask))); if (Raycast(raycast, ref m_treeNodes[index], p, halfExtents, ref param, order)) { return(true); } } } } else { halfExtents *= 0.5f; center = center - extents + halfExtents; for (var i = 0; i < 8; ++i) { var p = center; var n = (order >> (4 * i)) & 0xF; if ((n & 1) != 0) { p.x += extents.x; } if ((n & 2) != 0) { p.y += extents.y; } if ((n & 4) != 0) { p.z += extents.z; } if (Raycast(raycast, ref m_treeNodes[node.childIndex + n], p, halfExtents, ref param, order)) { return(true); } } } return(false); }
private bool Raycast(MeshTreeRaycast raycast, ref TreeNode node, ref MeshTreeRaycast.TemporaryParam param) { if (node.m_childIndex < 0) { if (node.m_triangles == null || node.m_triangles.Length == 0) { return(false); } var hit = false; for (var i = 0; i < node.m_triangles.Length; ++i) { var tri = node.m_triangles[i]; if (raycast.TriangleHitTest(m_vertices[m_indices[tri]], m_vertices[m_indices[tri + 1]], m_vertices[m_indices[tri + 2]])) { hit = true; } } return(hit); } float distance1, distance2; var hit1 = raycast.BoundsHitTest(m_treeNodes[node.m_childIndex].m_bounds.center, m_treeNodes[node.m_childIndex].m_bounds.extents, param, out distance1); var hit2 = raycast.BoundsHitTest(m_treeNodes[node.m_childIndex + 1].m_bounds.center, m_treeNodes[node.m_childIndex + 1].m_bounds.extents, param, out distance2); if (hit1) { if (hit2) { if (distance1 < distance2) { if (Raycast(raycast, ref m_treeNodes[node.m_childIndex], ref param)) { // there is a chance that the other node has the nearest hit point, since bounding boxes of nodes in a binary mesh trees are overlapping each other. if (distance2 < raycast.hitDistance) { Raycast(raycast, ref m_treeNodes[node.m_childIndex + 1], ref param); } return(true); } return(Raycast(raycast, ref m_treeNodes[node.m_childIndex + 1], ref param)); } if (Raycast(raycast, ref m_treeNodes[node.m_childIndex + 1], ref param)) { // there is a chance that the other node has the nearest hit point, since bounding boxes of nodes in a binary mesh trees are overlapping each other. if (distance1 < raycast.hitDistance) { Raycast(raycast, ref m_treeNodes[node.m_childIndex], ref param); } return(true); } return(Raycast(raycast, ref m_treeNodes[node.m_childIndex], ref param)); } return(Raycast(raycast, ref m_treeNodes[node.m_childIndex], ref param)); } if (hit2) { return(Raycast(raycast, ref m_treeNodes[node.m_childIndex + 1], ref param)); } return(false); }