Camera question

Blitz3D Forums/Blitz3D Programming/Camera question

ervin(Posted 2008) [#1]
Hi all.

I have a little problem that I'm wondering if someone can help me with.

I'm trying to display a simple mesh, x units wide and z units deep.
Let's say the mesh is 0 units tall, and so is totally flat.

Now, I want to raise the camera so that I get an overview of the mesh.
What I want to do is to have the near side of the mesh (ie. the closest left and right corners) to be in the bottom left and right corners of the viewport, regardless of the resolution.

For example, I'd like the closest side of this mesh to rest along the bottom of the viewport, with the left and right mesh corners tucked tight into the left and right viewport corners, no matter what resolution the window is.



I hope that all made sense.

Can anyone help me with this?
Thanks for any assistance.


Ross C(Posted 2008) [#2]
Your going to have to mess about with the camera a bit. This really all depends on the width of the mesh you have. You'll need to scale it appropriately and generally mess about with the values, experimenting.


Kryzon(Posted 2008) [#3]
You could position the camera\Mesh inside a modeler (like 3DS Max), checking the results in the B3D Pipeline "Preview" window, and then exporting it.


EDIT:
Now, if you want to create a Screen Quad (for displaying graphics, making fade-ins\outs), then it seems to work for me if you create it's vertices at: [ -0.5 ; -0.5 ] - [ +0.5 ; -0.5] - [ -0.5 ; +0.5 ] - [ +0.5 ; +0.5 ]

Then you can position and parent the screenquad to the camera by using EntityParent screenquad,Camera,False - the "false" being the parameter that tells to align the sprite with the camera with a mathematical precision. Then move the screenquad to 0,0,+1 locally, away from the camera.

Then scaling the thing using ScaleSprite screenquad, 2,1.5
This will keep the sprite's edges mathematically aligned with the screen edges, I believe.

Here's some code if you don't have a clue on how to do that:
Function CreateScreenQuad( Camera )

   Local mesh = CreateMesh()
   Local surf = CreateSurface(mesh)

   v0 = AddVertex(surf,-0.5,0.5,0)
   v1 = AddVertex(surf,0.5,0.5,0)
   v2 = AddVertex(surf,-0.5,-0.5,0)
   v3 = AddVertex(surf,0.5,-0.5,0)

   AddTriangle(surf,v0,v1,v2)
   AddTriangle(surf,v1,v3,v2)

   EntityParent mesh,Camera,False  ;aligns global position and rotation values.
   MoveEntity mesh,0,0,1                 ;moves +1 unit in the Z direction.
   ScaleEntity mesh,2,1.5,1              ;scales to occupy the entire screen.
 
   Return mesh                                ;optional, returns the mesh's Handle.

End Function

So, to use this function, you'd...

ScreenQuad = CreateScreenQuad( MainCamera )
EntityAlpha ScreenQuad,0
[...] ;and apply whatever effects and alpha you want to it.


PS: Do note that if you paint this mesh black (using Entitycolor and EntityFX 1), you can have a fade screen effect! simply making a rendering loop where you'll progressively changing the alpha of the screenquad until it reaches 1 (fade out) or 0 (fade in, showing the background). It's veeeery useful and makes you project look 3x more Pr0.
PS2: You could create the quad, then position at the screen with the function I gave you, and then reverse engineering the animation: recording the position\rotation of the mesh\camera into an array or something (there's an animation recording example in the Blitz3D Samples directory, if i'm not mistaken), and then invert that animation so as you play it the quad'd look like it's coming to sit in the screen.

Good luck.


ervin(Posted 2008) [#4]
Thanks very much for your help.
I'll give it a go a bit later today.

Thanks also for the tip on a screen fade, as I'll need to do that too at some point.


ervin(Posted 2008) [#5]
Fantastic - it works nicely! Thanks.

The only change I made was to add resolution independence.
;add these lines
Local gfxWidth#=GraphicsWidth()
Local gfxHeight#=GraphicsHeight()

;change this line
ScaleEntity mapSectionMesh,2.0,(gfxHeight/gfxWidth)*2.0,1.0



Kryzon(Posted 2008) [#6]
Resolution independence? you gotta be kidding me, that's amazing. I wasn't able to figure it out when I wrote it, some time ago.
Thanks you too for that :D


ervin(Posted 2008) [#7]
I'm glad I could be of some use. :o)

Another question if I may...

I've now got it looking like this:


I want it to look like this (mock-up):


I need the top of the mesh to be "tilted" into the screen, as if the mesh was being rotated 30 degrees around the x axis. RotateEntity however would rotate the entire mesh along the middle of the screen and the bottom of the mesh would come "out of" the screen and disappear.
I need the bottom of the mesh to stay where it is.

Can anyone help?


big10p(Posted 2008) [#8]
Parent a pivot to the bottom of the mesh and rotate that instead.

Or

Use PositionMesh to move the mesh origin to the bottom.


ervin(Posted 2008) [#9]
Thanks big10p.

I haven't figured out how to do it just yet... but I think using the pivot might be the way to go.

[EDIT] I can figure out how to parent the pivot to the mesh, and once that is done I rotate the pivot, and the mesh rotates. But the bottom of the mesh is disappearing "out of" the viewport. I don't know how to attach the pivot to the bottom of the mesh, so that the bottom of the mesh stays where it is.

Thanks for any help.


Kryzon(Posted 2008) [#10]
You could move the pivot to sit right in the bottom vertices (it doesn't really need to be in mid-bottom, just at the lower corners should do the trick if you only turn in the X Axis). Here's how the final function should be:
Function CreateScreenQuad( Camera )

   Local mesh = CreateMesh()
   Local surf = CreateSurface(mesh)

   v0 = AddVertex(surf,-0.5,0.5,0)
   v1 = AddVertex(surf,0.5,0.5,0)
   v2 = AddVertex(surf,-0.5,-0.5,0)
   v3 = AddVertex(surf,0.5,-0.5,0)

   AddTriangle(surf,v0,v1,v2)
   AddTriangle(surf,v1,v3,v2)

   EntityParent mesh,Camera,False  ;aligns global position and rotation values.
   MoveEntity mesh,0,0,1                 ;moves +1 unit in the Z direction.
   ScaleEntity mesh,2,( GraphicsHeight()/GraphicsWidth() ) * 2,1              ;scales to occupy the entire screen. Now adapted to resolution :D
  
   ;Now that all the vertices were modified and have their new positions to cover the screen, we need to grab one of the last two vertices (the ones with index 2 or 3. They are respectively the 3rd and 4th but since Blitz3D stars counting from 0...), since they are sitting in the bottom and that's the edge you wanna keep rotation-intact.

   VX# = VertexX( GetSurface(mapSectionMesh,1), 3 ) ;the "3" in the end is for the last vertex (the 4th one, but starting from 0 makes it 3).
   VY# = VertexY( GetSurface(mapSectionMesh,1), 3 ) 
   VZ# = VertexZ( GetSurface(mapSectionMesh,1), 3 )
   
   TFormPoint VX,VY,VZ,mesh,0  ;generates a global 3D "point" coordinate from the vertex positions we just read in.

   Pivot = CreatePivot()
   PositionEntity Pivot,TFormedX(),TFormedY(),TFormedZ()
   EntityParent mesh,Pivot
   ;Now you can turn this pivot only on the X-Axis (the first axis parameter in commands such as Turn or Rotate Entity). 

   Return Pivot                                ;well, now that you want the pivot, you'd get this function's return and turn it accordingly, only in the X-Axis.

End Function

Using it should be something like...
RotPivot = CreateScreenQuad( MainCamera )

While [...]

   TurnEntity RotPivot, value, 0, 0 ;Only turning in X-Axis

Wend


That should do it. Please tell how did that go!


ervin(Posted 2008) [#11]
It works!
Thanks so much for your help.