4

I have a GLScene object of varying (but known) size. It is completely surrounded by a TGLDummyCube.

I want to position the GLCamera (with CameraStyle: glPerspective) so that the object is completely visible on screen. I got this running basically - the object is visible, but the distance is sometimes too far, or the object is larger than the screen and clipped.

How can I do that? I suppose that this can be done by a clever combination of camera distance and focal length, but I have not been successful so far.

This seems to be different in GLScene compared to OpenGL. I'm using GLScene and Delphi 2007.

Nate Barbettini
  • 43,095
  • 21
  • 121
  • 135
Andreas
  • 469
  • 3
  • 9
  • If you get no joy asking this way, you might consider removing the Delphi tag and just asking about GLScene, stating that any logic would be appreciated, including pseudocode, and that you'll plan to adapt to Delphi. The language you're using isn't really important, it's the logic/math you're after. – Argalatyr Jul 25 '09 at 14:56
  • Thanks Argalatyr, but I'm not sure about the GLCamera object - is that just an encapsulation of a standard OpenGL camera, or does it add additional features? – Andreas Jul 27 '09 at 05:47
  • It's a classic OpenGL camera at its core, there are extra features, but they don't change the underlying maths. – Eric Grange Feb 03 '12 at 07:46

2 Answers2

4

Although varying the camera distance and focal length will change the object's visual size, it has the drawback of also changing the perspective, thus leading to a somewhat distorted view. I suggest to use the camera's SceneScale property instead.

Alas, I have no valid steps to calculate the correct value for that. In my case I have to scale to a cube with varying size, while the window size of the viewer is constant. So I placed two dummycubes at the position of the target cube, each sized to fit either the width or the height of the viewer with appropriate values for SceneScale, camera distance and FocalLength. During runtime I calculate the new SceneScale by the ratio of the target cube size in respect to the dummycube sizes. This works quite well in my case.

Edit: Here is some code I make for the calculations.

  • ZoomRefX and ZoomRefY are those DummyCubes
  • TargetDimX and TargetDimY give the size of the current object
  • DesignWidth and DesignHeight are the size of MyGLView at design time
  • DesignSceneScale is the camera's SceneScale at design time

The calculation code:

ScaleX := (ZoomRefX.CubeSize*MyGLView.Width)/(DesignWidth*TargetDimX);
ScaleY := (ZoomRefY.CubeSize*MyGLView.Height)/(DesignHeight*TargetDimY);
NewSceneScale := Min(ScaleX, ScaleY)*DesignSceneScale;

The DummyCubes ZoomRefX and ZoomRefY are sized so that they have a small margin to either the left-right or top-bottom edges of the viewing window. The are both positioned so that the front faces match. Also the target object is positioned to match its front face with those of these DummyCubes.

The formulas above allow the window size to be different from design time, but I actually didn't test this feature.

Nate Barbettini
  • 43,095
  • 21
  • 121
  • 135
Uwe Raabe
  • 39,888
  • 3
  • 77
  • 115
  • Thanks for the tip - I've been playing with SceneScale as well, using it in my OnMouseWheel event handler. Do I understand correctly that you set those dummycubes up during development, and the fit the cube accordingly at run-time? Sounds like a clever trick. Change the object, not the camera. – Andreas Jul 27 '09 at 05:51
  • I set the dummycubes at during development to a size matching the window size of the viewer. Two cubes because the screen is not quadratic, but the dummycubes are. Now when my real object has say double the size of the dummycube, I know I have to halfen the SceneScale to make its visible size like the dummycube at design time. Doing these calculations separately for the widht and the height I can calculate the SceneScale that makes the target object fit into the window. This only works because the window size is fixed. And I don't change the object - I only change the camera's SceneScale. – Uwe Raabe Jul 27 '09 at 06:48
0

@Andreas if you've been playing with SceneScale (as you mentioned in comments) that means that you are looking for a proper way to fit object within camera view by either changing camera distance/focal length or by resizing object. If so, the easiest way to resize single object to fit the screen is to use its BoundingSphereRadius property like this:

ResizeMultiplier := 2; //play with it, it depends on your camera params
GLFreeForm1.Scale.Scale(ResizeMultiplier / GLFreeForm1.BoundingSphereRadius);

You can add GLDummyCube as root object for all other scene objects and then resize GLDummyCube with method mentioned above.

Kainax
  • 1,306
  • 14
  • 24