Seite 1 von 1

Raypick funktioniert nur bedingt.

Verfasst: 08.02.2024, 10:38
von Andy90
Hallo :) ich habe mich gestern daran gemacht, eine Funktion zu erstellen, mit der ich Entitys mi der Maus picken kann. Ich habe gesehen das es dafür mehrere Möglichkeiten gibt und dachte, dass sich ein Raycast ganz gut eignen könnte. Jedoch habe ich das Problem das das ganze nicht so richtig funktionieren mag.

Mit dieser Klasse erstelle ich den Raycast

Code: Alles auswählen

public class MouseRay
{
    public vec3 CurrentRay { get; set; }
    public mat4 ProjectionMatrix { get; set; }
    public mat4 ViewMatrix { get; set; }
    public Camera Camera { get; set; }


    public MouseRay(Camera camera)
    {
        this.Camera = camera;
    }

    private void GenerateMatrix(Camera camera)
    {
        vec3 cameraPosition = camera.Location.ToGlmVec3();
        Vec3 cameraFront = Utils.CalculateCameraFront2(camera);

        ProjectionMatrix = mat4.Perspective(Utils.ToRadians(45.0f), camera.Size.X / camera.Size.Y, camera.Near, camera.Far);
        ViewMatrix = mat4.LookAt(cameraPosition, cameraPosition + cameraFront.ToGlmVec3(), new vec3(0.0f, 1.0f, 0.0f));
    }

    public Vec3 RayCast(float mouseX, float mouseY, Viewport viewport)
    {
        this.GenerateMatrix(this.Camera);
        var ndc = GetNDC(mouseX, mouseY, viewport);
        var clip = new vec4(ndc.x, ndc.y, -1f, 1f);
        var eye = GetEyeCords(clip);
        vec3 ray_wor = GetWorldCords(eye);
        return new Vec3(ray_wor);
    }

    private vec3 GetWorldCords(vec4 eye)
    {
        vec3 rey_wor = (ViewMatrix.Inverse * eye).xyz;
        return rey_wor.Normalized;
    }

    public vec4 GetEyeCords(vec4 clip)
    {
        vec4 ray_eye = ProjectionMatrix.Inverse * clip;
        return new vec4(ray_eye.x, ray_eye.y, -1f, 0f);
    }

    public vec2 GetNDC(float x, float y, Viewport viewport) 
    {
        float ndcX = (2.0f * x) / viewport.Width - 1.0f;
        float ndcY = 1.0f - (2.0f * y) / viewport.Height;
        return new vec2(ndcX, -ndcY);
    }
}
und dann Prüfe ich hiermit ob es zu einer Intersection zwischen cast und aabb eines entitys kommt

Code: Alles auswählen

                start = this.Camera.Location;
                end = MouseRay.RayCast(e.X, e.Y, Viewport);

                foreach (var layer in this.Scene.Layer)
                {
                    foreach (var entity in layer.Elements)
                    {
                        StaticMeshBehavior staticMeshBehavior = (StaticMeshBehavior)entity.GetBehavior<StaticMeshBehavior>();
                        if (staticMeshBehavior != null)
                        {
                            Genesis.Physics.Aabb aabb = Genesis.Physics.Aabb.FromBulletRigidBody(staticMeshBehavior.RigidBody);
                            if (Genesis.Physics.Aabb.IntersectRay(start, end, aabb.Min, aabb.Max))
                            {
                                MessageBox.Show("contact");
                            }
                        }
                    }
                }
Es ist nun so, dass der cast nicht wirklich in Richtung der Maus verläuft und ich die Message box für den kontakt auch erhalte wenn ich nicht auf das Entity klicke.

Beste grüße

Andy

Re: Raypick funktioniert nur bedingt.

Verfasst: 08.02.2024, 12:07
von Mirror
Du schreibst gar nicht was für ein Mesh es ist. Handelt es sich denn um eine Box und ist sie auch wirklich Achsenausgerichtet ? Beides sind Gründe warum Du nicht das gewünschte Ergebnis erhältst. Wenn Du eine Box verwendest, musst Du eine Oriented-Bounding-Box verwenden und den Ray in den Modelview umrechnen.

