【问题标题】:OpenGl translate the world after camera rotationOpenGL在相机旋转后翻译世界
【发布时间】:2016-08-21 19:46:23
【问题描述】:

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

    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);
    }

一个网格类和它的draw void是:

    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());

【问题讨论】:

  • 您能否发布一些有关如何尝试旋转相机视图矩阵和平移模型矩阵的代码。
  • 最后一次编辑似乎你有行而不是列顺序。那么你需要行而不是列。对此感到抱歉,我认为 Android 矩阵已转置,但您的情况似乎并非如此。

标签: android matrix opengl-es


【解决方案1】:

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

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

现在,具有旋转和平移的矩阵运算就像在第一人称视角下一样工作。例如,围绕 X 旋转(向上或向下)意味着围绕 right 旋转 upforward。向量的翻译(x,y,z)表示position += (x*right, y*up, z*forward),涵盖了你常用的大部分矩阵工具。

现在要了解您想要根据视图矩阵平移对象的具体情况:您需要使用相机基向量来平移位置。因此,要通过屏幕坐标(x,y) 翻译它,请使用model.position += (camera.right.x*x, camera.up.y*y)。例如,要根据视图围绕 X 旋转它,您需要围绕 camera.x 旋转模型 model.forwardmodel.upmodel.right 的所有基本向量...

【讨论】:

  • 很好的解释,我能理解理论但不幸的是我不能应用它。
  • 似乎有什么问题?
  • 此过程希望您使用它而不是矩阵并从中生成矩阵。在最后一行中,如果几何矩阵的修改超出平移(旋转或缩放),那么这将不起作用。我也不确定这些列方法的作用,但你可以尝试一些测试。对于作为身份的视图矩阵,你期望 right(1,0,0), up(0,1,0) 我希望你从身份中看到模式矩阵。然后尝试将其旋转 90 度,看看值是否正确。我也希望矩阵在 Android 上转置,否则你需要行而不是列。
  • 你的答案是正确的,我会研究它并有更多的阅读。谢谢
  • 这是关键“此过程希望您使用它而不是矩阵并从中生成矩阵”
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-06-07
  • 1970-01-01
  • 2014-11-21
  • 2013-08-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多