OpenGl在镜头旋转后翻译世界

时间:2016-08-21 19:46:24

标签: android matrix opengl-es

我有一个基本问题我想用触摸事件翻译所有对象(世界)问题是如果视图矩阵被旋转我无法计算模型矩阵平移以正确方向移动,我想翻译x和z轴。 我需要数学逻辑。 我有一个相机类,它的绘制空白是:

    public void draw() {
        Matrix.setIdentityM(viewMatrix, 0);
        setLookAtM(viewMatrix, 0, position.getX(), position.getY(), position.getZ(), lookAt.getX(), lookAt.getY(), lookAt.getZ(), 0f, 1f, 0f);

        Matrix.setIdentityM(mCurrentRotation, 0);       
        Matrix.rotateM(mCurrentRotation, 0, mDeltaX, 0.0f, 1.0f, 0.0f);
        Matrix.rotateM(mCurrentRotation, 0, mDeltaY, 1.0f, 0.0f, 0.0f);     
        mDeltaX = 0.0f;
        mDeltaY = 0.0f;
        float[] mTemporaryMatrix = new float[16];
        Matrix.multiplyMM(mTemporaryMatrix, 0, mCurrentRotation.clone(), 0, mAccumulatedRotation, 0);
        System.arraycopy(mTemporaryMatrix, 0, mAccumulatedRotation, 0, 16);

        Matrix.multiplyMM(mTemporaryMatrix, 0, viewMatrix, 0, mAccumulatedRotation, 0);
        System.arraycopy(mTemporaryMatrix, 0, viewMatrix, 0, 16);
    }

和一个网格类及其绘制空格是:

    public void draw(float mDeltaX, float mDeltaY) {
        Matrix.setIdentityM(getMatrix().getFloatArray(), 0);
        multiplyMM(getMatrix().getFloatArray(), 0, containerMatrix.getFloatArray(), 0, geometry.getMatrix().getFloatArray(), 0);
        multiplyMM(modelViewMatrix, 0, this.getScene().getCamera().getViewMatrix(), 0, getMatrix().getFloatArray(), 0);

        Matrix.setIdentityM(mCurrentTranslation, 0);
        Matrix.translateM(mCurrentTranslation, 0,  -mDeltaX,  0,  -mDeltaX);
        float[] mTemporaryMatrix = new float[16];
        Matrix.multiplyMM(mTemporaryMatrix, 0, mCurrentTranslation.clone(), 0, mAccumulatedRotation, 0);
        System.arraycopy(mTemporaryMatrix, 0, mAccumulatedRotation, 0, 16);
        Matrix.multiplyMM(mTemporaryMatrix, 0, modelViewMatrix, 0, mAccumulatedRotation, 0);
        System.arraycopy(mTemporaryMatrix, 0, modelViewMatrix, 0, 16);

        this.getScene().getShaderProgram().setUniforms(modelViewMatrix, this.getScene().getCamera().getProjectionMatrix(), material.getTextureid(), material.getMaterialColor(), material.getEmissiveColor(), material.getShinines());
        geometry.getDataBuffer().bindData(this.getScene().getShaderProgram());
        glDrawArrays(GL_TRIANGLES, 0, geometry.getDataBuffer().getVerticesCount());
    }

onTouchEvent是:

        if (event.getAction() == MotionEvent.ACTION_MOVE) {
            if (mainRenderer != null) {
                if(event.getPointerCount()==1){
                    float deltaX = (x - mPreviousX) / mDensity / 2f;
                    float deltaY = (y - mPreviousY) / mDensity / 2f;
                    mainRenderer.getCamera().mDeltaX += deltaX;
                    mainRenderer.getCamera().mDeltaY += deltaY;
                }
                else if(event.getPointerCount()==2){
                    float deltaX = (x - mPreviousX) / mDensity / 2f;
                    float deltaY = (y - mPreviousY) / mDensity / 2f;
                    mainRenderer.getScene().mDeltaX += deltaX;
                    mainRenderer.getScene().mDeltaY += deltaY;
                }
            }
        }

