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
### 回答1: 相机视锥(Camera Frustum)是在计算机图形学中用于表示相机在三维空间中可见范围的几何形状。通过计算相机视锥代码,我们可以获得相机的射线方向和视野范围,从而帮助我们进行可视化渲染等操作。 以下是一个简单的计算相机视锥的代码示例: 1. 首先,我们需要获取相机的投影矩阵(projection matrix)和相机的视图矩阵(view matrix),这两个矩阵通常由引擎或库提供。 2. 然后,我们可以使用这两个矩阵来计算相机视锥的六个面(near, far, left, right, top, bottom)。 3. 首先,我们需要将投影矩阵和视图矩阵相乘,得到投影视图矩阵(projection-view matrix)。 4. 接下来,我们使用逆转置矩阵的转置以及四个坐标分量计算各个面的法线和距离。根据相机视锥的特性,这些面的法线向量和距离可以帮助我们计算视锥的六个面的方程式。 5. 最后,我们可以将这些值存储在一个数据结构中,以供后续的计算和使用。 这只是计算相机视锥的一个简单示例,实际上,相机视锥的计算可能涉及更多复杂的操作和算法,我们需要考虑到相机的位置、方向、视角等因素。 通过计算相机视锥,我们可以实现一些基于相机的功能和效果,比如裁剪不可见物体、实现可见性检测、绘制远近景物体等。这对于实现高性能的可视化渲染是非常重要的。 ### 回答2: 相机视锥是指在计算机图形学中,用来确定在屏幕上显示的可见场景的范围。在3D图形渲染中,相机视锥由近裁剪面、远裁剪面、左裁剪面、右裁剪面、上裁剪面和下裁剪面六个平面组成,形成一个截锥体。计算相机视锥的代码通常需要用到视图矩阵、投影矩阵和顶点坐标等信息。 一个简单的计算相机视锥的代码示例如下: 1. 定义视图矩阵和投影矩阵。 ``` matrix4 viewMatrix = ...; matrix4 projectionMatrix = ...; ``` 2. 定义顶点坐标。 ``` vec3 vertex1 = ...; vec3 vertex2 = ...; ... ``` 3. 将顶点坐标变换到裁剪空间。 ``` vec4 clipVertex1 = projectionMatrix * viewMatrix * vec4(vertex1, 1.0); vec4 clipVertex2 = projectionMatrix * viewMatrix * vec4(vertex2, 1.0); ... ``` 4. 计算裁剪空间中的四个顶点(左下、左上、右下、右上)。 ``` vec4 bottomLeft = clipVertex1; vec4 topLeft = clipVertex2; vec4 bottomRight = clipVertex2; vec4 topRight = clipVertex1; ``` 5. 将裁剪空间中的顶点坐标变换到规范化设备坐标空间(NDC)。 ``` vec3 ndcVertex1 = bottomLeft.xyz / bottomLeft.w; vec3 ndcVertex2 = topLeft.xyz / topLeft.w; ... ``` 6. 计算相机视锥的近裁剪面、远裁剪面以及左、右、上、下裁剪面在规范化设备坐标空间中的位置。 ``` float nearPlane = ndcVertex1.z; float farPlane = -ndcVertex2.z; float leftPlane = ndcVertex1.x; float rightPlane = ndcVertex2.x; float bottomPlane = ndcVertex1.y; float topPlane = ndcVertex2.y; ``` 以上是一个简单的计算相机视锥的代码示例。一般来说,还可以根据需要添加更多功能,例如视锥的可视体积、剔除不可见的物体等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值