使用 THREE.Frustum 计算近/远平面顶点 [英] Calculate near/far plane vertices using THREE.Frustum

查看:14
本文介绍了使用 THREE.Frustum 计算近/远平面顶点的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要一些帮助来处理 THREE.Frustum 对象.

I need some help to deal with THREE.Frustum object.

我的问题:

我需要计算近/远平面的顶点;我看过这些教程

I need to calculate near/far plane vertices; I've taken a look at these tutorials

  1. http://www.lighthouse3d.com/tutorials/view-frustum-culling/view-frustums-shape/
  2. http://www.lighthouse3d.com/tutorials/view-frustum-culling/geometric-approach-extracting-the-planes/

并且我已经勾画了这个函数,它完全(我希望如此)实现了所解释的过程(只是为了获得左上/右上顶点,假设相机只能向左和向右看):

and I've sketched this function implementing exactly (I hope so) the procedure explained (just to get top-left/right vertices, assuming the camera can only look left and right):

        // Near Plane dimensions
        hNear = 2 * Math.tan(camera.fov / 2) * camera.near; // height
        wNear = hNear * camera.aspect; // width

        // Far Plane dimensions
        hFar = 2 * Math.tan(camera.fov / 2) * camera.far; // height
        wFar = hFar * camera.aspect; // width

getVertices : function() {
        var p = camera.position.clone();
        var l = getCurrentTarget(); // see below
        var u = new THREE.Vector3(0, 1, 0);

        var d = new THREE.Vector3();
        d.sub(l, p);
        d.normalize();

        var r = new THREE.Vector3();
        r.cross(u, d);
        r.normalize();

        // Near Plane center
        var dTmp = d.clone();
        var nc = new THREE.Vector3();
        nc.add(p, dTmp.multiplyScalar(camera.near));

        // Near Plane top-right and top-left vertices
        var uTmp = u.clone();
        var rTmp = r.clone();
        var ntr = new THREE.Vector3();
        ntr.add(nc, uTmp.multiplyScalar(hNear / 2));
        ntr.subSelf(rTmp.multiplyScalar(wNear / 2));

        uTmp.copy(u);
        rTmp.copy(r);
        var ntl = new THREE.Vector3();
        ntl.add(nc, uTmp.multiplyScalar(hNear / 2));
        ntl.addSelf(rTmp.multiplyScalar(wNear / 2));

        // Far Plane center
        dTmp.copy(d);
        var fc = new THREE.Vector3();
        fc.add(p, dTmp.multiplyScalar(camera.far));

        // Far Plane top-right and top-left vertices
        uTmp.copy(u);
        rTmp.copy(r);
        var ftr = new THREE.Vector3();
        ftr.add(fc, uTmp.multiplyScalar(hFar / 2));
        ftr.subSelf(rTmp.multiplyScalar(wFar / 2));

        uTmp.copy(u);
        rTmp.copy(r);
        var ftl = new THREE.Vector3();
        ftl.add(fc, uTmp.multiplyScalar(hFar / 2));
        ftl.addSelf(rTmp.multiplyScalar(wFar / 2));

getCurrentTarget : function() {
        var l = new THREE.Vector3(0, 0, -100);
        this.camera.updateMatrixWorld();
        this.camera.matrixWorld.multiplyVector3(l);
        return l;
    }

这似乎有效,但是...

This seems to work but...

我的问题:

我可以使用 THREE.Frustum 对象以更优雅(可能更正确)的方式获得相同的结果吗?

Can I obtain the same result in a more elegant (maybe more correct) way, using a THREE.Frustum object?

推荐答案

Three.Frustum 并不能真正帮助您——它是一组平面.好消息是您的解决方案看起来是正确的,但有一个更简单的方法来考虑这个问题.

Three.Frustum is not really going to help you -- it is a set of planes. The good news is your solution appears correct, but there is an easier way to think about this.

近平面的右上角是相机空间中具有以下坐标的点:

The upper right corner of the near plane is a point in camera space with these coordinates:

var ntr = new THREE.Vector3( wNear / 2, hNear / 2, -camera.near );

使用您对 wNearhNear 的定义,这是正确的.

using your definition of wNear and hNear, which are correct.

现在,确保 camera.matrixWorld 已更新,您可以像这样将该点转换为世界坐标:

Now, making sure that camera.matrixWorld is updated, you convert that point to world coordinates like so:

camera.updateMatrixWorld();
ntr.applyMatrix4( camera.matrixWorld );

现在,翻转标志以获得其他三个角,然后对远平面重复计算.

Now, flip the signs to get the other three corners, and then repeat the calculation for the far plane.

看,你说得对;你只是走了一条更复杂的路线.:-)

See, you had it right; you just took a more complicated route. :-)

更新为three.js r.66

updated to three.js r.66

这篇关于使用 THREE.Frustum 计算近/远平面顶点的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