Position camera so view fits a ground square

BlitzMax Forums/MiniB3D Module/Position camera so view fits a ground square

KronosUK(Posted 2013) [#1]
Here's a brain teaser for someone.

Say I have a square on the ground and I want to view that square from a camera using orthographic projection mode, so that the square exactly fits to the camera viewport.

For a given camera angle , rotating on the x axis only, how would I calculate the camera position to do this.

What I want to do is render a texture to use as a shadowmap on a square tile of terrain. There will be many such tiles each with its own static shadow texture so the texture fit has to be exact.


Kryzon(Posted 2013) [#2]
Image taken from the DirectX documentation:



Since you're using an ortographic projection, these clipping planes above would have the same size; This means the camera's frustum would have a cuboid shape.
If you set up a square viewport with the same size in pixels as that of your power-of-two texture, the frustum will extend from -1 to +1 in the X axis (so it's 2 units wide), -1 to +1 in the Y axis (so it's 2 units high) and from the NearPlane to the FarPlane in the Z axis.

Since you're only rotating the camera in the global X axis (so the camera only looks up or down), the left and right sides of the camera's frustum cuboid will be parallel to the left and right sides of the cuboid that encloses the terrain tile geometry (imagine an abstract axis-aligned bounding box that surrounds your terrain tile perfectly).
In other words, the camera's local X axis is parallel to the terrain tile's local X axis. This facilitates things.

To render your terrain tile to be fit in the viewport, you need to do a few things.
First, center the terrain tile on the world's origin [0,0,0].
Then you need to ensure that this tile's total width is 2 units. Like the camera's frustum, this tile will extend from -1 to +1 in the global X axis.
Then position the camera like this:
Const NEAR_PLANE# = 1.0
Const FAR_PLANE# = 100.0 ;It could be less than this, but this value is conservative enough.
Const SHADOWMAP_SIZE = 256

CameraRange( camera, NEAR_PLANE, FAR_PLANE )
CameraViewport( camera, 0, 0, SHADOWMAP_SIZE, SHADOWMAP_SIZE )


[...]


;Orient the camera in the desired way.
RotateEntity( camera, xAngle, 0, 0, True )

;Position the center of the camera's frustum at the world's origin, preserving the camera's orientation.
TFormPoint( 0, 0, FAR_PLANE / 2.0, camera, 0 )
TranslateEntity( camera, -TFormedX(), -TFormedY(), -TFormedZ(), True )

RenderWorld()
CopyRect( ... )