Parallel Projection

Hi everyone…



Is it possible in jME to use parallel projection?

It seems that the frustum can only be set to a rectangular based pyrimad, not a box shape. I’ve also tried the Ortho related methods, but no succes.

I’m not quite sure I understand the problem. There are two methods of rendering perspective and orthographic. Orthographic should give you the parallel projection you need. What is happening that is undesired when using orthographic?

I’m rather new to jME and OpenGL, so I’ll try and explain better what I’m trying to achieve:



What I want is to project my 3D scene in such a way that distance does not affect the size of the 3D object. It should however still affect the x,y,z coordinates. This way any lines that run parallel will also be projected parralel. In my highschool drawing classes this was called “parellel projection”.



In terms of games think of stuff like Simcity 2000:





I’ve gotten close to that effect by using a really low Fov for the camera, but there is still a big difference for objects really close and really far. A Fov of 0 of course did not work since then the frustum effectivly becomes a line. At least, I have not found a way to make it a “box” rather than a line or based on a pyramid.



Is there any way to do this using setOrtho()? I’m not sure what it does exactly… I see it uses the size of the screen. If that means it uses the quad of the screensize to calculate the frustum rather than the point in the middle of your screen that’d be great. But I’m really confused on how the camera works for objects rendered in Ortho mode. I’m lucky if anything show up at all, and when it does it usually looks really messed up.

Ortho is typically used when making 2D games or GUI’s. SimCity also uses it (or would at least have used it if the drawing was done through OpenGL :)).



What makes it look 3D is simply the way the images are painted, and a render que drawing buildings and the like in front of cars.



If making a strategy game with the todays tech, you might want to grab inspiration from newer titles such as ground control.

In OpenGL there is the possibility to set the view to use parallel projection, so ortho mode is true 3D, just not using a frustum but a cube. You don’t need to paint isometric 3d sprites and place them on quads to use it. This projection mode is mainly used for tech apps like CAD and the likes.



The only thing with jME is that this mode cannot be used currently as it seems. At least not by simply placing objects in the ortho queue. They don’t get rendered, I just tried it out (well, could be because my PC at work is cr*p).



Maybe by using setOrtho() from the renderer in the draw method rather than placing objects in the ortho queue instead?

Well, I understand Simcity 2000 uses 2D tiles. That doesn’t mean it’s impossible to get the same effect using 3D objects. A box based frustum would accomplish just that.



Maybe it’s impossible using normal OpenGL techniques… I have no idea. But considering what OpenGL was designed for (SGI workstations and the like) I thought it might be possible, since this type of drawing is often used for technical designs because it gives you a very good idea how big things are compared to each other. (Ok, just before I was to hit post I saw Batman.ac’s reply!)



Of course, in some games that could be very handy too. I wouldn’t make it the only available drawing mode in a game, but switching to it would be nice.



I think can get close to the effect by putting the camera really far away, and using a really far away “near” value for the frustum. I just hope this won’t effect culling performance, mess up the depth buffer or cause other weirdness I don’t know about. I’d be nice to avoid having to use this method.

"llama" wrote:
Maybe it's impossible using normal OpenGL techniques.. I have no idea. But considering what OpenGL was designed for (SGI workstations and the like) I thought it might be possible, since this type of drawing is often used for technical designs because it gives you a very good idea how big things are compared to each other. (Ok, just before I was to hit post I saw Batman.ac's reply!)

No it is perfectly possible with OpenGL - i got an OpenGL book totally relying on ortho projection. It's just that currently I cannot figure out how to make it work with jME.

When I am at home later today, I will try to find out what has to be done.

Ok, looking at LWGLRenderer.java to see what happens with setOrtho(). It actually calls GLU.gluOrtho2D() so it seems this is for 2D orthographic projection not 3D orthographic projection.



This could probably replaced with G11.glOrtho() which according to a quick google would produce a parallel projection.



Parameters:

left, right

Specify the coordinates for the left and right vertical clipping planes.
bottom, top

Specify the coordinates for the bottom and top horizontal clipping planes.
near, far

Specify the distances to the nearer and farther depth clipping planes. These values are negative if the plane is to be behind the viewer.


That sounds to me like it defines a "box", where everything within the box will be on screen. I was calling this a "frustum" before, I believe that's technically the correct term for a box shape as well, OpenGL just seems to use this term for pyramidal frustum. Just saying it to clear up any confusion I might have caused with that.

I quickly replaced this code in setOrtho, and there's my perfect parallel projected rotating cube :) Need some more testing/reading to see if everything works like it should right away (culling, depth buffer, etc.)

Of course the camera doesn't work (I assume cause it's in a different matrix), so I'll check how cameras work in jME and OpenGL, and wether it's possible to have 1 "camera" in both projection modes that shows somewhat the same stuff. If that doesn't work perhaps I can just rotate and move the entire scene around 0,0,0?

Well, I should start thinking before writing…



