'Drag' Scrolling in 3D
Blitz3D Forums/Blitz3D Programming/'Drag' Scrolling in 3D
| ||
I'm thinking of implementing a Black & White style drag scroll in my game. The problem is I have no idea where to start. How do I translate a 2D vector (from the mouse) to a 3D movement in my game world? Any pointers? |
| ||
I'm doing something similar in my current project. All I do is use MouseXSpeed() and MouseYSpeed() values to move the camera in the X and Z axes when the right mouse button is pressed. Seems to do the trick. |
| ||
I need it to work whatever the orientation of the camera and at the right speed for the distance of the bit of the landscape I'm grabbing. The maths is a bit beyond me. |
| ||
Hi, I never played B&W so I'm not sure if you mean entity or camera movement, here's a camera method, is this right? Use LMB to drag, and cursors left/right to rotate Graphics3D 800,600,32,2 piv=CreatePivot() cam=CreateCamera(piv) PositionEntity piv,0,8,0 RotateEntity cam,30,0,0 light=CreateLight() RotateEntity light,30,30,0 plane=CreatePlane() EntityColor plane,100,200,200 Dim box(200) box(1)=CreateCube() ScaleEntity box(1),Rnd(.2,.4),Rnd(1,1.5),Rnd(.2,.4) EntityColor box(1),Rand(100,255),Rand(100,255),Rand(100,255) For i=2 To 200 box(i)=CopyEntity(box(1)) ScaleEntity box(i),Rnd(.2,.4),Rnd(1,1.5),Rnd(.2,.4) EntityColor box(i),Rand(100,255),Rand(100,255),Rand(100,255) PositionEntity box(i),Rnd(-50,50),.5,Rnd(-50,50) Next While Not KeyDown(1) If MouseHit(1) Gosub moveLoop If KeyDown(203) TurnEntity piv,0,1,0 If KeyDown(205) TurnEntity piv,0,-1,0 UpdateWorld RenderWorld Flip Wend End .moveLoop ;Clicked X,Y cx#=MouseX() cy#=MouseY() ex#=EntityX#(piv,1) ez#=EntityZ#(piv,1) sens#=.025 While MouseDown(1) mx#=MouseX()-cx mz#=MouseY()-cy mx=-mx*sens mz=mz*sens If KeyDown(203) TurnEntity piv,0,1,0 If KeyDown(205) TurnEntity piv,0,-1,0 TFormVector mx,0,mz,piv,0 PositionEntity piv,ex#+TFormedX#(),8,ez#+TFormedZ#() UpdateWorld RenderWorld Flip Wend Return Tom |
| ||
If I understand what you want, you could use camerapick on the terrain or on an invisible plane, and do something like this... ;keep track of mouse position relative to visable grid function Function track_mouse(marker,camera) marker_X#=Int(PickedX#())+.5 marker_Z#=Int(PickedZ#())+.5 marker_Y#=Int(PickedY#())+.5 CameraPick(camera,MouseX(),MouseY()) End Function parent and point the camera at a point that follows a marker position found with this function. |
| ||
Its possible to map 3D X and Y positions to the 2D mouse X and Y positions. I did this ages ago. If I recall, what I did was set my camera position and then Projected the 3d point to the 2d screen, then projected a second point +1x, +1y to get a ratio between the 3d single point movement and the 2d movement. Then you just need to flip it 1.0/DeltaX# 1.0/deltaY# to get your ratio from 2D to 3D. This has limited use though because if you move the camera you have to re-project it but if thats what you need its possible. If your just wanting the camera to move with the mouse in the 3d world which is the recommended way of doing it then just use the MouseXspeed(), MouseYSpeed() on the camera movement commands. |
| ||
Toms example is close to what I want (cheers for that Tom). I'll have tinker with it tomorrow and see if I can make it work the way I want. Ideally I want it to feel like you have actually grabbed hold of an object/part of the landscape. So if I grab a tower then then I can drag it around the screen with the tower staying with the mouse pointer. Grabbing somewhere further in the distance will result in a different speed/scale of movement than grabbing something closer. |
| ||
My not just camera pick the mouse position on the terrain? |
| ||
And then what? |
| ||
Then you know the XYZ of the where the mouse is using pickedx pickedy and pickedz Then if you take the current xyz of the mouse and take it away from the last XYZ of the mouse you will know the xyz mouse speed. |
| ||
I can't see that working. If I 'grabbed' the top of a tower then moved the mouse to the side then the mouse mighty be over something miles away in the distance. So it would register a massive movement. What I want is the camera to move in such a way that the tower stays under the mouse cursor. I'm thinking of getting the x,y,z location the way you say and then finding where on screen x+1,y,z is and where x,y,z+1 is. Then I would have some kind of scale for the dragging. Something close to the camera would need smaller movement (in world coords) than something far away in order to keep up with the mouse. |
| ||
I knew I'd seen something like this before... This might help. http://www.blitzbasic.com/codearcs/codearcs.php?code=379 |
| ||
That seems to be on the right track but it locks the objects Z position. I need it to lock in the y. |
| ||
How about the mouse routine as before (using mousespeed and linepick) but Position a pivot at the picked co-ordinates. move the object by mousespeed multiplied by the distance of the camera to the pivot? This is only theory but it should work. Let me know :) If it fails, Kick me :P |
| ||
That's pretty similar current solution (written this morning) and it works pretty well. But it's not perfect, I'd really like the target object to stay exactly under the mouse cursor. |
| ||
lower the radius of the linepick? :/ |