Moving the Camera vs. Moving the Terrain
Blitz3D Forums/Blitz3D Beginners Area/Moving the Camera vs. Moving the Terrain
| ||
Hi guys, Instead of moving the camera I'd like to move the terrain below to achieve the same effect. I want my camera being static @ x=0, y=0, z=0 but i want the movement of the terrain below give the illusion of the camera moving. I've played around a little but somehow my brain is locked up and I'd really appreciate a hint on where to continue. If you try out my program that I've come up with this far, you'll see that when using Left-Shift the camera is moving and everything is working as designed. But strange things happen when i try to simulate the same behavior without Left-Shift pressed (i.e. when i move the terrain itself, and try to turn the view using a pivot.) Program keys: WASD - navigation Arrow-Keys - turning and tilting Left-Shift - Use normal camera movement. R - reset everything and start over Const KEY_ESC= 1 Const KEY_W= 17 Const KEY_A= 30 Const KEY_S= 31 Const KEY_D= 32 Const KEY_UP= 200 Const KEY_DOWN= 208 Const KEY_LEFT= 203 Const KEY_RIGHT= 205 Const KEY_R= 19 Const KEY_LEFTSHIFT= 42 Graphics3D(800, 600, 0, 2) Local plane = CreateTerrain(8) EntityColor(plane, 127, 127, 255) PositionEntity(plane, -4, -2, -4) Local cam=CreateCamera() Local camPivot=CreatePivot(cam) Local light=CreateLight() While Not KeyDown(KEY_ESC) If KeyDown(KEY_R) ;reset everything EntityParent(plane, 0) RotateEntity(cam, 0, 0, 0) PositionEntity(cam, 0, 0, 0) RotateEntity(plane, 0, 0, 0) PositionEntity(plane, -4, -2, -4) FreeEntity(camPivot) camPivot=CreatePivot(cam) EndIf Local xmov = KeyDown(KEY_A)-KeyDown(KEY_D) Local zmov = KeyDown(KEY_W)-KeyDown(KEY_S) Local xturn = KeyDown(KEY_UP)-KeyDown(KEY_DOWN) Local yturn = KeyDown(KEY_LEFT)-KeyDown(KEY_RIGHT) If KeyDown(KEY_LEFTSHIFT) ;moving by camera, static entity EntityParent(plane, 0) MoveEntity(cam, xmov * 0.1, 0, zmov * 0.1) TurnEntity(cam, xturn, yturn, 0) Else ;static camera, moving entity EntityParent(plane, camPivot) MoveEntity(plane, xmov * -0.1, 0, zmov * -0.1) TurnEntity(camPivot, -xturn, -yturn, 0) EndIf UpdateWorld() RenderWorld() Flip() Wend |
| ||
Blitz3D doesn't work with matrices, which would fit like a glove to this coordinate-context changing you want. When you move with the camera itself (with left shift), it's in its own space. When you move everything while the camera is standing still, you need to move and rotate objects within the camera's local space so it appears that it's the camera itself that is moving. While Blitz3D provides a way for you to know the value of a vector transformed into different spaces, it doesn't for rotations. So we do have a way to fake the camera's movement, but not its rotation. MoveEntity works locally: doing a MoveEntity(entity,0,0,+1) will move any entity forward, whatever direction it's facing. Doing the same with rotations is not as simple. Anyway, here's what I came up with (I've modified your code directly): Const KEY_ESC= 1 Const KEY_W= 17 Const KEY_A= 30 Const KEY_S= 31 Const KEY_D= 32 Const KEY_UP= 200 Const KEY_DOWN= 208 Const KEY_LEFT= 203 Const KEY_RIGHT= 205 Const KEY_R= 19 Const KEY_LEFTSHIFT= 42 Graphics3D(800, 600, 0, 2) Local cam=CreateCamera() Local camPivot=CreatePivot() Local light=CreateLight() Local FPSTimer = CreateTimer(60) Local plane = CreateTerrain(8,camPivot) ;Parented to 'camPivot', which is the "peg" that will move everything. Any object in the level needs to be parented to this. EntityColor(plane, 127, 127, 255) PositionEntity(plane, -4, -2, -4) While Not KeyDown(KEY_ESC) WaitTimer(FPSTimer) ;Limit the frame-rate so it doesn't use 100% CPU. If KeyDown(KEY_R) ;Reset everything. ResetTransform(cam) ResetTransform(camPivot) EndIf Local xmov = KeyDown(KEY_A)-KeyDown(KEY_D) Local zmov = KeyDown(KEY_W)-KeyDown(KEY_S) Local xturn = KeyDown(KEY_UP)-KeyDown(KEY_DOWN) Local yturn = KeyDown(KEY_LEFT)-KeyDown(KEY_RIGHT) If KeyDown(KEY_LEFTSHIFT) ;Moving by camera, static entity. TFormVector(-xmov*0.1, 0, zmov*0.1, cam, 0) ;Transform from 'cam' to 'world'. TranslateEntity(cam, TFormedX(), TFormedY(), TFormedZ()) TurnEntity(cam, xturn, yturn, 0) Else ;Static camera, moving entity. TFormVector( xmov*0.1, 0, -zmov*0.1, cam, 0) ;Transform from 'cam' to 'world'. TranslateEntity(camPivot, TFormedX(), TFormedY(), TFormedZ()) TurnEntity(cam, xturn, yturn, 0) EndIf UpdateWorld() RenderWorld() Flip() Wend Function ResetTransform(entity%) PositionEntity(entity,0,0,0) RotateEntity(entity,0,0,0) ScaleEntity(entity,1,1,1) End FunctionIt still uses the camera's own rotation when not holding the shift key, but when doing so, the movement at least is all faked. I used TFormVector to retrieve a transformed movement-vector. I want to strafe left and right, so I transform a local 'xmov*0.1' vector on the entity's local X axis to the world-space coordinate system, which takes into account the entity's rotation. It'll move left wherever it may be facing. Since I'm already using a transformed vector, I can't use MoveEntity (which also works similarly, working locally within each entity's local-space); so I use TranslateEntity which works with world coordinates only: I transformed my vector into world-space, so I need to use a function that expects world-space values. An easier way to imagine what TFormVector does: • Look into any random direction, and point with your hand towards it: this direction is your Z+ local axis. • Now consider the world's Z+ axis - it won't point in the same direction. You would have to use TFormVector(0,0,+1, Me, 0) to retrieve with TFormedX(),Y() and Z() the direction your arm would be pointing in relation to the world's origin. Last edited 2011 |
| ||
Thank you very much! That's a lot more than I hoped for! Now I have a lot to check out but at a quick glance your code seems very good and fitting for my intended usage. Rotating the camera in place @(0, 0, 0) will probably work perfectly well, since the original problem was that I didn't want to get very high coord-values for the camera, to avoid the loss of floating point precision. EDIT: Even ymov (new variable) works when added to TFormVector(). Nice! Last edited 2011 |
| ||
An easier way to imagine what TFormVector does: • Look into any random direction, and point with your hand towards it: this direction is your Z+ local axis. • Now consider the world's Z+ axis - it won't point in the same direction. You would have to use TFormVector(0,0,+1, Me, 0) to retrieve with TFormedX(),Y() and Z() the direction your arm would be pointing in relation to the world's origin. Ah, beautiful. I've always wanted to understand that command more, but I haven't been able to fully grasp it 'til now. I knew what it would do, but not how to use it. |