LWJGLRenderer.setOrtho uses GLU.gluOrtho2D, which sets a 2D ortho projection. What you would want instead is something which uses GL.glOrtho as this lets you specify near and far plane. Currently there is no way in jME to achieve this - or you would need to extend the Renderer interface and provide new methods.

"batman.ac" wrote:
Well, I should start thinking before writing...

LWJGLRenderer.setOrtho uses GLU.gluOrtho2D, which sets a 2D ortho projection. What you would want instead is something which uses GL.glOrtho as this lets you specify near and far plane. Currently there is no way in jME to achieve this - or you would need to extend the Renderer interface and provide new methods.

Yes, as you can see I posted just before you about my results with this. I created a quick new method setOrtho3D. That could be useful the same way setOrtho/setOrthoCenter are used today, eg if you want to draw a quick overlay of a 3D orthographic projected map. (just forceDraw it etc.)

I, however, want my entire scene to render in this projection, and I want to be able to switch between the two. I'll need culling for both modes too. This probably means I have to adapt the camera classes as well (that's where it looks like intersection is calculated for culling). It would nice to have some of those camera convinience methods available in Ortho3D mode too. (if I can get them to work)

My question is, is it worth putting this stuff in jME or should it remain my own obscure little patch?

no, its definelty usefull!



It adds an entirely new perspective to the engine with many new games that could be made with it.



However, having said that. You will also need to adapt collision detection, culling (as u already know), and the rendering queue. And create a system whereby the order of rending is changed according to the place of the sprite…



also an animation system changing texturestate quickly…



as u can see, the list is quite large and they are pretty tough to implement. Good luck :slight_smile:



DP

"DarkProphet" wrote:
You will also need to adapt collision detection,

Hmm, not sure about this. The model and world coordinates of the triangles won't change, only the projection. Collision detection and everything else which does not rely on view projection should not be affected.

Wow, a fellow goes to sleep and totally misses out on the conversation. :slight_smile: First, let me say that my response was me forgetting that we use Ortho2D, and that’s what led to me not understanding what your problem was.



Because setting your projection to Ortho (3D) would be a one time thing for you (i.e. this is not GUI elements but the scene itself), this should be a one time deal.



We could perhaps introduce a ProjectionState with PS_PERSPECTIVE, PS_ORTHOGRAPHIC. You could then set this to which ever parent node you want and that node + children would then be rendered in that projection. You could then mix modes if you wanted to (for whatever reason).



I don’t know the feasibility of this, and it would require a bit of experimentation, but it’s a possible solution.



Collision detection - wouldn’t need changing (that’s a mathematical problem, not a rendering).



Culling - If setting the projection could someone define the frustums, we would be ok.



Rendering Queue - wouldn’t require any changes if we used a state. (That is if the state works like I think it will).



I’m not sure what you are talking about regarding sprites and animation systems, that has nothing to do with the projection method.

"DarkProphet" wrote:
no, its definelty usefull!

It adds an entirely new perspective to the engine with many new games that could be made with it.

However, having said that. You will also need to adapt collision detection, culling (as u already know), and the rendering queue. And create a system whereby the order of rending is changed according to the place of the sprite...

also an animation system changing texturestate quickly....

as u can see, the list is quite large and they are pretty tough to implement. Good luck :)

DP

Yipe!
Can you explain some things though? Why would I need to change al* of those things? I can understand culling (after all, there's a difference between what's in the viewport). Thankfully a box intersection should be doable even with my math skills.

Collision detection: the actual position of an object will not change in Ortho 3D mode, just the way it appears on the screen. Think of ortho3D vs Perspective projection as a different "lense" for your camera system. If two triangles intersect in prespective, they'll also intersect in ortho3D, *and* be drawn that way.

Same thing really for changing the render order. Since the objects are exactly the same as in prespective, why would I need to change anything?
If I have to change anything wouldn't it be mostly reuse of existing code? And I know what a sprite is but I'm not sure what you mean by it here? All objects are still 3D..

Rendering queue.. probably trivial right? In fact is it needed at all? If you want to do some overlay drawing you can use the existing orthoBucket, if you want to switch perspectives, well right now I'm looking into doing this by "changing" the camera (like the lens anology) so you'll render either Ortho3D or Perspective, so they don't need to be seperated in the queue. I'm realising this might not be "the jME way" though, maybe a RenderState or something is better? or a new state? ("ProjectionState") Then I can avoid the queue except for overlay drawing.. and you can actually mix different prespectives.. though I image this will look weird for most things (issues with Lights etc.) I guess the biggest advantage there would be not having to setFreakingOrhto3D() all the time.. maybe it will make my coding easier too.

Why would I need to make a new texture animation system? Or are you just trying to fool me into making one? ;) Or am I missing something obvious?

As a first assesment I think I can reuse LWGL GLU methods for changing the camera, and it looks like there won't be any problems with different matrixes and the depthbuffer (OpenGL newbie here). So if DP is a little wrong on some of the things here it shouldn't be TOO much work...

