2013-02-16 17 views
6

私は、そのマップに惑星全体を使用するゲームを作っています。私は球状の惑星using this techniqueをテッセレーションして、今カメラコントロールで追加しています。カメラをポイントに回転

球の大きさは1から-1です。したがって、球上の各点も正規化されたベクトルになります。一度に、球を構成する六角形のタイルの1つが「選択された」タイルです。プレーヤーは、dパッドを使用して選択範囲を隣接するタイルに移動することができます。また、アナログスティックを使用してカメラを独立して回転させることもできます。

選択したタイルとカメラに関連して2つのことを行う必要があります。まず、選択範囲をカメラに最も近いタイルに切り替える必要があります。次に、ハイライトされたタイルの上にカメラを配置する必要があります。

球が原点に位置し、カメラがポイント(0,0,1)に座ります。グラフィックエンジンでは、カメラをX軸とY軸の周りで回転させることしかできないので、最初の問題を解決するために、xとy軸の周りの点(0,0,1)を回転させて

private Quaternion quat = new Quaternion(0,0,0,0); 
    private double[] output = new double[4]; 
    private double[] cam = new double[3]; 

    private double camX = 0; 
    private double camY = 0; 
    private double camZ = 1; 


    private double[] getCamPosition(){ 

     quat.setAxisAngle(1, 0, 0, Math.toRadians(-graphicsEngine.getRotationX())); 
     quat.RotateVector(camX, camY, camZ, output);    
     cam[0] = output[0]; 
     cam[1] = output[1]; 
     cam[2] = output[2]; 

     quat.setAxisAngle(0, 1, 0, Math.toRadians(-graphicsEngine.getRotationY())); 
     quat.RotateVector(cam[0], cam[1], cam[2], output);   
     cam[0] = output[0]; 
     cam[1] = output[1]; 
     cam[2] = output[2]; 

     return cam; 
    } 

Iは、各タイルの重心とカメラ位置の間の距離を比較し、新たに選択されたタイルであることが最も近いタイルを取る:カメラは3D空間。

しかし、第2の問題を解決するために、私はその逆をしたいと思います。重心(これは既に正規化されたベクトルの形をしています)を取り出して、Xの回りの回転とYを中心とする回転を見つけて、カメラを中央に置く必要があります。

現時点ではカメラを(0,0,1)に戻してからX軸とY軸の角度を(0,0,1)と重心の間で取得し、それを使用してカメラをもう一度回転させます:

private double[] outputArray = new double[2]; 

/** 
* Cam is always (0,0,1) 
*/ 
public void centreOnSelected(double camX, double camY, double camZ){   

    selectedTile.getCentroidAngles(outputArray); 

    outputArray[0] -= Math.atan2(camZ, camY); 
    outputArray[1] -= Math.atan2(camX, camZ); 

    // this determines if the centroid is pointing away from the camera 
    // I.e. is on the far side of the sphere to the camera point (0,0,1) 
    if(!selected.getCentroidDirectionY(camX, camZ)){ 
     outputArray[0] = -Math.PI - outputArray[0];   
    } 

    graphicsEngine.rotateCam(Math.toDegrees(outputArray[0]), Math.toDegrees(outputArray[1])); 


} 

selected(タイルクラス)で

void getCentroidAngles(double[] outputArray){ 
    outputArray[0] = Math.atan2(centroidZ, centroidY); 
    outputArray[1] = Math.atan2(centroidX, centroidZ); 

} 

問題はこれです(x軸は常に外に出ているように見えます)、角度を取得して回転させる数学と関係していると確信しています。

注:グラフィックスエンジンは、その後、Yの周りのX軸、:

 gl.glRotatef(mRotateX, 1, 0, 0); 
     gl.glRotatef(mRotateY, 0, 1, 0); 

重心がすべて正しい場所にあり、カメラは間違いなく正しい量だけ回転し、ので、私はこの問題は、グラフィックスエンジンではないと確信しています。私は、これはプログラム

をステップ実行することで動作確認されてきたように、それが戻って(0,0,1)にも、カメラの再配置ではありません、私はこの問題を説明するためにビデオをも作った:

http://www.youtube.com/watch?v=Uvka7ifZMlE

これは数日間私を悩ませていますので、これを解決するための助けがあれば幸いです!

