Using CameraZoom to keep objects in view

Blitz3D Forums/Blitz3D Programming/Using CameraZoom to keep objects in view

In my game i'm using camerazoom to get the optimal view of a variable number of active objects (anywhere between 1-5).

I cameraproject the 3D position of each object and work out a bounding 2D box which encompasses all the returned coords. I do a linepick at the centre of that 2D box to work out where the camera should be looking.

Next I calculate a zoom value based on the diagonal length across opposite corners of that box.

dist#= (Diagonal Length of 2D box)
dist=Sqr(dist/GraphicsWidth())	
If dist<.001 Then dist=.001
		
vis_zoom#=1.4/dist
 


the viz_zoom is a bit of a trial and error algorithm. Basically it works reasonably well but not perfectly. As the objects get further apart it tends to zoom out too far. I'd like to find a way to calculate the optimum zoom value which will keep all the objects within the screen (or within a rectangle a bit smaller than the screen).

Any ideas?

Maybe something like
vis_zoom#=1.4/(dist*0.75)
?

What I'm getting at is the margin of error seems be non-linear.

When you say it zooms out 'too far' - how far is that?? Screenshots?

Its possibly the fact that you're using the diagonal length thats throwing it off a bit. Maybe calculate the square root of the diagonal and redo your calculation (with more trial and error) from there. Should help to reduce the problem if its one of those things that becomes more apparent the further out you zoom.

I'll try that.

I think you need to re-scan the objects after aiming the camera. Then use the new 'bounding box' to adjust the zoom factor.

well I recalculate it every frame and only actually adjust the zoom a small amount so the camera basically eases into position. I just need a way to calculate the zoom so the virtual bounding box is the same size at all times.

This should work:
Graphics3D 640,480,0,2
SetBuffer BackBuffer()

Type thingy
	Field mesh
	Field a#
	Field b#
	Field x#,y#,z#
End Type

camera = CreateCamera()

PositionEntity camera,0,0,-100

For i = 0 To 20
	t.thingy = New thingy
	t\mesh = CreateCube()
	t\a = Rnd(0,360.0)
	t\b = Rnd(-2.0,2.0)
	t\x = Rnd(-10.0,10.0)
	t\y = Rnd(-10.0,10.0)
	t\z = Rnd(0.0,10.0)
	PositionEntity t\mesh,t\x,t\y,t\z
Next

Global d#

Repeat

	For t.thingy = Each thingy
		t\a = t\a + t\b
		PositionEntity t\mesh,t\x + Sin(t\a)*10.0, t\y + Cos(t\a)*10.0,t\z + Cos(t\a)*10.0
		TurnEntity t\mesh,0.1,0.1,0.1
	Next

	If KeyDown(200) Then MoveEntity camera,0,0, 1
	If KeyDown(208) Then MoveEntity camera,0,0,-1

	z# = CameraFocus(camera)
	
	RenderWorld
	
	Text 0,0,"Zoom = "+z
	Text 0,10,"Distance = "+d
	
	Flip

Until KeyHit(1)

Function CameraFocus#(cam)

	minx# = 100000.0
	miny# = minx
	minz# = minx
	maxx# = -minx
	maxy# = -miny
	maxz# = -minz
	
	cx# = 0.0
	cy# = 0.0
	cz# = 0.0
	count = 0

	For t.thingy = Each thingy
	
		;
		; Compute simple linear projection
		For s = 1 To CountSurfaces(t\mesh)
			surf = GetSurface(t\mesh,s)
			For v = 0 To CountVertices(surf)-1
				TFormPoint VertexX(surf,v),VertexY(surf,v),VertexZ(surf,v),t\mesh,cam
	
				If TFormedZ()=>0.001
					x# = TFormedX()/TFormedZ()
					y# = TFormedY()/TFormedZ()

					If x<minx Then minx = x
					If y<miny Then miny = y
					If x>maxx Then maxx = x
					If y>maxy Then maxy = y
				EndIf
				
			Next
		Next
		
		;
		; Center point addition
		cx = cx + EntityX(t\mesh,True)
		cy = cy + EntityY(t\mesh,True)
		cz = cz + EntityZ(t\mesh,True)
		count = count + 1
	Next

	;
	; Nothing to focus on
	If count = 0 Then Return
	
	;
	; Width and height of projection
	w# = (maxx-minx)
	h# = maxy-miny
	
	size# = Sqr(w*w + h*h)
	
	;
	; Finalize center point
	cx# = cx/count
	cy# = cy/count
	cz# = cz/count
		
	;
	; Zoom factor
	zoom# = (GraphicsWidth()/Float(GraphicsHeight()))/size
	
	;
	; Point at center
	dummy = CreatePivot()
	PositionEntity dummy,cx,cy,cz
	PointEntity cam,dummy
	
	d = EntityDistance(cam,dummy)
	
	FreeEntity dummy
	
	;
	; Set zoom factor
	CameraZoom cam,zoom
	
	Return zoom
	
End Function

For speed it's better to just compute the projection for either the center of each thingy or the bounding box.

Wow, that's a lot better. Cheers fredborg.