oops! completely misinterpreted what you meant…



I see now that all the stuff that i listed are not needed. I was imagining it in 2D like how i used to do it… ://



lol, now can u see why i said what i said…animation libraries, sprites, overalys…hehehe



DP lookin like a fool!

Huhu, and I didn’t even know there was such a thing as Ortho 3D



Having it accessable from jME would be good :slight_smile:

However, doing this extra tracking, let alone the extra matrix calculations would be a waste if you don't actually need them. Plus many of the current calls don't apply to both modes. (Change the ortho when you call setFrustum? Rolling Eyes). That's why I suggest making new methods for setting the Ortho3D camera (PROJECTION camera), with it's own names. However, I propose another method; something like setProjectionMethod which could be PM_PROJECTION (ortho 3d) PM_MODELVIEW (prespective, and default) PM_BOTH. When you call one of the "convinience" methods, such as lookAt, setLocation, setDirection it will be done according to what you've set there (whatever maps to GLU Razz). Maybe when someone feels like it they can write some methods that set the far / near plane for both at once and split up methods some more, I'm busy enough for now.


That's where the RenderState I suggested would come in (my post may have been lost as there were a couple posts around the same time). You would have a ProjectionState that defines either perspective or orthographic with perspective being the default.

You could then set the perspective at any level of the scene graph (the whole thing as orthographic, everything as perspective but have labels in the RTS be orthographic). This will handle all the state tracking of the projection using the already existing system.

Camera culling is still based on mathematical concepts of the frustum (which is perspective), but we can still use it for culling, we will just get false positives (things that aren't on screen being rendered). But *should* not get false negatives (things that are on screen not being rendered). Which at least as a proof of concept should be fine (the majority of the scene will still be culled).
"mojomonk" wrote:
However, doing this extra tracking, let alone the extra matrix calculations would be a waste if you don't actually need them. Plus many of the current calls don't apply to both modes. (Change the ortho when you call setFrustum? Rolling Eyes). That's why I suggest making new methods for setting the Ortho3D camera (PROJECTION camera), with it's own names. However, I propose another method; something like setProjectionMethod which could be PM_PROJECTION (ortho 3d) PM_MODELVIEW (prespective, and default) PM_BOTH. When you call one of the "convinience" methods, such as lookAt, setLocation, setDirection it will be done according to what you've set there (whatever maps to GLU Razz). Maybe when someone feels like it they can write some methods that set the far / near plane for both at once and split up methods some more, I'm busy enough for now.


That's where the RenderState I suggested would come in (my post may have been lost as there were a couple posts around the same time). You would have a ProjectionState that defines either perspective or orthographic with perspective being the default.

Well, I suggested ProjectionState right about the same time as you did. We even gave it the same name :) Look at my post just a few minutes after your's.

But as I understand it RenderStates apply to Spatials. We still have to draw those spatials and we draw them in a different glMatrixMode that the camera is in, so the transform and multimatrix our camera currently sets is useless. The part of my post you quoted is on how we should sync (and NOT synch) these two different cameras...


You could then set the perspective at any level of the scene graph (the whole thing as orthographic, everything as perspective but have labels in the RTS be orthographic). This will handle all the state tracking of the projection using the already existing system.


Exactly my plan.. creating a new Renderstate shouldn't be too hard.


Camera culling is still based on mathematical concepts of the frustum (which is perspective),


Except our frustum is now different in those two different glMatrixModes. That's why I think the API of Camera should change from contains(BoundingVolume) to contains(BoundingVolume, ProjectionState).

I think as a first goal I'll implement the "conviniece methods" in Camera to work on both projections. We'll save the discussion on culling, and how to sync between modes for when it's shown this will work..


but we can still use it for culling, we will just get false positives (things that aren't on screen being rendered). But *should* not get false negatives (things that are on screen not being rendered). Which at least as a proof of concept should be fine (the majority of the scene will still be culled).


Well, it depends on the difference between the frustum in MODELVIEW and the ortho in PROJECTION. Drawing a few extra isn't that bad, not drawing a few that should be drawn is VERY bad. For a proof of concept I guess I'll live with it. Considering it will probably rotate your FPS counter it might be the least of or worries at that time :)

Feel free to play with this, as it’s not something I’ll be able to get around to any time soon.



I’m actually leaning away from the render state as we discuss this, because you are right, there will require camera changes (specifically in onFrustumChange) and possibly changes to LWJGLRenderer (the draw method sets the matrix mode). Both of these are out of the perview of a render state.



However, adding another queue, or sublimenting the current ortho queue with a 3D component might work.



Not really certain, playing around and experimenting would be needed, but if you come up with a clean elogant solution, let us know. If not, I’ll try looking into something as soon as I can.

Ok, I hope to have something to show soon. It might be a little less work than I expected after all…