0

私は、車両の上面図と車両の速度に対するカメラのズームを備えたandroid opengl1.12dゲームを心配しています。速度が上がると、カメラがズームアウトして、プレーヤーに最高の道路の視認性を提供します。

スプライトが表示されているかどうかを正確に検出する方法を見つけるのに、彼の位置と現在のカメラのズームに関して少し問題があります。

重要な精度です。私のゲームのオブジェクトはすべて同じz座標上にあります。私はカメラ効果のためだけに3dを使用します。(それが私が錐台の複雑な計算を必要としない理由です)

これが私のGLSurfaceView.Rendererクラスのサンプルです

public static float fov_degrees =  45f;
public static float fov_radians =  fov_degrees / 180 * (float) Math.PI;
public static float aspect; //1.15572 on my device
public static float camZ;  //927 on my device



@Override
public void onSurfaceChanged(GL10 gl, int x, int y) {

    aspect =  (float) x / (float) y;
    camZ = y / 2 / (float) Math.tan(fov_radians / 2);

    Camera.MINIDECAL = y / 4;   // minimum cam zoom out (192 on my device)

    if (x == 0) { // Prevent A Divide By Zero By
        x = 1; // Making Height Equal One
    }
    gl.glViewport(0, 0, x, y); // Reset The Current Viewport
    gl.glMatrixMode(GL10.GL_PROJECTION); // Select The Projection Matrix
    gl.glLoadIdentity(); // Reset The Projection Matrix

    // Calculate The Aspect Ratio Of The Window
    GLU.gluPerspective(gl, fov_degrees, aspect , camZ / 10, camZ * 10);

    GLU.gluLookAt(gl, 0, 0, camZ, 0, 0, 0, 0, 1, 0); // move camera back


    gl.glMatrixMode(GL10.GL_MODELVIEW); // Select The Modelview Matrix

    gl.glLoadIdentity(); // Reset The Modelview Matrix

カメラの相対オブジェクトを描画するときは、次の変換方​​法を使用します。

gl.glTranslatef(position.x - camera.centerPosition.x , position.y -camera.centerPosition.y , - camera.zDecal);

すべてが正常に表示されます。問題は、オブジェクトが表示されているかどうかを確認するときの私の物理スレッドに起因します。

public static boolean isElementVisible(Element element) {

    xDelta =  (float) ((camera.zDecal + GameRenderer.camZ) * GameRenderer.aspect *  Math.atan(GameRenderer.fov_radians));
    yDelta = (float) ((camera.zDecal + GameRenderer.camZ)*   Math.atan(GameRenderer.fov_radians));

    //(xDelta and yDelta are in reallity updated only ones a frame or when camera zoom change)

    Camera camera = ObjectRegistry.INSTANCE.camera;

    float xMin = camera.centerPosition.x - xDelta/2;
    float xMax = camera.centerPosition.x + xDelta/2;

    float yMin = camera.centerPosition.y - yDelta/2;
    float yMax = camera.centerPosition.y + yDelta/2;

    //xMin and yMin are supposed to be the lower bounds x and y of the visible plan
    // same for yMax and xMax

    // then i just check that my sprite is visible on this rectangle.


    Vector2 phD = element.getDimToTestIfVisibleOnScreen();
    int sizeXd2 = (int) phD.x / 2;
    int sizeYd2 = (int) phD.y / 2;


    return (element.position.x + sizeXd2 > xMin)
            && (element.position.x - sizeXd2 < xMax)
            && (element.position.y - sizeYd2 < yMax)
            && (element.position.y + sizeYd2 > yMin);


}

残念ながら、オブジェクトはすぐに消えて遅く見えたので、テスト目的でカメラにズームアウトを手動で追加しました。

手動テストを行ったところ、xDeltaとyDeltaを計算するときにカメラのzインデックスに約260を追加することで、問題がないことがわかりました。したがって、行は次のようになります。

xDelta =  (float) ((camera.zDecal + GameRenderer.camZ + 260) * GameRenderer.aspect *  Math.atan(GameRenderer.fov_radians));
yDelta = (float) ((camera.zDecal + GameRenderer.camZ + 260)*   Math.atan(GameRenderer.fov_radians));

これはハックであり、マジックナンバーがすべてのデバイスで機能するとは限らないため、私が見逃したものを理解したいと思います。その「260」のマジックナンバーには、視野または配給の幅/高さから得られ、ピクセルの完全な検出のための数式パラメータとして設定できるものがあると思います。

何か推測?

4

1 に答える 1

0

私の推測では、Math.tan(GameRenderer.fov_radians)の代わりに使用する必要がありMath.atan(GameRenderer.fov_radians)ます。

理由:

視野角が 90 度のカメラを使用した場合、xDeltayDeltaは無限に大きくなるはずですよね? カメラは無限平面全体を表示する必要があるためです。

tan(pi/2) は無限大 (および負の無限大) です。atan(pi/2) は単に 1.00388...

tan(pi/4) は 1 ですが、atan(pi/4) は 0.66577...

于 2013-01-22T23:54:00.233 に答える