如何使用 MDL 对边界框进行命中测试

mje*_*agh 5 3d swift metal metalkit

我正在尝试计算与 MDL 边界框的交集,我的代码基于 WM 的精彩文章,网址为http://metalbyexample.com/picking-hit-testing/#more-738

t0 应该是最近点的想法https://www.scratchapixel.com/lessons/3d-basic-rendering/minimal-ray-tracer-rendering-simple-shapes/ray-sphere-intersection

https://www.scratchapixel.com/lessons/3d-basic-rendering/minimal-ray-tracer-rendering-simple-shapes/ray-box-intersection

但这并没有发生

extension MDLAxisAlignedBoundingBox {

    func intersect(_ ray: Ray) -> float4? {

        var tmin = minBounds
        var tmax = maxBounds

        let inverseDirection = 1 / ray.direction

        var sign : [Int] = [(inverseDirection.x < 0) ? 1 : 0,(inverseDirection.y < 0) ? 1 : 0,(inverseDirection.z < 0) ? 1 : 0]


        var bounds : [float3] = [minBounds,maxBounds]


        var t0 = Float(minBounds.z)

        if ((tmin.x > tmax.y) || (tmin.y > tmax.x)){
            return nil
        }



        if (tmin.y > tmin.x){
             tmin.x = tmin.y;
        }


        if (tmax.y < tmax.x){
            tmax.x = tmax.y;
        }

        tmin.z = (bounds[sign[2]].z - ray.origin.z) * inverseDirection.z
        tmax.z = (bounds[1-sign[2]].z - ray.origin.z) * inverseDirection.z



        if ((tmin.x > tmax.z) || (tmin.z > tmax.x)){
            return nil
        }

        if (tmin.z > tmin.x){
            tmin.x = tmin.z
            t0 = tmin.x
        }

        if (tmax.z < tmax.x){
            tmax.x = tmax.z
            t0 = tmax.z
        }


        return float4(ray.origin + ray.direction * t0, 1)
    }
}
Run Code Online (Sandbox Code Playgroud)

预计最后达到的结果应该是最短向量。

先感谢您

mje*_*agh 2

这是解决方案:

extension MDLAxisAlignedBoundingBox {

        func intersect(_ ray: Ray) -> float4? {

            var tmin = minBounds
            var tmax = maxBounds

            let inverseDirection = 1 / ray.direction

            var sign : [Int] = [(inverseDirection.x < 0) ? 1 : 0,(inverseDirection.y < 0) ? 1 : 0,(inverseDirection.z < 0) ? 1 : 0]


            var bounds : [float3] = [minBounds,maxBounds]


            var t0 = Float(minBounds.z)

            if ((tmin.x > tmax.y) || (tmin.y > tmax.x)){
                return nil
            }



            if (tmin.y > tmin.x){
                 tmin.x = tmin.y;
            }


            if (tmax.y < tmax.x){
                tmax.x = tmax.y;
            }

            tmin.z = (bounds[sign[2]].z - ray.origin.z) * inverseDirection.z
            tmax.z = (bounds[1-sign[2]].z - ray.origin.z) * inverseDirection.z



            if ((tmin.x > tmax.z) || (tmin.z > tmax.x)){
                return nil
            }

            if (tmin.z > tmin.x){
                tmin.x = tmin.z
                t0 = tmin.x
            }

            if (tmax.z < tmax.x){
                tmax.x = tmax.z
                t0 = tmax.z
            }


            return float4(ray.origin + ray.direction * t0, 1)

  }

}
Run Code Online (Sandbox Code Playgroud)

你必须确保你的方向是正确的。

far / (near - far)
Run Code Online (Sandbox Code Playgroud)

你的

eyeRayDir.z = -1
Run Code Online (Sandbox Code Playgroud)

和相机位置

相机位置 = [0, 0, 15]

在你的节点类中你应该有

var boundingBox = MDLAxisAlignedBoundingBox()
var size: float3 {
    return boundingBox.maxBounds - boundingBox.minBounds
}
Run Code Online (Sandbox Code Playgroud)

希望有帮助