2013-03-27 59 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。然后,您可以用变换后的光线执行交点。

至于距离计算你有两个选择。您可以使用逆世界矩阵变换摄像机位置,或者使用(不是逆)世界矩阵变换球体位置。