Results 1 to 9 of 9

Thread: Ray picking

  1. #1
    Legendary Member NecroDOME's Avatar
    Join Date
    Mar 2004
    Location
    The Netherlands, Eindhoven
    Posts
    1,059

    Ray picking

    Hi there,

    I need to pick some objects with my 3D view.

    How can I transform my screen x and y (and some depth) to 3D world coordinates (x, y and z). As I'm not using newton for this I don't know how to do it...

    And next I need to test if a sphere is intersected.

    Michiel.

    (ps, using DirectX, I found some OpenGL but it doesn't help me much)
    NecroSOFT - End of line -

  2. #2

    Ray picking

    Some Ray picking links:

    http://www.mvps.org/directx/articles/rayproj.htm
    http://www.mvps.org/directx/articles...ay_picking.htm(a ray picking app)
    http://www.toymaker.info/Games/html/picking.html

    Ray-Sphere intersection:

    http://www.devmaster.net/wiki/Ray-sphere_intersection
    http://www.cs.princeton.edu/courses/...ast/sld012.htm
    http://www.realtimerendering.com/int/(all kinds of intersections... very usefull for collision detection )

    Hope it will be usefull for you.

    Good luck

    BTW.. you can also check the Pick example in the DX SDK.
    Coders rule nr 1: Face ur bugz.. dont cage them with code, kill'em with ur cursor.

  3. #3
    Legendary Member NecroDOME's Avatar
    Join Date
    Mar 2004
    Location
    The Netherlands, Eindhoven
    Posts
    1,059

    Ray picking

    This is what I got so far:

    [pascal]procedure ScreenToWorld(x, y, w, h, Depth : Single; var P1, P2: TD3DVector);
    var
    v: TD3DVector;
    invMatrix, viewMatrix, projMatrix: TD3DMatrix;

    rayOrigin, rayDir : TD3DVector;
    begin

    Necro3D.Screen.Device.GetTransform(D3DTS_VIEW, projMatrix);
    v.x := ( ( ( 2.0 * x ) / w ) - 1 ) / projMatrix._11 * 1.3333;
    v.y := -( ( ( 2.0 * y ) / h ) - 1 ) / projMatrix._22;
    v.z := 1.0;

    Necro3D.Screen.Device.GetTransform(D3DTS_VIEW, viewMatrix);
    D3DXMatrixInverse(invMatrix, nil, viewMatrix);


    rayDir.x := v.x*invMatrix._11 + v.y*invMatrix._21 + v.z*invMatrix._31;
    rayDir.y := v.x*invMatrix._12 + v.y*invMatrix._22 + v.z*invMatrix._32;
    rayDir.z := v.x*invMatrix._13 + v.y*invMatrix._23 + v.z*invMatrix._33;
    rayOrigin.x := invMatrix._41;
    rayOrigin.y := invMatrix._42;
    rayOrigin.z := invMatrix._43;

    p1 := rayOrigin;
    p2.x := (rayDir.x * Depth) + rayOrigin.x;
    p2.y := (rayDir.y * Depth) + rayOrigin.y;
    p2.z := (rayDir.z * Depth) + rayOrigin.z;
    end;[/pascal]

    It's not perfect (far from it).
    - When I'm looking straight forward it works correctly
    - When looking backward, the X axis is inverted
    - When looking up/down more then 90 degrees the numbers go nuts (some gimball lock or something?)

    x, y - screen coordinats,
    w, h - screen width and height
    Depth - z on the screen, how long the pick-ray should be (currently I place a light on this point to see some debug info)

    ps. I'm using this approach: http://www.toymaker.info/Games/html/picking.html
    NecroSOFT - End of line -

  4. #4

    Ray picking

    Owh... i think i see the bug

    Change:
    [pascal]
    Necro3D.Screen.Device.GetTransform(D3DTS_VIEW, projMatrix);
    [/pascal]

    To:

    [pascal]
    Necro3D.Screen.Device.GetTransform(D3DTS_PROJECTIO N, projMatrix);
    [/pascal]

    Since projMatrix should contain the projection matrix instead of the view matrix.

    You can also try this demo:
    http://www.mvps.org/directx/articles...ay_picking.htm

    If it works you can use the code. The only problem is that it's C++.

    Hope this helps
    Coders rule nr 1: Face ur bugz.. dont cage them with code, kill'em with ur cursor.

  5. #5
    Legendary Member NecroDOME's Avatar
    Join Date
    Mar 2004
    Location
    The Netherlands, Eindhoven
    Posts
    1,059

    Ray picking

    Thanks!!

    Works now
    NecroSOFT - End of line -

  6. #6
    Legendary Member NecroDOME's Avatar
    Join Date
    Mar 2004
    Location
    The Netherlands, Eindhoven
    Posts
    1,059

    Ray picking

    Only the ray-sphere-intersection doesn't work.. I managed to create lights (just for testing) on the screen just by clicking on it.

    I used this for ray-intersection:
    http://www.flipcode.com/cgi-bin/fcar...cgi?show=64047

    My code:
    [pascal]// Ported from the C++ example
    function intersectRaySphere(rO, rV, sO: TD3DVector; sR: single): single;
    var Q : TD3DVector;
    c, v, d : single;
    begin
    Q := VectorSub(sO, rO);
    c := lengthOfVector(Q);
    v := dot(Q, rV);
    d := (sR*sR) - ((c*c) - (v*v));

    // If there was no intersection, return -1
    if d < 0.0 then
    Result := -1
    else
    // Return the distance to the [first] intersecting point
    Result := v - sqrt(d);
    end;[/pascal]

    My ray function:
    [pascal]procedure ScreenToWorld(x, y, w, h, Depth : Single; var P1, P2, rayDir: TD3DVector);
    var
    v: TD3DVector;
    invMatrix, viewMatrix, projMatrix: TD3DMatrix;

    rayOrigin : TD3DVector;
    begin
    Necro3D.Screen.Device.GetTransform(D3DTS_PROJECTIO N, projMatrix);
    v.x := ( ( ( 2.0 * x ) / w ) - 1 ) / projMatrix._11;
    v.y := -( ( ( 2.0 * y ) / h ) - 1 ) / projMatrix._22;
    v.z := 1.0;

    Necro3D.Screen.Device.GetTransform(D3DTS_VIEW, viewMatrix);
    D3DXMatrixInverse(invMatrix, nil, viewMatrix);

    rayDir.x := v.x*invMatrix._11 + v.y*invMatrix._21 + v.z*invMatrix._31;
    rayDir.y := v.x*invMatrix._12 + v.y*invMatrix._22 + v.z*invMatrix._32;
    rayDir.z := v.x*invMatrix._13 + v.y*invMatrix._23 + v.z*invMatrix._33;
    rayOrigin.x := invMatrix._41;
    rayOrigin.y := invMatrix._42;
    rayOrigin.z := invMatrix._43;

    p1 := rayOrigin;
    p2.x := (rayDir.x * Depth) + rayOrigin.x;
    p2.y := (rayDir.y * Depth) + rayOrigin.y;
    p2.z := (rayDir.z * Depth) + rayOrigin.z;
    end;[/pascal]

    It's kinda strange. I try to explane my problem:

    When a light is on the left side of the screen and when I click on the right side of the screen it's selected. When I click left of the light, it's doesn't do anything.

    And this is how I pick my stuff:
    [pascal]if intersectRaySphere(RayPos, RayDir, Necro3D.Lights.Lights[i].Position, 1)<>-1.0 then Success[/pascal]
    NecroSOFT - End of line -

  7. #7
    Legendary Member NecroDOME's Avatar
    Join Date
    Mar 2004
    Location
    The Netherlands, Eindhoven
    Posts
    1,059

    Ray picking

    Got it, needed to normalize the vector
    NecroSOFT - End of line -

  8. #8

    Ray picking

    I would be interested to see the final function if that is ok
    The views expressed on this programme are bloody good ones. - Fred Dagg

  9. #9
    Legendary Member NecroDOME's Avatar
    Join Date
    Mar 2004
    Location
    The Netherlands, Eindhoven
    Posts
    1,059

    Ray picking

    Final function: see previous post.

    Set in the beginning of IntersectRaySphere something like D3DXVec3Normilize(rV, rV);

    ScreenToWorld works fine

    Some details on intersectRaySphere:
    rO = ray origin
    rV = ray direction
    sO = sphere origin
    sR = sphere radius
    NecroSOFT - End of line -

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •