0

私のプロジェクトでは、3D 座標系でいくつかの球を表示します。下の写真を見てください。

ここに画像の説明を入力

各球体には、lab - colorvalue が表示されます。球体を作成するには、DirectX で Meshfunction を使用します。

// 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 と交差するすべてのメッシュを一時リストに設定しました。このアルゴリズムは正しく機能します。私の問題は、正しい距離を取得することです。カメラ ベクトルと静的なラボ値ベクトルからの距離を計算するためです。球体をクリックする前にデバイスを回転させたときに、静的なラボの値をデバイスの世界に変換するにはどうすればよいですか? 解決策を知っていますか?ご協力ありがとうございました!

4

1 に答える 1

0

デバイスの変換が考慮されていないため、交差コードが機能するかどうかは疑問です。いずれにせよ、交差の分析計算を実行する必要があります。Mesh.Intersectすべての三角形をチェックする必要があるため、非常に遅くなる可能性があります。球の位置と半径があります。これらの値に基づいて交点をチェックする必要があります (レイ/ポイントの距離を参照)。

を使用する場合Mesh.Intersectは、レイを変換する必要があります。これは、メソッドが変換されていないメッシュのみを考慮するためです。したがって、デバイスの回転を元に戻す変換が必要です。これは、ワールド マトリックスの逆です。TransformCoordinateTransformNormalおよびInvertを参照してください。次に、変換された光線との交差を実行できます。

距離の計算に関しては、2 つのオプションがあります。逆ワールド行列でカメラの位置を変換するか、(逆ではない) ワールド行列で球体の位置を変換できます。

于 2013-04-03T15:31:34.220 に答える