おかげ ジェームズ

答えて

2

は、残念ながら、私は完全にここで何が起こっているのか理解していない、との完全なソリューションを提供することはできませんが、少なくとも見ていくつかの問題を指摘することができます。

私はglRotatefを一度も使ったことはありませんが、ここでは変換の順序と記号について混乱しています。たとえば、glRotatef呼び出しの順番で最初にx回転を行っていますか?あなたが最初のもので(centroidY, centroidZ)を意味した

とにかく、問題の少なくとも一部は、ここでは、これらの式

まず
outputArray[0] = Math.atan2(centroidZ, centroidY); 
outputArray[1] = Math.atan2(centroidX, centroidZ); 

から来ていますか?もっと真剣に、あなたがここに到達する角度は、(0,0,1)を重心に運ぶ回転を構築するために使用することはできず、その逆もありません。たとえば、セントロイドベクトルを(0,0,1)に回転させたいとします。 2つの回転のそれぞれを個別に使用して、単一の軸を中心に回転させて、1つの成分をゼロに設定することができます。例えば、outputArray[0]による適切な符号のx軸周りの回転は、y成分を0に設定する(atan2への引数が入れ替えられたと仮定して)。あるいは、y軸の右の符号をoutputArray[1]で回転させると、x成分は0に設定されます。しかし、まずx回転を行ってy成分を0に設定した後、重心ベクトルが変化します。 x成分を0に設定するメソッドは、もはやoutputArray[1]によって記述されません。

これらの適切な式は、常に一方の角度がatan2、他方がacosまたはasinです。たとえば、あなたは(x,y,z)上にベクトル(1,0,0)を運ぶアクティブな回転のための角度はあなたがこれらの角度は周りの回転を記述します(

first_angle_around_x = atan2(y, z) 
second_angle_around_y = -asin(x) 

使用することになり(1,0,0)(x,y,z)を実施するために

first_angle_around_x = -asin(y) 
second_angle_around_y = atan2(x, z) 

を使用したい場合は、軸が「あなたを目の当たりにしている」と反時計回りのx軸、y軸)。

もう一つの問題はここにあります

outputArray[0] -= Math.atan2(camZ, camY); 
outputArray[1] -= Math.atan2(camX, camZ); 

このような角度を差し引くと、1つの軸の周りの回転にのみ作用します。いったん異なる軸の周りの回転から合成変換を構築すると、関係ははるかに複雑になります。そのため、行列と四元数が便利になります。 CamX-Z入力がメソッドの前のコメントで示唆されているように重複している場合は、このコードは問題にならないかもしれません(ただし、ZおよびYコンポーネントを使用している間に、私が言及した最初の方程式でそれらが「間違った」方法であることを補う;これが意図的であるかどうかわからない)。

カメラを選択したタイルに移動する方法にも根本的な問題がありますが、実際に問題があるかどうかは少し主観的です。あなたはx軸とy軸の周りだけで回転するので、あなたの惑星上の各点に固有のカメラ方向があります。問題は、このような向きを連続的に選ぶ方法がないことです。これは、惑星上のベクトル場を想像すると、各点のベクトルは、カメラがその点よりも上にあるときに画面x方向に沿っている単位ベクトルです。このフィールドはHairy Ball Theoremによって継続することはできません。これが実際に何を意味するかということは、カメラの位置を少し調整したようなものを作ることによって、惑星の周りに画面上で180度までの周りの車輪が作られるという惑星上の点があることです。これを避けたい場合は、回転量を最小限に抑えるために、現在のカメラの位置に基づいて向きを選択することができます。例えば、あなたのゲームでは望ましくない可能性のある閉ループでカメラが動いた場合、惑星が画面上で「回転」することがあります。また、エンジンが3軸全てで回転できることが必要です。

+0

面白い、ありがとう!私は周りの車輪で理解していますが、私はそれが名前を持っていたことは決して実現しませんでした(はるかに少なく、毛むくじゃらのボール定理として陽気な)。このホイール動作は、私がプレイしたコンピュータゲームでは珍しいことではなく、おそらくゲームをプレイするときにわずかなグラフィカルな迷惑になります。私はセンタリングを落とさなければならないと思うが、当面は重心にカメラを回転させる必要がある –

関連する問題