Frustum Culling 在Maya里根據相機視錐來過濾物體

檢查物體是否在攝影機視錐範圍的腳本。
但是實際使用中,考慮到光照和反射的影響,即使物體出畫,似乎也不能簡單的就將其隱藏或刪除。。。。
原文地址:https://gizmosandgames.com/2017/05/21/frustum-culling-in-maya/

import maya.api.OpenMaya as OpenMaya


class Plane(object):
    def __init__(self, a, b, c, d):
        self.normal = OpenMaya.MVector(a, b, c)
        self.distance = d

    def normalise(self):
        length = self.normal.length()
        self.normal /= length
        self.distance /= length

    def is_in_front(self, point):
        return point * self.normal + self.distance > 0


class Frustum(object):
    def __init__(self, camera_name):
        selection_list = OpenMaya.MSelectionList()
        selection_list.add(camera_name)
        # cam_dag_path = selection_list.getDagPath(0)
        cam_dag_path = self.get_object_dagPath(camera_name)
        self.camera = OpenMaya.MFnCamera(cam_dag_path)

        world_to_cam = OpenMaya.MFloatMatrix(cam_dag_path.inclusiveMatrixInverse())
        projection = self.camera.projectionMatrix()
        post_projection = self.camera.postProjectionMatrix()

        # MFloatMatrix = [x-axis, y-axis, z-axis, translate]
        view_projection = world_to_cam * projection * post_projection


        # Right = translate - x-axis
        self.right = Plane(
            view_projection[3] - view_projection[0],
            view_projection[7] - view_projection[4],
            view_projection[11] - view_projection[8],
            view_projection[15] - view_projection[12],
        )

        # Left = translate + x-axis
        self.left = Plane(
            view_projection[3] + view_projection[0],
            view_projection[7] + view_projection[4],
            view_projection[11] + view_projection[8],
            view_projection[15] + view_projection[12],
        )

        # Bottom = translate + y-axis
        self.bottom = Plane(
            view_projection[3] + view_projection[1],
            view_projection[7] + view_projection[5],
            view_projection[11] + view_projection[9],
            view_projection[15] + view_projection[13],
        )

        # Top = translate - y-axis
        self.top = Plane(
            view_projection[3] - view_projection[1],
            view_projection[7] - view_projection[5],
            view_projection[11] - view_projection[9],
            view_projection[15] - view_projection[13],
        )

        # Far = translate + z-axis
        self.far = Plane(
            view_projection[3] + view_projection[2],
            view_projection[7] + view_projection[6],
            view_projection[11] + view_projection[10],
            view_projection[15] + view_projection[14],
        )

        # Near = translate - z-axis
        self.near = Plane(
            view_projection[3] - view_projection[2],
            view_projection[7] - view_projection[6],
            view_projection[11] - view_projection[10],
            view_projection[15] - view_projection[14],
        )

        self.planes = [self.right, self.left, self.bottom, self.top, self.far, self.near]

    def get_object_dagPath(self, name):
        selectionList= OpenMaya.MSelectionList()
        selectionList.add(name)
        node_dagDath = selectionList.getDagPath(0)
        return node_dagDath

    def intersects(self, name):
        node_dagDath = self.get_object_dagPath(name)
        node_dagNode = OpenMaya.MFnDagNode(node_dagDath)
        bbox = node_dagNode.boundingBox
        limits = [bbox.min, bbox.max]

        for plane in self.planes:
            # The corner furthest in normal direction of plane
            index_x = int(plane.normal.x > 0)
            index_y = int(plane.normal.y > 0)
            index_z = int(plane.normal.z > 0)
            point = OpenMaya.MVector(limits[index_x].x, limits[index_y].y, limits[index_z].z)

            # If this corner is not in front, none are, bbox is out of view
            if not plane.is_in_front(point):
                return False

        return True


if __name__ == '__main__':
    fs = Frustum('camera1')
    statue = fs.intersects('pCylinder1')
    print statue
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章