2013-03-27 62 views
0

在我的項目中,我在三維座標系中顯示了一些球體。請參閱下圖。如何在DirectX中旋轉後獲得一個網格矢量?

enter image description here

每個球體顯示器的實驗室 - colorvalue。要創建一個球體我用Meshfunction在DirectX:

// Radius der Kugel 
private const float radius = 4f; 
// Die Anzahl der Ebenen einer Kugel 
private const int slices = 8; 
// Die Anzalh der Flächen einer Ebene 
private const int stacks = 8; 

// Das Mesh zum Darstellen der Kugel 
private Mesh mesh = null; 
private Vector3 vec; 
public Vector3 min; 
public Vector3 max; 

public void createMesh(Device device, Color color, params float[] labValues) 
{ 
    // Erstellt die Kugel mit der Anbindung an das Device 
    mesh = Mesh.Sphere(device, radius, slices, stacks); 
    // Kopiert das Mesh zum Erstellen des VertexArrays 
    Mesh tempMesh = mesh.Clone(mesh.Options.Value, Vertex.FVF_Flags, device); 
    // Erstellt den VertexArray 
    Vertex[] vertData = (Vertex[])tempMesh.VertexBuffer.Lock(0, typeof(Vertex), LockFlags.None, tempMesh.NumberVertices); 

    // Weist jedem Vertex die Farbe und die Position zu 
    for (int i = 0; i < vertData.Length; ++i) 
    { 
     vertData[i].color = color.ToArgb(); 
     vertData[i].x += labValues[1]; 
     vertData[i].y += labValues[0] - 50f; 
     vertData[i].z += labValues[2]; 
    } 
    min = new Vector3(labValues[1], labValues[0] + 100f, labValues[2]); 
    max = new Vector3(labValues[1], labValues[0] - 100f, labValues[2]); 

    // Gibt den VertexBuffer in der Kopie frei 
    tempMesh.VertexBuffer.Unlock(); 
    // Löscht den Mesh aus dem Speicher 
    mesh.Dispose(); 
    // Legt die Kopie in der Meshinstanz ab 
    mesh = tempMesh; 

    Vector3 vTemp = new Vector3(labValues[1], labValues[0], labValues[2]); 
    vec = vTemp; 
} 

struct Vertex 
{ 
    public float x, y, z; // Position of vertex in 3D space 
    public int color;  // Diffuse color of vertex 

    /// <summary> 
    /// Konstruktor der Vertex 
    /// </summary> 
    /// <param name="_x">X(A) - Position</param> 
    /// <param name="_y">Y(L) - Position</param> 
    /// <param name="_z">Z(B) - Position</param> 
    /// <param name="_color">Die Farbe</param> 
    public Vertex(float _x, float _y, float _z, int _color) 
    { 
     x = _x; y = _y; z = _z; 
     color = _color; 
    } 

    // Das Format des Vertex 
    public static readonly VertexFormats FVF_Flags = VertexFormats.Position | VertexFormats.Diffuse; 
} 

對於設備的旋轉,我拿起了鼠標移動的座標,並將其用於渲染。所以我不改變相機的位置。用於顯示實驗室

Matrix MX = Matrix.RotationX(impValue.ObjektRotationY); 
impValue.ObjektRotationY = 0; 
Matrix MY = Matrix.RotationY(impValue.ObjektRotationX); 
impValue.ObjektRotationX = 0; 

Matrix Rotation = device.Transform.World; 
Rotation *= MY; 
Rotation *= MX; 

device.Transform.World = Rotation; 

現在我添加了一個功能,點擊一個球(Picking - Tutorial) - 值:我僅旋轉設備對象

public Sphere getSphereByCoordinates(Device device, List<Sphere> meshList, Vector3 cameraVec, float x, float y) 
{ 
    // Temporäre Liste für die Kugeln 
    List<Sphere> tempSphereList = new List<Sphere>(); 
    Sphere closestSphere = null; 

    // Instanz des dichten und fernen Vektors 
    Vector3 v3Near = new Vector3(x, y, 0); 
    Vector3 v3Far = new Vector3(x, y, 1); 

    // Wandelt den 2D Vektor in einen 3D Vektor um 
    v3Near.Unproject(device.Viewport, device.Transform.Projection, device.Transform.View, device.Transform.World); 
    v3Far.Unproject(device.Viewport, device.Transform.Projection, device.Transform.View, device.Transform.World); 
    // Subtrahiert die beiden Vektoren 
    v3Far.Subtract(v3Near); 

    // Geht jede einzelne Kugel durch 
    foreach(Sphere tempSphere in meshList) 
    { 
     // Prüft ob sich die Punkte schneiden und fügt es ggf. einer Liste hinzu 
     if(tempSphere.labMesh.Intersect(v3Near, v3Far)) 
      tempSphereList.Add(tempSphere); 
     } 

     // Die nächste Distanz 
     double closestDistance = -1.0; 
     // Geht alle zutreffenden Kugeln durch und sucht sich die nahste Kugel zur Kamera aus 
     foreach(Sphere tempSphere in tempSphereList) 
     { 
      //VertexBuffer haha = tempSphere.labMesh. 
      double theDistance = Distance(cameraVec, tempSphere.labVector); 

      if (theDistance < closestDistance || closestDistance == -1d) 
      { 
       closestDistance = theDistance; 
       closestSphere = tempSphere; 
      } 
     } 

     return closestSphere; 
    } 

private double Distance(Vector3 v1, Vector3 v2) 
{ 
    // Erstellt einen Differenzvektor 
    Vector3 difference = new Vector3( v1.X - v2.X, 
             v1.Y - v2.Y, 
             v1.Z - v2.Z); 
    // Gibt die berechnete Distanz zurück 
    `return Math.Sqrt(Math.Pow(difference.X, 2f) + Math.Pow(difference.Y, 2f) + Math.Pow(difference.Z, 2f)); 
} 

怎麼可以看到我設置的所有網格誰將MouseWorldCoordinates交叉到一個臨時List中。此算法正常工作。我的問題是通過現在獲得正確的距離。因爲我調用了相機矢量和靜態實驗值矢量之間的距離。在點擊球體之前旋轉設備時,如何將靜態實驗室值轉換爲設備世界?你知道一個解決方案嗎?感謝您的幫助!

+0

與您的問題無關,但請'PascalCase'您的公共職能...(http://msdn.microsoft.com/en-us/library/vstudio/ms229043%28v=vs.100%29.aspx ) – antonijn 2013-03-27 16:48:52

回答

0

我懷疑你的交叉碼是否有效,因爲它不考慮設備轉換。無論如何,您應該執行交叉點的分析計算。 Mesh.Intersect會變得非常慢,因爲它必須檢查每個三角形。你有球體的位置和半徑。您應該根據這些值檢查交叉點(請參閱射線/點的距離)。

如果您想使用Mesh.Intersect,則必須轉換射線,因爲該方法僅考慮未轉換的網格。所以你需要一個轉換來恢復設備的旋轉,這正是世界矩陣的逆轉。請參閱TransformCoordinate,TransformNormalInvert。然後,您可以用變換後的光線執行交點。

至於距離計算你有兩個選擇。您可以使用逆世界矩陣變換攝像機位置,或者使用(不是逆)世界矩陣變換球體位置。