Example #1
0
        public override void Raycast(MeshTreeRaycast raycast)
        {
            var param = raycast.CreateTemporaryParam();
            var order = 0x3210u;

            if (raycast.direction.x < 0.0f)
            {
                order ^= 0x1111u;
            }
            if (raycast.direction.z < 0.0f)
            {
                order ^= 0x2222u;
            }
            Raycast(raycast, ref m_treeNodes[m_treeNodes.Length - 1], m_bounds.extents, 0, 0, m_heightMapWidth,
                    ref param, order);
        }
Example #2
0
 public abstract void Raycast(MeshTreeRaycast raycast);
Example #3
0
        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);
        }
Example #4
0
        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);
        }
Example #5
0
        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);
        }
Example #6
0
        public override void Raycast(MeshTreeRaycast raycast)
        {
            var param = raycast.CreateTemporaryParam();

            Raycast(raycast, ref m_treeNodes[m_treeNodes.Length - 1], ref param);
        }