Как пройти тест с помощью ограничительной рамки, используя MDL - PullRequest
3 голосов
/ 30 марта 2019

Я пытаюсь вычислить пересечение с ограничивающим прямоугольником 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)
    }
}

ожидается, что результат, если он достигнут в конце, должен быть кратчайшим вектором.

СпасибоВы заранее

1 Ответ

1 голос
/ 06 июля 2019

Вот решение:

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)

  }

}

Вы должны быть уверены, что находитесь в правильном направлении.

far / (near - far)

ваш

eyeRayDir.z = -1

и положение камеры

camera.position = [0, 0, 15]

и в вашем классе узлов вы должны иметь

var boundingBox = MDLAxisAlignedBoundingBox()
var size: float3 {
    return boundingBox.maxBounds - boundingBox.minBounds
}

Надеюсь, это поможет

...