相机可以很好地旋转,但我无法将对象转换为与视图矩阵相关的方向。

我做了以下代码

    Vector3 camPos=new Vector3();
    camPos.setFromMatrixColumn(this.getScene().getCamera().getViewMatrix(),3);
    Vector3 camUp=new Vector3();
    camUp.setFromMatrixColumn(this.getScene().getCamera().getViewMatrix(),1);
    Vector3 camForward=new Vector3();
    camForward.setFromMatrixColumn(this.getScene().getCamera().getViewMatrix(),2);
    Vector3 camRight=new Vector3();
    camRight.setFromMatrixColumn(this.getScene().getCamera().getViewMatrix(),0);
    translateM(geometry.getMatrix().getFloatArray(), 0, mDeltaX*camRight.getX(), 0, mDeltaY*camUp.getY());

但结果出乎意料,我知道这是不正确的,但我试着按照你的指示,从视图矩阵中获取位置,前进,上下,然后将事务应用于模型矩阵。

更新 这段代码接近正确的结果,但并不完美,我从视图矩阵中正确地获得了向上,向前,向右和位置

    Vector3 col1=new Vector3();
    col1.setFromMatrixColumn(this.getScene().getCamera().getViewMatrix(),3);
    Vector3 col2=new Vector3();
    col2.setFromMatrixColumn(this.getScene().getCamera().getViewMatrix(),1);
    Vector3 col3=new Vector3();
    col3.setFromMatrixColumn(this.getScene().getCamera().getViewMatrix(),2);
    Vector3 camUp=new Vector3(col1.getY(), col2.getY(), col3.getY());
    Vector3  camForward=new Vector3(col1.getZ(), col2.getZ(), col3.getZ());
    Vector3 camRight=new Vector3(col1.getX(), col2.getX(), col3.getX());
    camRight.setFromMatrixColumn(this.getScene().getCamera().getViewMatrix(),0);
    translateM(geometry.getMatrix().getFloatArray(), 0, mDeltaX*camRight.getX(),0,mDeltaY*camForward.getZ());

1 个答案:

答案 0 :(得分:1)

如果我正确理解您的问题,您将需要更好的系统,然后直接使用矩阵。问题是如果你想将物体从相机移开,你需要知道相机实际面对的方式。这实际上可以通过获取视图矩阵的第3列来完成矩阵,该第3列表示当前视图方向的Z轴(这是您面向的方式)。这有点复杂,难以使用,所以我建议您使用4个矢量(3个也可以),它们定义场景中对象的位置和方向,包括相机/用户。

为此,您应该构建一个包含向量positionforwardupright的类。向量right是可选的,因为您可以使用forwardup之间的叉积来构造它。现在,如果每个模型/对象都包含此类来定义其位置,则需要从中构造矩阵。您将需要2个过程,1个用于模型矩阵,另一个用于视图矩阵。要构建视图矩阵,您只需使用lookAt lookAt参数为position + forward的{​​{1}},而其余参数不应成为问题(向上为up,眼睛为position ...)所以这涵盖了相机。要构建模型矩阵,您可以简单地从向量生成它们,其中矩阵的左上角3x3部分表示基矢量,因此第一列是X轴right,第二列是up,第三个Z是forward。第4列是position,最后一行是(0,0,0,1)

现在,旋转和翻译的矩阵操作与第一人称视角一样。例如,围绕X旋转(向上或向下)意味着在up周围旋转forwardright。向量(x,y,z)的翻译意味着position += (x*right, y*up, z*forward),它涵盖了您习惯使用的大多数矩阵工具。

现在,根据您的视图矩阵,您需要转换对象:您需要使用相机基矢量转换位置。因此,要按屏幕坐标(x,y)进行翻译,请使用model.position += (camera.right.x*x, camera.up.y*y)。例如,根据您需要在model.forward周围旋转模型model.upmodel.rightcamera.x的所有基本向量所需的视图,将其围绕X旋转。 / p>