2017-07-12 3 views
0

Irrlichtエンジンを使用してフリーフロー2Dラスタ画像を空間に配置する関数を作成したいと考えています。これのインスピレーションは、Rパッケージrglの関数rgl::show2dです。 Rの実装例はhereです。Irrlicht:4つのコーナー座標に基づいて3D空間に2D画像を描画する

chewie in space

入力データは、画像へのパスと、各プロット矩形の四隅の座標テーブルに限定されるべきです。

イルリヒトでこれを実現するための私の最初の、かなり原始的かつ最終的には失敗したアプローチ:

キューブを作成します。

ISceneNode * picturenode = scenemgr->addCubeSceneNode(); 

は片側フラット化:

picturenode->setScale(vector3df(1, 0.001, 1)); 

をテクスチャとして画像を追加します。

picturenode->setMaterialTexture(0, driver->getTexture("path/to/image.png")); 

4つのコーナー座標の中央の位置にフラットキューブを配置します。私はちょうど小さな関数position_calc()で3つの軸すべての平均座標を計算します。

vector3df position = position_calc(rcdf); picturenode->setPosition(position); 

、四隅の座標によって定義される平面の法線を計算し、結果を正規化し、何とか回転角度に得られたベクターを変換しようとすることで、オブジェクトの回転を決定します。

vector3df normal = normal_calc(rcdf); 
vector3df angles = (normal.normalize()).getSphericalCoordinateAngles(); 
picturenode->setRotation(angles); 

このソリューションでは、期待した結果が得られません。回転計算が間違っています。このアプローチでは、画像をコーナー座標に正確に拡大することもできません。

ワークフローを修正するにはどうすればよいですか?それとも、私が気付いていないイルリヒトでこれを達成するためのより良い方法がありますか?


編集:私は、私はほとんどそこだと信じて@spugに感謝。私はquaternionsが既にIrrlichtで利用可能であるため、彼の方法2を実装しようとしました。ここで私は回転を計算するために思い付いたものです:

#include <Rcpp.h> 
#include <irrlicht.h> 
#include <math.h> 

using namespace Rcpp; 

core::vector3df rotation_calc(DataFrame rcdf) { 

    NumericVector x = rcdf["x"]; 
    NumericVector y = rcdf["y"]; 
    NumericVector z = rcdf["z"]; 

    // Z-axis 
    core::vector3df zaxis(0, 0, 1); 
    // resulting image's normal 
    core::vector3df normal = normal_calc(rcdf); 

    // calculate the rotation from the original image's normal (i.e. the Z-axis) 
    // to the resulting image's normal => quaternion P. 
    core::quaternion p; 
    p.rotationFromTo(zaxis, normal); 

    // take the midpoint of AB from the diagram in method 1, and rotate it with 
    // the quaternion P => vector U. 
    core::vector3df MAB(0, 0.5, 0); 
    core::quaternion m(MAB.X, MAB.Y, MAB.Z, 0); 
    core::quaternion rot = p * m * p.makeInverse(); 
    core::vector3df u(rot.X, rot.Y, rot.Z); 

    // calculate the rotation from U to the midpoint of DE => quaternion Q 
    core::vector3df MDE(
     (x(0) + x(1))/2, 
     (y(0) + y(1))/2, 
     (z(0) + z(1))/2 
); 
    core::quaternion q; 
    q.rotationFromTo(u, MDE); 

    // multiply in the order Q * P, and convert to Euler angles 
    core::quaternion f = q * p; 
    core::vector3df euler; 
    f.toEuler(euler); 

    // to degrees 
    core::vector3df degrees(
    euler.X * (180.0/M_PI), 
    euler.Y * (180.0/M_PI), 
    euler.Z * (180.0/M_PI) 
); 

    Rcout << "degrees: " << degrees.X << ", " << degrees.Y << ", " << degrees.Z << std::endl; 

    return degrees; 
} 

結果はほとんど正しいのですが、1つの軸上の回転が間違っています。これを修正する方法はありますか、実装に本質的に欠陥がありますか?

これは、今の結果です。ポイントは予想されるコーナーポイントをマークします。私はこれを行うには、2つの方法を考えてきました

berries in space

+1

何が 'rcdf'ですか? – meowgoesthedog

+0

私は[Rcpp](https://cran.r-project.org/web/packages/Rcpp/index.html)フレームワークを使用しています。これはDataFrameオブジェクトで、この場合は3列4行のテーブルを表します。 4つのコーナーポイントのx、y、z座標。申し訳ありません - 私はこれを記述するのを忘れました。 – nevrome

+0

これの問題は、* 2 *球座標の角度だけです。 'normal'の周りの画像の回転を指定するのに3番目が必要です。これはロールと呼ばれます。あなたは少なくとも、正しい方向を指すように画像*平面を得ることができますか? – meowgoesthedog

答えて

1

。どちらも非常に優雅ではありません - 私たちを球面の極に制限するIrrlichtによって助けられません。

NB。以下はrcdfが原点の中心にあると仮定しています。これは、回転計算を少し簡単にするためです。しかし修正が簡単:追加

  • 以下の手順を実行しrcdf
  • 減算の

    1. 計算中心点(オフセット翻訳を)このrcdf
    2. のすべてのポイントからの結果に戻ってオフセットポイント。

    前提条件の:スケーリングは

    これは簡単です。 rcdfの幅と高さの比率を元の画像に単純に換算してからsetScalingに電話してください。

    enter image description here


    方法1:このため、逆行列

    イルリヒトだけ(私は信じている)4×4を持っているので、我々は、3×3行列をサポートしている外部ライブラリを必要としています。

    イメージをX-Yからrcdfに回転させる行列式を解く必要があります。このためには、各フレームに 3点が必要です。これらのうちの2つはすぐにに隣接してイメージのコーナーのに設定することができます。 (完全な基底を形成するために3次元のデータが必要なので)3次元は画像の平面を指し示す必要があります。計算するために、各画像の法線にオフセット定数(例えば1)を掛けてください。

    enter image description here

    解決するための式はことである(スケーリングされた原画像上の点に注意してください):

    enter image description here

    (列表記を使用して)。 Eigenライブラリは、3x3行列と逆行列の実装を提供しています。そして

    球面極座標角度にこのマトリックスを変換:https://www.learnopencv.com/rotation-matrix-to-euler-angles/


    方法2:

    Bの方向ベクトルAから回転する四元を計算する:Finding quaternion representing the rotation from one vector to another

    1. 元の画像の回転を計算する通常すなわち、 Z軸)をrcdfのnormal => quaternion Pに設定します。

    2. は、方法1における図からAB中点を取り、四元Phttp://www.geeks3d.com/20141201/how-to-rotate-a-vertex-by-a-quaternion-in-glsl/)=>ベクターUと一緒に回転します。

    3. ためQ * PUからDE =>四元Q

    4. 乗算の中間点に回転を計算し、オイラーへの変換は、角度:https://en.wikipedia.org/wiki/Conversion_between_quaternions_and_Euler_angles

    場合(わかりませんIrrlichtは四元数をサポートしています)

  • +0

    私は方法2を実装しようとしました。それを見て何が残念ながら私のアプローチではエラーがあります。 – nevrome

    +0

    @nvromeこんにちは遅れて申し訳ありません。なぜダイアグラムに6点ありますか?私は下のポリゴンが最終結果であると仮定しますか? – meowgoesthedog

    +0

    @nevrome ah私はちょうど実現しました - 答えは 'rcdf'が原点の中心にあると仮定していますが、あなたの' rcdf'は翻訳オフセットを持っています。しかしこれを修正するのはかなり簡単です - あらかじめ中心を計算し、それを 'rcdf'の点から減算し、計算して、それを元に戻してください。私は* normal *計算がこの平行移動の影響を受けないので、これが不正確な角度を引き起こしていると思うので、最終平面は正しくなりますが、面内方向ではありません。 – meowgoesthedog

    関連する問題