将Point3D转换为Screen2D在three.js中得到错误的结果

时间:2015-04-23 07:05:43

标签: matrix 3d three.js project

我在three.js 69中使用这样的函数

  function Point3DToScreen2D(point3D,camera){
    var p = point3D.clone();
    var vector = p.project(camera);

    vector.x = (vector.x + 1) / 2 * window.innerWidth;
    vector.y = -(vector.y - 1) / 2 * window.innerHeight;

    return vector;

  }

当我保持场景静止时,它工作正常。 但是当我旋转场景时,它会出错,并在屏幕上返回错误的位置。当我旋转180度时会发生这种情况。它显示屏幕上没有位置但是显示出来。

我在var tmpV=Point3DToScreen2D(new THREE.Vector3(-67,1033,-2500),camera);中设置了一个位置update并用css3d显示它。当我旋转180度但小于360度时,该点再次显示在屏幕上。显然它是' sa错误的位置,可以从现场打电话,我没有360度旋转。

我对Matrix知之甚少,所以我不知道project是如何运作的。

以下是three.js中project的来源:

project: function () {

        var matrix;

        return function ( camera ) {

            if ( matrix === undefined ) matrix = new THREE.Matrix4();

            matrix.multiplyMatrices( camera.projectionMatrix, matrix.getInverse( camera.matrixWorld ) );
            return this.applyProjection( matrix );

        };

    }()

matrix.getInverse( camera.matrixWorld )是多余的吗?我试图删除它,但它没有工作。 任何人都可以帮助我吗?谢谢。

4 个答案:

答案 0 :(得分:2)

您正在使用类似这样的图案将3D点从世界空间投射到屏幕空间:

var vector = new THREE.Vector3();
var canvas = renderer.domElement;

vector.set( 1, 2, 3 );

// map to normalized device coordinate (NDC) space
vector.project( camera );

// map to 2D screen space
vector.x = Math.round( (   vector.x + 1 ) * canvas.width  / 2 ),
vector.y = Math.round( ( - vector.y + 1 ) * canvas.height / 2 );
vector.z = 0;

然而,使用这种方法,相机背后的点也会被投射到屏幕空间。

你说你想过滤掉相机背后的点。为此,您可以先使用此模式:

var matrix = new THREE.Matrix4(); // create once and reuse

...

// get the matrix that maps from world space to camera space
matrix.getInverse( camera.matrixWorld );

// transform your point from world space to camera space
p.applyMatrix( matrix );

由于相机位于相机空间的原点,并且由于相机始终向下看相机空间中的负z轴,因此相机后面的点将具有大于零的z坐标。

// check if point is behind the camera
if ( p.z > 0 ) ...

three.js r.71

答案 1 :(得分:0)

与上面的示例类似,但您可以检查vector.z以确定它是否在前面。

var vector = new THREE.Vector3();
var canvas = renderer.domElement;

vector.set( 1, 2, 3 );

// map to normalized device coordinate (NDC) space
vector.project( camera );

// map to 2D screen space
vector.x = Math.round( (   vector.x + 1 ) * canvas.width  / 2 ),
vector.y = Math.round( ( - vector.y + 1 ) * canvas.height / 2 );

//behind the camera if z isn't in 0..1 [frustrum range]
if(vector.z > 1){
   vector = null;
}

答案 2 :(得分:0)

深入研究此答案:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:util="http://www.springframework.org/schema/util"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-3.0.xsd
           http://www.springframework.org/schema/mvc
           http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd"
       default-autowire="byName">

    <!-- 防止@ResponseBody出现的中文乱码 -->
    <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
        <property name="messageConverters">
            <list>
                <bean class="org.springframework.http.converter.ByteArrayHttpMessageConverter"/>
                <bean class="org.springframework.http.converter.StringHttpMessageConverter">
                    <property name="supportedMediaTypes">
                        <list>
                            <value>text/plain;charset=UTF-8</value>
                            <value>text/json;charset=UTF-8</value>
                            <value>text/xml;charset=UTF-8</value>
                        </list>
                    </property>
                </bean>
                <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"/>
                <bean class="org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter"/>
                <bean class="org.springframework.http.converter.ResourceHttpMessageConverter"/>
            </list>
        </property>
    </bean>

   

    <!-- 防止@ResponseBody出现的中文乱码 -->
    <!-- 启动Spring MVC的注解功能,完成请求和注解POJO的映射 -->
    <mvc:resources location="/static/" mapping="/static/**"/>
    <mvc:annotation-driven/>
    <context:component-scan base-package="org.format.demo.controller" />


    <!--
    <import resource="classpath:springConfig/viewConfig/jsp.xml"/>
    -->
    <import resource="classpath:springConfig/viewConfig/freemarker.xml"/>


</beans>
  

这不是事实。映射不连续。点远   平面也映射到大于1的z值

投影向量的z值代表什么? X和Y在规范化的剪贴空间[-1,1]中,那么z呢?

这是真的吗?

// behind the camera if z isn't in 0..1 [frustrum range]
if(vector.z > 1){
   vector = null;
}

答案 3 :(得分:0)

由于摄影机位于摄影机空间的原点,并且由于摄影机始终在摄影机空间中向下看z轴,因此摄影机后面的点的z坐标将大于1。

//check if point is behind the camera
if ( p.z > 1 ) ...

注意:如果满足此条件,则投影坐标必须是中心对称的

{x: 0.233, y: -0.566, z: 1.388}
// after transform
{x: -0.233, y: 0.566, z: 1.388}