2d camera?

BlitzMax Forums/MiniB3D Module/2d camera?

jkrankie(Posted 2009) [#1]
Hi all,

i don't suppose anyone has got any code floating around that makes the MiniB3D camera behave like it would in Max2D, i.e. have 0,0 in the top left corner and 800*600 or whatever in the bottom right? I was looking at the possibility of making a 2d-in-3d style game based on some existing code that uses these coordinates, and just wanted to replace the drawing commands and not the logic.

Cheers
Charlie


ima747(Posted 2009) [#2]
Sory I don't have a sample off hand but look into CameraProjMode() setting the projection mode to orthographic essentially removes the depth perspective from the view (but not depth itself), then it's just a matter of setting CameraZoom and the distance to your objects. you will probably need to make a converter between pixel positons and 3d positions as 800 is a pretty big number in 3d unless you scale everything up. However one nice thing about using a 3d as 2d view is that the scale will stay the same regardless of the screen resolution (as long as you don't change the screen ratio) so moving your object 2 units to the right does the same thing at 800x600 as it does at 1280x960, all the smoothing and pixel precision is taken care of by the 3d engine.

You can do it without using orthographic view if you want to keep visible depth but I found it's a bit harder, though far from impossible to get the camera lined up right. the bigger problem is getting the layer order right and keeping track of it. if you want to draw everything at the same depth to keep the same scale, use collision etc. you need to use EntityOrder() to set the draw order of you get graphical glitches from objects drawing through each other.

Hope that gets you started. I'm using some 3d as 2d in one of my current projects, I'll try to dig out a sample if you need more help.


jkrankie(Posted 2009) [#3]
some absolutely for dummies sample code would be awesome, especially if as you say the scale would stay the same despite the resolution.

either way i'll take a look at using orthographic view.

Cheers
Charlie


jkrankie(Posted 2009) [#4]
ok, after a bit of fiddling, i managed to come up with the following code, which is ok but the y coords appear upside down (as they should i guess, cartesian coordinates are this way up). is there any way to 'flip' the camera upside down so that 0,0 appears at the top left instead of the bottom left?

i know that it wouldn't be too difficult to allow for this in my code, but it would mean changing quite a lot of stuff, and i'd like to avoid this ideally.

Import sidesign.minib3d

Graphics3D 800, 600

camera:TCamera = CreateCamera()
PositionEntity camera, 400, 300, - 400
CameraRange (camera, 1, 2000)

light:TLight = createLight()
RotateEntity light, 400, 300, -100

'cube 0,0
cube1:TMesh = createCube()
'EntityColor cube1, 255, 0, 0
ScaleEntity (cube1, 10, 10, 10)
PositionEntity cube1,0,0,0

'cube 800,600
cube2:TMesh=CreateCube()
EntityColor cube2, 0, 255, 0
ScaleEntity cube2, 5, 5, 5
PositionEntity cube2, 800, 600, 0

Local x:Float = 0, y:Float = 0, z:Float = 0
Local count:Int = 0
While Not KeyDown(KEY_ESCAPE)
	count:+1
	RotateEntity(cube1, count, count, 0)
	Local d:Float
	If KeyDown(KEY_UP)
		 d = -3
		TranslateEntity(cube1, 0, d, 0)
	End If
	If KeyDown(KEY_DOWN)
		 d:Float = 3
		TranslateEntity(cube1,0,d,0)
	End If
	If KeyDown(KEY_LEFT)
		 d:Float = -3
		TranslateEntity(cube1, d, 0, 0)
	End If
	If KeyDown(KEY_RIGHT)
		 d:Float = 3
		TranslateEntity(cube1, d, 0, 0)
	End If
	
	RenderWorld
	
	Flip

Wend

End 


Cheers
Charlie


Robert Cummings(Posted 2009) [#5]
untested:

Function SetView( x1, y1, x2, y2, z1, z2)
	'camera 
	glMatrixMode(GL_PROJECTION) 'work on the projection matrix
	glLoadIdentity()
	glOrthof(x1 , x2 , y2 , y1 , z1 , z2) 'left, right, top, bottom, near, far - coordinate system
	glMatrixMode(GL_MODELVIEW)
end function


I'm working in C++ now so its just from memory but from what I know, max uses standard opengl calls and constants under the hood.

glOrthof sets your opengl viewport to remove all perspective and act as 2D while setting the view dimensions to whatever you want. For example SetView(0 , 0 , 640 , 480 , -1 , 1); Should give a basic 2D flat rendering window.

Might be rotated wrong and need a camera transform.

If you wanted to do this on top of existing 3D you need to use the opengl push and pop, which is a way of keeping the state intact. Middleware for AAA games use push and pop to keep the state of existing rendering engines saved while they mess with stuff.

Look on opengl.org docs - they are comprehensive and will give you a command reference, it just takes looking.

glOrthof will actually remove any kind of depth though, so if you move something far away, it will appear the same size still. It should work out of the box as above after setting up minib3d normally.


Robert Cummings(Posted 2009) [#6]
Oh and give the Z values a massive amount of space if you can't see anything. That is after all, your Z buffer.

The x,y stuff: you larger values to fit more on screen (or was that smaller? can't remember) you use it to determine the coordinate space you work in, so it has the affect of scaling the entire world without changing your coordinates if used like that.


jkrankie(Posted 2009) [#7]
thanks, but i don't get it :(

any chance of an example?

Cheers
Charlie


Robert Cummings(Posted 2009) [#8]
Just call that function and it will make your game 2D? its safe to call it at any time.


jkrankie(Posted 2009) [#9]
well, i couldn't get that to go. i figured out orthographic view via the camera project example, although i had to fiddle with camera zoom to get it to look right.

thanks everyone for the help :)

Cheers
Charlie


Nigel Brown(Posted 2009) [#10]
@jkrankie, would really like to do this myself any chance of you posting your findings?


jkrankie(Posted 2009) [#11]
@Nigel, sure thing. While i strongly suspect that there is a better way of doing it, this suits my needs. Basically i'm positioning the camera at 400,-300 (to effect an 800*600 2d screen), the only thing to remember is that you will need to draw your stuff at -y.

Here is a quick bit of code that demonstrates this. You can change the resolution to what ever you want and it will all scale ok if you keep to 4:3 screen ratios. if you want to do wide screen you'll have to zoom the camera out a bit more

SuperStrict
Import sidesign.minib3d

graphics3d 800,600,32,7,70

'create a camera
Local camera:tcamera=createcamera()

'move the camera 
positionentity camera,400,-300,-400
camerarange camera,1,2000

'set projection mode to orthograpic
cameraprojmode camera,2
'zoom the camera out a long way.
camerazoom camera,0.0025

Local light:tlight=createlight(2)
positionentity light,400,-300,-10

'quick point type
Type point

	Field x:Float,y:Float
	Field xvel:Float,yvel:Float
	Field mesh:tmesh=Null
	
End Type

Local spheres:point[50]
'create some spheres
For Local i:Int=0 To 49
	spheres[i]=New point
	spheres[i].x=Rand(0,800)
	spheres[i].y=Rand(0,600)
	spheres[i].xvel=Rand(-5,5)
	spheres[i].yvel=Rand(-5,5)
	spheres[i].mesh=createsphere(4)
Next

'begin main loop
Local count:Float=0
While Not KeyHit(key_escape)
	
	'update everythin as if it were 2d
	For Local i:Int=0 To 49
		spheres[i].x:+spheres[i].xvel
		spheres[i].y:+spheres[i].yvel
		
		If spheres[i].x<0 
			spheres[i].x=0
			spheres[i].xvel=-spheres[i].xvel
		Else If spheres[i].x>800
			spheres[i].x=800
			spheres[i].xvel=-spheres[i].xvel
		EndIf
		
		If spheres[i].y<0 
			spheres[i].y=0
			spheres[i].yvel=-spheres[i].yvel
		Else If spheres[i].y>600
			spheres[i].y=600
			spheres[i].yvel=-spheres[i].yvel
		EndIf
		
		rotateentity spheres[i].mesh, count, count, count

                'scale up the spheres, remember that your camera is quit a distance from 0
		scaleentity spheres[i].mesh,20,20,20
		
		
		'draw the mesh, but - the y value
		positionentity spheres[i].mesh,spheres[i].x,-spheres[i].y,0
		count:+0.01
	Next
	
	renderworld
	Flip
	
Wend

For Local i:Int=0 To 49
	freeentity spheres[i].mesh
Next

EndGraphics()

End




ima747(Posted 2009) [#12]
if you roll the camera upside down (making y work the way you would like, but inverting X) you could then yaw it 180deg (thus inverting the inverted X) and position it at 400,300,400 you might fix the Y problem... untested just a thought. this would turn things upside down, but you could roll the meshes, or if you use sprites you can just set them to match the camera roll (they do by default)...

come to think of it -y is probably the easier fix hehe, but if you were to be using this as a basis for porting an existing 2d game to 3d for effects or whatever it could make life easier than finding everything at interacts with a y value...

Thanks for the sample!


jkrankie(Posted 2009) [#13]
Yep, i was porting a 2d game. Also, wouldn't rolling the camera round make the x axis the wrong way round?

Cheers
Charlie


ima747(Posted 2009) [#14]
yea, that's why you'd also need to yaw the camera (making it face the other way, which should reverse X and since it's reversed it will set it right) and then put it on the other side of 0 since it's facing backwards

thinking about it again, that would be just pitching it 180, that would do the upside down and the backwards at once...