2
votes

I'm using FireMonkey to create a 3D scene, which works well: camera set up and in the image below, three stretched cubes show the three axes (red X, green Y, blue Z.)

Normal 3D perspective view in FireMonkey

Normal 3D perspective view in FireMonkey - Projection is pjCamera.

However, this is a perspective 3D scene, and I would like an orthographic 3D projection instead - that is, one in which the size of objects does not diminish as they get further away. (The ultimate idea is to use this to show a 3D isometric view.) FireMonkey seems to have no orthographic projection code - pjCamera translates to using a perspective matrix.

I have no need for a perspective 3D view at all so have approached this by replacing the perspective matrix method with a method to create an orthographic matrix instead. That is, TContext3D.GetProjectionMatrix (which gets the perspective matrix) calls MatrixPerspectiveFovRH to calculate a perspective matrix:

Result := MatrixPerspectiveFovRH(cPI / 4, FWidth / FHeight, 1.0, 1000.0);

I am replacing this with a call to an ortho matrix instead:

Result := IdentityMatrix3D;
Result.m11 := 2 / FWidth;
Result.m22 := 2 / FHeight;
Result.m33 := 1 / (zn - zf);
Result.m43 := zn / (zn - zf);

where zn = 1 and zf = 1000. FWidth is the width of the view in pixels (say, 320) and FHeight the height in pixels, say 240.

This initially appears to work okay-ish, although further away from the objects than I expected: enter image description here

The problem is that the rendered image no longer seems to change with the camera position. I have verified the world-view matrix is calculated the same (ie unaffected by my changes) but when I move the camera closer to (0,0,0) the visible objects get trimmed, but the rendered image itself doesn't change. For example, here I have moved the camera very close to (0,0,0) and here are the perspective and orthographic renderings of the same camera position: enter image description here

Clearly something is wrong with how I'm calculating the orthographic projection, but what I don't know.

  • I do know that changing the width and height used in the ortho calculation appears to move the objects nearer and further - smaller width and height moves them closer to the screen.
  • I am fairly sure the ortho matrix setup is supposed to be correct - although obviously this is wrong :)
  • Although it uses DirectX under the hood, the perspective matrix is a right-handed matrix, so the ortho one should be too.

I have read quite a lot about how to set up an orthographic matrix but obviously not the right things. For example:

  • Do width and height represent the screen width and height, or something else - frustum for example? Nothing I read explained what these were, assuming they were obvious.
  • If they are something else, where can I extract their values from? Can I extract them from the perspective matrix if I allow that to be calculated?

Thankyou for your help.

1
This sounds like expected behaviour. If objects appear the same size no matter how far away you are, why would moving the camera towards or away from the scene change how it appears? For isometric projections you "zoom" by changing the size of the scene rather than the position of the viewer.David Heffernan
@DavidHeffernan Hmm, I might have missed something fundamental then. But wouldn't the camera position affect what is in the field of view? The size is based on what's in the FOV which is based on the camera distance?David
I'm more familiar with isometric projections, for which camera position does not affect field of view. Indeed you can see objects that are behind you. The 3D coordinates are projected normal to the view direction onto a plane. However, I've not looked in detail at what you are doing, and am personally allergic to FMX so know no details. It's quite possible that I am spouting nonsense.David Heffernan
@DavidHeffernan We all spout nonsense sometimes, but it sounds like you're on to something to me. Please keep going! (I am actually ultimately trying to create a 30-deg isometric view, using an orthographic projection with a camera at an appropriate angle in order to give the 30-deg view.) You can see in the screenshot the grid is being clipped as the camera moves. Can you suggest how I might scale the width/height to get onscreen something that matches how FMX is clipping objects, in order to show a zoom close to what it thinks is the zoom?David
I guess you would set the size of the scene based on the projected size of the object you want to fill the viewDavid Heffernan

1 Answers

2
votes

There are great videos on YouTube. Search for "Quark Cube". A - apparently - german developer has some great video's that shows a lot of 3D programming in Firemonkey.

To you question - this works for me: If a dummy shape are the parent of your shapes then 2 simple changes are needed:

These calls set the view to orthogonal: In dummys event "OnRender" call:
Context.SetCameraViewAngle(0.1);
Dummys Scale.Point property must be set to:
Dummy.Scale.Point:= TPoint3D.Create(1, 1, 1) / 45;

To restore to Perspective view:
Dummy.Scale.Point:= TPoint3D.Create(1, 1, 1); Context.SetCameraViewAngle(45);

The above code works for me. And no, I'm absolutely no expert, but the above code was extracted from a 2 year old YouTube video: "Tutorial: Utah teapot in wireframe with Orthogonal view (FireMonkey XE6 / Delphi XE6)" - Channel "Quark Cube".
BTW, I'm using Berlin 10.2, so it works on that version as well.
Hope this helps and can be usefull for others developers with the same problem.