Re: Raypick funktioniert nur bedingt.

Verfasst: 08.02.2024, 12:17
von Andy90
Hallo, danek für deine Antwort. Die Aabb erhalte ich von bullet selbst. Ich debuge den Ray und da ist schon zu sehen das die linie nicht zur Maus position geht.

Re: Raypick funktioniert nur bedingt.

Verfasst: 08.02.2024, 12:21
von Chromanoid
Wenn Du Bullet benutzt, kannst Du doch direkt einen RayTest ausführen und musst nicht selbst alle Entities durchgehen?

Re: Raypick funktioniert nur bedingt.

Verfasst: 08.02.2024, 12:55
von Andy90
Ich nutze direkt bullet sondern ein wrapper namens Bulletsharp. Ich habe noch nicht wirklich rausgefunden wie ich einen RayTest mit bullet machen kann. Ich habe auch keine game loop, da es für ein editor ist und dieser nur rendert wenn ein neues Frame benötigt wird.

Habe eine RayTest funktion gefunden. Allerdings brauche ich dafür auch die Maus Position in world coordinaten.

Re: Raypick funktioniert nur bedingt.

Verfasst: 08.02.2024, 15:14
von Andy90
Ich glaube einfach meine Maus Koordinaten sind zu gering. Mein Model ist auf 0,0,0 und hat eine größe von 1,1,1. Meine Maus ist, mit einer TopDown view am oberen Linken Bildschirmrand an der position (0,32, -0.78, 0.533) und in der Mitte wie es sein soll auf (0, -1, 0). Demnach ist ja der Mausbereich viel zu gering oder irre ich mich da?

Re: Raypick funktioniert nur bedingt.

Verfasst: 08.02.2024, 17:23
von Schrompf
Kommt auf den Öffnungswinkel an, ob das korrekt ist, aber die Zahlen sehen erstmal einfach danach aus, als wäre Dein Vektor normiert. Und das würde ich ja auch so erwarten.

Re: Raypick funktioniert nur bedingt.

Verfasst: 08.02.2024, 17:25
von Chromanoid

Re: Raypick funktioniert nur bedingt.

Verfasst: 08.02.2024, 17:29
von Andy90
Ja genau, das mache ich hier mit dem Normalisieren

Code: Alles auswählen

        private vec3 GetWorldCords(vec4 eye)
        {
            vec3 rey_wor = (ViewMatrix.Inverse * eye).xyz;
            return rey_wor.Normalized;
        }
Das Beispiel habe ich gesehen. Habe das auch schon so implementiert. Allerdings ist es so, was ich festgestellt habe, dass wenn ich mein Model auf die Position die ich erhalte (von meinem Raycast) es überhaupt nicht diesen Welt Koordinaten entspricht.

Re: Raypick funktioniert nur bedingt.

Verfasst: 08.02.2024, 18:16
von Andy90
habe anhand von dem Beispiel von Chromanoid folgendes gefunden was etwas besser funktioniert aber noch nicht ganz richtig. https://github.com/AndresTraks/BulletSh ... mo.cs#L311 Ich nehme an, dass es sich bei Freelook um die Kamera handelt und bei Freelook.target um den Mittelpunkt der Kamera.

Re: Raypick funktioniert nur bedingt.

Verfasst: 08.02.2024, 21:22
von Andy90
Ich nehme an, ich habe mein fehler gefunden. Die Koordinaten des Rays sind auch im Normal Device Space. Nun ist die frage wie wandele ich diese um.

Re: Raypick funktioniert nur bedingt.

Verfasst: 09.02.2024, 00:28
von Andy90
Sorry für die vielen Nachrichten, ich denke ich hab es gelöst. Wie @Chromanoid vorgeschlagen hat mit bullet selbst. https://www.opengl-tutorial.org/miscell ... s-library/ hat mir auch sehr geholfen. Werde morgen noch den code des RayCasters posten, so dass andere was davon haben, bei selben Problemmen.

----------------------
Edit: Hier ist die klasse von dem Raycaster https://github.com/Andy16823/GFX/blob/m ... ouseRay.cs