Moving where the camera looks?

Blitz3D Forums/Blitz3D Programming/Moving where the camera looks?

John Pickford(Posted 2004) [#1]
The camera always 'looks' at the centre of the viewport. Is there any way to shift this point?

I'd like to overlay a load of icons which obscure most of the bottom third of the viewport. I'd like to shift the camera's centre point to 1/3rd down the screen rather than 1/2. Make sense?

Essentially the bottom 3rd of the screen is just a 'panel' but I'd like the 3D view to be still behind it.

I hope I'm explaining this right - I don't seem to have the correct jargon.


fredborg(Posted 2004) [#2]
This isn't possible.

You might be able to do some weird stuff, if the camera is parented to a pivot. Then rotate the camera slightly up compared to the pivot, and scale the pivot on the y-axis. That would do a non-uniform squash of the perspective, but it would also mess up the sense of depth...

The easiest would just be to make a second camera, that shows all the icons, and then adjust the viewports of the individual cameras. Although that's not what you want :)


Shambler(Posted 2004) [#3]
Have you got a picture of what you want to achieve because you've lost me ^^

Couldn't you just move your icons?


John Pickford(Posted 2004) [#4]
*sigh* Why do I keep coming up with impossible ideas?

;-)


fredborg(Posted 2004) [#5]
Graphics3D 640,480,0,2
SetBuffer BackBuffer()

pivot = CreatePivot()
camera = CreateCamera(pivot)
RotateEntity camera,-50,0,0
ScaleEntity pivot,1.0,0.5,1.0
RotateEntity pivot,50,0,0

box = CreateCube()
PositionEntity box,0,0,10

light = CreateLight()

Repeat
	TurnEntity box,1,1,1	
	RenderWorld
	Flip
Until KeyHit(1)
This sort of does it, but as you can see the perspective is messed up...


_PJ_(Posted 2004) [#6]
Why not create two cameras. One taking up say the top 3/4ths ofthe screen as your ACTUAL viewport, then another under this as the backing for your icons?


Shambler(Posted 2004) [#7]
I think you could render the scene with the camera to the backbuffer then blit this to a smaller imagebuffer, clear the backbuffer then blit the imagebuffer back to the backbuffer.

You would have to shrink the image when you blit it, not sure how fast or what artifacts this would produce.


John Pickford(Posted 2004) [#8]
Malice, Not sure what you mean, as there would be no way match up the backing for my icons to the main view. The same problem exists.

Shambler, Yes that could work. I essentially need to render a bigger image and shift it physically 'up' the screen so the old centre is now 1/3 from the top. Another problem is that the backbuffer can't be bigger than the screen.


_PJ_(Posted 2004) [#9]
can CameraViewport accept negative X/Y values?


John Pickford(Posted 2004) [#10]
I don't think so.


Shambler(Posted 2004) [#11]
Forget my idea, although it works it's painfully slow -.-


napole0n(Posted 2004) [#12]
The only thing I can think of is rotating the camera around it's Z-axis, so that the horizon appears higher in the screen. And then move it along the Y-axis to compensate for any lost information you want in your scene.


Shambler(Posted 2004) [#13]
Hmm this a bit faster...rough and ready code.

Change part# to alter how big the division between the camera and panel is.

Graphics3D 800,600,32


;FPS
Global FPS_Timer
Global FPS_FrameCount
Global FPS_FPS


Global gw=GraphicsWidth()
Global gh=GraphicsHeight()
Global part#=0.75
Global part1#=1/part

SetBuffer BackBuffer()
Global image=CreateImage(gw,gh*part#)

camera=CreateCamera()

cube=CreateCube()
light=CreateLight(2,camera)
LightRange light,10
PositionEntity camera,0,0,-10
PointEntity camera,cube
ScaleEntity camera,1,part#,1

ClsColor 0,0,255



While Not KeyHit(1)

TurnEntity cube,1,0.8,0.7
RenderWorld()
blit()
;Draw buttons now
Text 0,0,"Mode"+" "+gw+" "+gh+" "+GetFPS()
Flip False

Wend



Function blit()

i=ImageBuffer(image)
b=BackBuffer()

y#=0

Repeat
CopyRect 0,y#,gw,1,0,y#*part#,b,i
y#=y#+part1#
Until y#=>gh

Cls 
CopyRect 0,0,gw,gh*part#,0,0,i,b

End Function



Function GetFPS()
FPS_FrameCount = FPS_FrameCount + 1
If MilliSecs() >= FPS_Timer
FPS_FPS        = FPS_FrameCount
FPS_FrameCount = 0  
FPS_Timer      = MilliSecs() + 1000
EndIf
Return FPS_FPS
End Function




Shambler(Posted 2004) [#14]
Hold on doesn't CameraViewport do this? ^^

Graphics3D 800,600,16
SetBuffer BackBuffer()

camera=CreateCamera()
CameraViewport camera,0,0,800,400

cube=CreateCube()

light=CreateLight(2,camera)
LightRange light,10

PositionEntity camera,0,0,-10
PointEntity camera,cube

ClsColor 0,0,255

While Not KeyHit(1)

TurnEntity cube,1,0.8,0.7
Cls
RenderWorld()
Flip False

Wend




John Pickford(Posted 2004) [#15]
That's what I want (in terms of where on screen the camera is looking) but I need the image to extend to fill the screen.
CameraViewport camera,0,-200,800,800


Would do the trick if it worked.


Difference(Posted 2004) [#16]
I'd very mush like to see this feature too.
I need to do tile renders (3*3 and similar) for print.
I too tried the viewport thing, but it does not alow negative offsets and larger than screensize viewports.

Could it maybe be done by adding some sort of "Virtual viewport" command?


napole0n(Posted 2004) [#17]
Can't you render to an imagebuffer that's larger than the screen? Like:

ImageBuffer = CreateImage(800,800)
SetBuffer ImageBuffer

RenderWorld

SetBuffer BackBuffer
DrawImage Imagebuffer, 0,-200,

Flip


John Pickford(Posted 2004) [#18]
You can't render to anything but the backbuffer and that can't be larger than the screen.


fredborg(Posted 2004) [#19]
If you run your game in a window, you can have a larger backbuffer than the window.


John Pickford(Posted 2004) [#20]
I didn't know that. Still no use, I'd like my game to work full screen and in any available resolution.


DJWoodgate(Posted 2004) [#21]
I'm not sure but I think this sort of thing can be done in Direct3d by modifying the projection matrix... http://www.mvps.org/directx/articles/tilerender/
I guess scaleentity modifies part of this matrix when it is applied to a camera, so maybe adding a CameraOffset command would allow this sort of thing. Or maybe not :)


big10p(Posted 2004) [#22]
I'd be surprised if you can achieve this, tbh. While I understand what you want to do, what you're asking the camera to render doesn't make any sense (to me, anyway). I mean, in the real world, if you're sat on a chair looking forward and you want to change the plane of your vision to be higher, you have to stand up. It seems to me that what you're wanting to do is render the view seen while standing AND sitting down.

Maybe you don't understand what I'm trying to say - I'm not always good at explaining things. :/ Maybe you can do some trickery by fiddling with the perspective matrix but I'm betting the result won't be what you're after.


ChrML(Posted 2004) [#23]
You can split the area around it into 360 degrees, then use the distance to calculate where to point the camera with Tin (for example 20 degrees more to left). Create a pivot at that position, and point the camera to it. Do it both for X and Y axes. Like this:



The green X is the camera, the red X is the target, while the gray line is the distance between.


Difference(Posted 2004) [#24]
I don't know about John, but pixelperfect tileable renders is exactly what I want. (Like in the link from DJWoodgate)


John Pickford(Posted 2004) [#25]
Big10p,
I'm sure it's possible. All I want is for the centre of the image to be 'off' centre.

Imagine rendering an 800,800 image, chopping off the top 200 lines and displaying what's left on an 800,600 screen. That would give the exact result I'm looking for. Though I would *like* to do it without rendering stuff I'm not going to display. Make sense?

ChrML,
Eh?


big10p(Posted 2004) [#26]
Yes, that makes sense - you want to do this:



Where the red cross (soz, jpeg blurred it) is the camera's focal point, the yellow box is the portion you actually want to display on-screen and the yellow cross is the centre point of the displayed portion.

But won't this cause problems when moving around? :
Imagine the two crosses are actually part of the 3D scene. If you gradually move the camera forward you will zoom in on the red cross. However, I think the viewer will see the yellow cross as the centre of focus, which will gradually disappear off the bottom of the screen as we get closer to the red cross. Do you see what I mean? Maybe this isn't a prob for you, I don't know.


John Pickford(Posted 2004) [#27]
Yes that's exactly what I want. No it won't cause me any problems at all. I think the red cross will be seen as the focus. The yellow cross is meaningless.

The bottoms third of my screen will be overlayed with a lot of stuff but I want the environment behind it. The important bit is the top 2 thirds and the red cross is the centre of THAT.


DJWoodgate(Posted 2004) [#28]
Well this should be a pretty simple addition if this projection matrix stuff works as I think. It's usually the case that things are a bit more complicated than I first think though! A CameraOffset (camera,x,y) function would allow you to move the projection plane. There is a caveat in that tileable render thing though about it not dealing with pre-transformed vertices whatever they are. Maybe terrains fall into this category?