2017-07-12 117 views
0

我想創建一個函數,用Irrlicht引擎在空間中定位一個自由浮動的二維光柵圖像。靈感來自於R package rgl中的函數rgl::show2d。 R中的示例實現可以找到hereIrrlicht:基於四個角座標在三維空間中繪製二維圖像

chewie in space

輸入數據應當被限制於路徑圖像和與各情節矩形的四個角的座標的表格。

我的第一個,相當原始和最終失敗的方式與Irrlicht的認識到這一點:

創建一個立方體:

ISceneNode * picturenode = scenemgr->addCubeSceneNode(); 

拼合一面:

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

添加圖片作爲紋理:

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

將展平立方體放置在四個角座標的中心位置。我只用一個小函數position_calc()來計算所有三個軸上的平均座標。

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

通過計算正常由四個角落的座標限定的平面的,歸一化的結果,並試圖以某種方式翻譯所得的矢量來旋轉角度確定對象的旋轉。

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

此解決方案不會產生預期結果。旋轉計算錯誤。採用這種方法,我也無法正確地將圖像縮放到角點座標。

我該如何解決我的工作流程?或者有沒有更好的方法來實現Irrlicht,我不知道?


編輯:感謝@spug我相信,我幾乎沒有。我試圖實施他的方法2,因爲quaternions已經在Irrlicht中可用。以下是我想出了計算旋轉:

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

結果是幾乎正確的,但有一個軸的旋轉是錯誤的。有沒有辦法解決這個問題,或者是我的實現固有缺陷?

這就是現在的結果。分數標記預期的角點。

berries in space

+1

什麼是'rcdf'? – meowgoesthedog

+0

我正在使用[Rcpp](https://cran.r-project.org/web/packages/Rcpp/index.html)框架。它是一個DataFrame對象,表示 - 在這種情況下 - 一個包含3列和4行的表格。四個角點的x,y和z座標。對不起 - 我忘了描述這一點。 – nevrome

+0

這個問題是隻有*兩個*球面座標角度;你需要三分之一來指定圖像在「普通」周圍的旋轉 - 這叫做滾動。你是否至少能夠讓圖像*平面指向正確的方向? – meowgoesthedog

回答

1

我想過兩種方法來做到這一點;也不是非常優美 - Irrlicht沒有幫助我們限制球形。

注意:以下假定rcdf以原點爲中心;這是爲了使旋轉計算更直接一點。易雖然修復:這個從rcdf

  • 所有點

    1. 計算rcdf
    2. 減的中心點(平移偏移)執行以下
    3. 程序添加偏移回結果點。

    預備知識:縮放

    這是容易的;只需計算rcdf中的寬度和高度與原始圖像的比率,然後致電setScaling即可。

    enter image description here


    方法1:矩陣求逆

    爲此,我們需要支持3×3矩陣,由於Irrlicht的僅具有4×4(I相信)的外部庫。

    我們需要求解將圖像從X-Y旋轉到rcdf的矩陣方程。爲此,我們在每個參照系中需要3分。其中兩個我們可以立即設置爲,相鄰的角落的圖片;第三個必須指出圖像的平面(因爲我們需要所有三維數據形成一個完整的基礎) - 所以要計算它,只需將每個圖像的法線乘以某個偏移常數(比如1)即可。

    enter image description here

    (注意在原始圖像上的點已被縮放)因此

    要解決的方程是:

    enter image description here

    (使用列表示)。 Eigen庫提供了3x3矩陣和反轉的實現。

    然後該矩陣轉換爲球形的極角:https://www.learnopencv.com/rotation-matrix-to-euler-angles/


    方法2:

    爲了計算四元數從方向向量A旋轉到B:Finding quaternion representing the rotation from one vector to another

    1. 計算原始圖像的旋轉角度normal(即Z軸)到rcdf的法線=>四元數P

    2. 採取中點的AB從圖中方法1中,並與四元數Phttp://www.geeks3d.com/20141201/how-to-rotate-a-vertex-by-a-quaternion-in-glsl/)=>矢量U旋轉。

    3. U計算旋轉的中點DE =>四元數Q

    4. 乘法的順序Q * P,並轉換爲歐拉角:https://en.wikipedia.org/wiki/Conversion_between_quaternions_and_Euler_angles

    (不知道是否Irrlicht支持四元數)

  • +0

    好吧,我試圖實施方法2.你介意看看它有什麼不幸的是我的方法有錯誤。 – nevrome

    +0

    @nevrome嗨,對不起,延遲;爲什麼圖中有6點?我認爲下面的多邊形是最終結果? – meowgoesthedog

    +0

    @nevrome啊我剛剛意識到 - 答案假設'rcdf'在原點居中,但我看到你的'rcdf'有一個平移偏移量;這很容易修復 - 只需事先計算中心,從rcdf的點中減去它,進行計算並重新添加。我認爲這可能會導致錯誤的角度,因爲* normal *計算不受此平移的影響,所以最終的平面將是正確的,但不是面內方向。 – meowgoesthedog