Hi Randall

Thanks very much for your reply. After I sent my question to the list, I too got into the code - particularly camera.c - to see what was going on. Your email confirmed what I had found.

If I understand your reply correctly, I have one minor difference concerning the location of the projection plane and front clipping plane. I believe the projection plane runs right through the "To" point and that it also acts as the front clipping plane.

To confirm this, I set up a small experiment where I positioned a simple 2x2x2 cube on the origin and viewed in perspective with a "View Angle" of 90 degrees and with the X resolution = Y resolution (this means all half angles are 45 degrees which makes it easy to determine what the final projection should look like). If you then generate a perspective view the cube (connections) using from = (2,0,2) and to = (1,0,1), the front cube face lies on the projection plane and it should consume all of the rendered image window, due to the location of the viewer and the 90 degree view angle. And this does indeed occur. I've inserted the small net in the email if you wanted to try it.

Thanks again,
Joe Young.

//
// time: Tue Jun 18 07:31:12 2002
//
// version: 3.1.2 (format), 4.1.3 (DX)
//
//
// MODULE main
// workspace: width = 601, height = 299
// layout: snap = 0, width = 50, height = 50, align = NN
//
macro main(
) -> (
) {
    //
    // node Camera[1]: x = 385, y = 117, inputs = 9, label = Camera
    // input[1]: defaulting = 0, visible = 1, type = 8, value = [0 0 1]
    // input[2]: defaulting = 0, visible = 1, type = 8, value = [0 0 2]
    // input[4]: defaulting = 0, visible = 1, type = 1, value = 400
    // input[5]: defaulting = 0, visible = 1, type = 5, value = 1.0
    // input[7]: defaulting = 0, visible = 1, type = 3, value = 1
    // input[8]: defaulting = 0, visible = 1, type = 5, value = 90.0
    //
main_Camera_1_out_1 =
    Camera(
    main_Camera_1_in_1,
    main_Camera_1_in_2,
    main_Camera_1_in_3,
    main_Camera_1_in_4,
    main_Camera_1_in_5,
    main_Camera_1_in_6,
    main_Camera_1_in_7,
    main_Camera_1_in_8,
    main_Camera_1_in_9
    ) [instance: 1, cache: 1];
    //
    // node Grid[1]: x = 168, y = 24, inputs = 4, label = Grid
    // input[1]: defaulting = 0, visible = 1, type = 8, value = [0 0 0]
    // input[2]: defaulting = 0, visible = 1, type = 32, value = "brick"
    // input[3]: defaulting = 0, visible = 1, type = 16777224, value = {[1 0 0] [0 1 0] [0 0 1]}
    // input[4]: defaulting = 0, visible = 1, type = 16777217, value = {2 2 2}
    //
main_Grid_1_out_1 =
    Grid(
    main_Grid_1_in_1,
    main_Grid_1_in_2,
    main_Grid_1_in_3,
    main_Grid_1_in_4
    ) [instance: 1, cache: 1];
    //
    // node ShowConnections[1]: x = 212, y = 128, inputs = 1, label = ShowConnections
    //
main_ShowConnections_1_out_1 =
    ShowConnections(
    main_Grid_1_out_1
    ) [instance: 1, cache: 1];
    //
    // node Display[1]: x = 288, y = 237, inputs = 8, label = Display
    // depth: value = 24
    // window: position = (0.0674,0.0286), size = 0.4043x0.6120
    //
main_Display_1_out_1[cache: 2] =
    Display(
    main_ShowConnections_1_out_1,
    main_Camera_1_out_1,
    main_Display_1_in_3,
    main_Display_1_in_4,
    main_Display_1_in_5,
    main_Display_1_in_6,
    main_Display_1_in_7,
    main_Display_1_in_8
    ) [instance: 1, cache: 1];
// network: end of macro body
}
main_Camera_1_in_1 = [0 0 1];
main_Camera_1_in_2 = [0 0 2];
main_Camera_1_in_3 = NULL;
main_Camera_1_in_4 = 400;
main_Camera_1_in_5 = 1.0;
main_Camera_1_in_6 = NULL;
main_Camera_1_in_7 = 1;
main_Camera_1_in_8 = 90.0;
main_Camera_1_in_9 = NULL;
main_Camera_1_out_1 = NULL;
main_Grid_1_in_1 = [0 0 0];
main_Grid_1_in_2 = "brick";
main_Grid_1_in_3 = {[1 0 0] [0 1 0] [0 0 1]};
main_Grid_1_in_4 = {2 2 2};
main_Grid_1_out_1 = NULL;
main_ShowConnections_1_out_1 = NULL;
main_Display_1_in_3 = "X24,,";
main_Display_1_in_4 = NULL;
main_Display_1_in_5 = NULL;
main_Display_1_in_6 = NULL;
main_Display_1_in_7 = NULL;
main_Display_1_in_8 = NULL;
Executive("product version 4 1 3");
$sync
main();



Joseph Young:
 |Fellow DX users ... Does anyone know the full specification of the OpenDX
 |perspective camera? One can set To, From, Up, View Angle (fov), Window
 |Width and Height in pixels. However, does anyone know exactly where the
 |view or projection plane positioned with respect to the scene objects (in
 |terms of World Coordinates)? - this is the plane that the perspective image
 |is projected onto. And what front and back clipping planes are used?
 |
 |Any help would be greatly appreciated.

Do you mean software rendering?

I have a page of notes I wrote up on this a while back while picking
through the code.  Might not be exactly what you need, but this is what I
have down:

(Camera space picture)

                      \                        /
                        \ A        B       C /           X
                   -------\----------------/--------    --->
                            \            /              |
                              \        /               \|/
                                \  t /                    Z
                                  \/
                                   D

The apex/eye (D) is 0,0,0.  The center of your image (B) is (0,0,-1).  The
X coord range of the image (A->C) runs from (-res/2,0,-1) to (res/2,0,-1).

The coord system is right-handed so Y is coming out of the monitor toward
you.  The Y image coord range runs -res*aspect/2 -> res*aspect/2.

Note that this camera space is after the camera transform has been applied
but before we've done the perspective divide.  The camera transform
includes an XY-only scale to convert from FOV units (aka "width"; world XY
units) to image resolution XY units (res).  FOV=2*tan(t/2), where angle t
is the view angle.

The projection transform is "if pt.z < nearPlane: pt /= -pt.z", so z=-1 (in
camera space) is the projection plane.  In world space, I think it's one
unit away on the vector from "from" to "to" (D->B).  See matrix() in
camera.c to check that.

As far as front/back clipping planes, I believe there's only a front plane.
It's dynamically computed to avoid loss of precision, though I haven't
traced this through.

One other thing.  DX uses this matrix order: x*A*B*C=y (at least in the
parts I looked through).

Hope this helps,

Randy

--
Randall Hopper (mailto:[EMAIL PROTECTED])
Lockheed Martin Operation Support
EPA Scientific Visualization Center
US EPA N127-01; RTP, NC 27711

-------------------------------
Dr Joseph Young
Scientific Computation & Visualisation Group
Department of Mathematical Sciences <http://www.maths.sci.qut.edu.au>
Queensland University of Technology <http://www.qut.edu.au>
GPO Box 2434, Brisbane, 4000.
Queensland, Australia.
Phone: +61 7 3864-1339

Reply via email to