CameraZoom question
Blitz3D Forums/Blitz3D Programming/CameraZoom question
| ||
Hi there, I'm trying to invoke CameraZoom with the mouse wheel, which works fine. Then I thought, "Hey, why not have it zoom toward the mouse pointer screen location?" I thought it would be simple to grab the coordinates of the current mouse pointer location on the screen, but in a 3D world the pointer isn't on a single coordinate; it is on a ray extending from the camera. However, I'm using CameraProjMode(cam,2) as this is really a 2D game (I just want the 3D shading and other features of meshes), so in fact there is no Z dimension. There is exactly one x and y location under the pointer. Any ideas how to get it? (Then I can move cam to that x,y and zoom in or out) I'm trying to use CameraPick, but that requires a mesh. I put a big cube in the background and set its entitypickmode to 3 and its entitybox to the same size & shape as the cube, but seems to work only sometimes, pretty much randomly, which is really odd. There are no other collisions going on. Is there a better way? Thanks in advance! |
| ||
So either nobody knows or nobody understands the question. (Or nobody gives a smeg). Let's try again: You know how in Google Maps you use the scroll wheel to zoom in and out? And how it zooms in and out toward the place you are pointing to? Well I want to do that in my Blitz3D game. I'm viewing it in orthographic projection (cameraprojmode(cam,2), so only x and y are relevant. It should be possible to find the world x and y coords from the mousex() and mousey() values and the current camerazoom(). (Why not just use 2D graphics instead, you ask? Because 3D graphics make it much easier to add shading and such.) Anyone? |
| ||
you could use mousex and mousey for a very simple way to do this. find out what coords the centre of screen is work out where the mouse is in relation to this move the camera a fraction of the distance that the mouse if offset by hope that helps KingPod |
| ||
KingPod, Thanks for the reply. Yes, your method is the one I'm using. It's the middle step - work out where the mouse is in relation to coords at the center of the screen - that is the tricky bit. That's trying to relate mouse position in pixels to world coordinates. I guess the question can be restated; how many world units per pixel are there for a given camerazoom? (in CameraProjMode(cam,2) - orthographic projection). CameraPick would solve it, but works unreliably for me in this view. Any ideas on that front? |
| ||
could you be more specific in how camerapick is unreliable? have you checked the pickmode ect? to find out the pixels you will have to experiment for yourself i guess. it depends how far the field is looking, how close your objects are to the camera and the camerazoom. |
| ||
Re camerapick being unreliable, how are you setting the entitybox? Never had a problem with it myself. You should set it up like so, for example ... cube = createcube() scalemesh cube, 10,10,1 entitypickmode cube, 3 entitybox cube, -10,-10,-1,20,20,2 Failing that - post some code which shows your issue and it's probably fixable. |
| ||
Wow, thanks Stevie G. I don't generally use collisions so the structure of the EntityBox parameters was news to me. I made the mistake of thinking that "position" of the box meant the origin, not the upper left. The documentation says: EntityBox entity,x#,y#,z#,width#,height#,depth# Parameters entity - entity handle# x# - x position of entity's collision box y# - y position of entity's collision box z# - z position of entity's collision box width# - width of entity's collision box height# - height of entity's collision box depth# - depth of entity's collision box No mention that the "position" means something different than an entity position. In any event I was using a pick_geometry of 2, which shouldn't require EntityBox anyway, but still wasn't working for me. pick_geometry of 3 works fine now, once the box is set right. As soon as I put the correct method of entitybox(-1000000,-1000000,-50,20000000,2000000,1) it works fine! Oddly, the documentation example for PickedEntity uses a plane, no box, and pick_geometry of 2 (i.e. same as mine was) and does work, but the way I have it now is good enough.) Thanks again. |
| ||
Here's the program. No need to fix anything, just thought I'd give it to you for helping me. I put some onscreen instructions, but of course it's very crude at this point. I don't actually know what it's going to be yet. (I know planets don't bounce off suns, but it's fun to watch!)Graphics3D(1280,1024,32,2) SetBuffer(BackBuffer()) AppTitle("2D Orbital Simulator") SeedRnd(MilliSecs()) Global gravity#=10.0 Global frame Global camzoom#=.01 Global maxtrailage=100000 Global maxalt# Global marker1,marker2 marker1=CreateCube() marker2=CreateCube() PositionEntity(marker2,1,0,0) ;background=CreatePlane() ;RotateEntity(background,-90,0,0) ;EntityAlpha(background,.5) background=CreateCube() ;ScaleEntity(background,1000,1000,1) PositionEntity(background,0,0,-50) ;EntityColor(background,0,0,0) EntityType(background,2) EntityBox(background,-1000000000,-1000000000,-50,2000000000,2000000000,1) EntityPickMode(background,3) cam=CreateCamera() CameraZoom(cam,camzoom) CameraProjMode(cam,2) PositionEntity(cam,0,0,-100) ;RotateEntity(cam,90,0,0) sun=CreateLight() RotateEntity(sun,10,-30,0) LightColor(sun,255,255,128) Global planet=CreateSphere(32) ;EntityPickMode(planet,1) ;EntityColor(planet,32,128,200) RotateEntity(planet,90,0,0) EntityColor(planet,255,255,128) ScaleEntity(planet,10,10,10) planetlight=CreateLight(2) LightColor(planetlight,16,16,16) Type satellite Field e Field size# Field x# Field y# Field xspeed# Field yspeed# Field red# Field green# Field blue# Field lastbounce End Type Type trail Field e Field satellite.satellite Field x# Field y# Field createdtime End Type Global particle=CreateMesh() surface=CreateSurface(particle) AddVertex(surface,1,-1,0) AddVertex(surface,-1,-1,0) AddVertex(surface,0,1,0) AddTriangle(surface,0,1,2) EntityColor(particle,255,255,255) ScaleEntity(particle,.2,.2,.2) EntityFX(particle,1) UpdateNormals(particle) For i=1 To 10 thissatellite=createsatellite() Next AmbientLight(128,128,255) While Not KeyHit(1) Local mzs#=MouseZSpeed() If mzs<>0 CameraPick(cam,MouseX(),MouseY()) CameraProject(cam,PickedX(),PickedY(),PickedZ()) PositionEntity(cam,PickedX(),PickedY(),-100) MoveMouse(GraphicsWidth()/2.0,GraphicsHeight()/2.0) ;PositionEntity(cam,EntityX(cam)+mzs*(MouseX()-GraphicsWidth()/2.0)/(10000.0*camzoom),EntityY(cam)-mzs*(MouseY()-GraphicsHeight()/2.0)/(10000.0*camzoom),-100) camzoom=camzoom*.1*(10+mzs) CameraZoom(cam,camzoom) EndIf If KeyDown(208); Up arrow PositionEntity(cam,EntityX(cam),EntityY(cam)-100,-100) EndIf If KeyDown(200); Down arrow PositionEntity(cam,EntityX(cam),EntityY(cam)+100,-100) EndIf If KeyDown(203) PositionEntity(cam,EntityX(cam)-100,EntityY(cam),-100) EndIf If KeyDown(205) PositionEntity(cam,EntityX(cam)+100,EntityY(cam),-100) EndIf frame=frame+1 updategravity() killoldtrails() RenderWorld() pe=PickedEntity() If pe<>0 Then Text(0,0,"pickedentity="+pe);EntityName(pe)) Text(0,20,"Highest Altitude="+maxalt) Text(0,40,"EntityX(cam)="+EntityX(cam)+" EntityY(cam)="+EntityY(cam)) Text(10,GraphicsHeight()-90,"Scroll-wheel zooms in/out. Right-click to enlarge planets if necessary. There should be 10 planets.") Text(10,GraphicsHeight()-75,"Distances can be extreme. If the Hightest Altitude parameter (top-left) is high (i.e. thousands or more),") Text(10,GraphicsHeight()-60,"zoom way out And hold the Right mouse button To enlarge the planets Until you find it.") Flip() Delay(10) Wend Function createsatellite() pivot=CreatePivot() this.satellite=New satellite Repeat this\size=Rnd(.5,3.0);2.0 ; this\x=Rnd(-60,60) ; this\y=Rnd(-60,60) ; this\xspeed=Rnd(-.5,.5) ; this\yspeed=Rnd(-.5,.5) Repeat altitude#=1.0/Rnd(1) angle#=Rnd(360) RotateEntity(pivot,0,0,angle) MoveEntity(pivot,altitude,0,0) this\x=EntityX(pivot);altitude*ACos(angle);1.0/Rnd(1);Rnd(-10000,10000)*Rnd(1) this\y=EntityY(pivot);altitude*ASin(angle);1.0/Rnd(1);Rnd(-10000,10000)*Rnd(1) Until Sqr(this\x*this\x+this\y*this\y)+this\size>10 speed#=10.0/Rnd(1)-10.0 direction#=Rnd(360) this\xspeed=speed*Cos(direction);1.0/Rnd(1)-1;Rnd(-10,10)*Rnd(1) this\yspeed=speed*Sin(direction);1.0/Rnd(1)-1;Rnd(-10,10)*Rnd(1) PositionEntity(pivot,this\x,this\y,0) netspeed#=Sqr(this\xspeed*this\xspeed+this\yspeed*this\yspeed) altitude#=EntityDistance(pivot,planet) gravforce#=gravity/(altitude*altitude) escapevelocity#=Sqr(2.0*gravforce*altitude) Until netspeed<escapevelocity this\e=CreateSphere(16) ;this\y=this\y+this\y RotateMesh(this\e,90,0,0) ScaleEntity(this\e,this\size,this\size,this\size) PositionEntity(this\e,this\x,this\y,0) Repeat this\red=(Rnd(0,255)+Rnd(0,255))/2.0 this\green=(Rnd(0,255)+Rnd(0,255))/2.0 this\blue=(Rnd(0,255)+Rnd(0,255))/2.0 Until this\red+this\green+this\blue>400 EntityColor(this\e,this\red,this\green,this\blue) ;EntityAlpha(this\e,.9) FreeEntity(pivot) End Function Function drawtrails() now=MilliSecs() For thistrail.trail=Each trail age=now-thistrail\createdtime If age>100 Delete thistrail Else agecolor#=255.0-255.0*(age/100.0) EndIf Next End Function Function killoldtrails() Local now=MilliSecs() Local thistrail.trail=First trail If thistrail<>Null While now-(thistrail\createdtime)>maxtrailage FreeEntity(thistrail\e) Delete(thistrail) thistrail=First trail Wend EndIf End Function Function updategravity() maxalt=0.0 For this.satellite=Each satellite If MouseDown(2) If .01*this\size/camzoom>this\size Then ScaleEntity(this\e,.01*this\size/camzoom,.01*this\size/camzoom,this\size) Else ScaleEntity(this\e,this\size,this\size,this\size) EndIf killit=False f#=frame/10.0 If f=frame/10 thistrail.trail=New trail thistrail\e=CopyEntity(particle) EntityColor(thistrail\e,this\red,this\green,this\blue) thistrail\satellite=this thistrail\x=this\x thistrail\y=this\y PositionEntity(thistrail\e,thistrail\x,thistrail\y,0) thistrail\createdtime=MilliSecs() EndIf altitude#=EntityDistance(this\e,planet) If altitude>maxalt Then maxalt=altitude minalt#=10.0+this\size If altitude<minalt If this\lastbounce<>0 And frame-this\lastbounce<100 killit=True Else this\lastbounce=frame checkalt#=2*10.0-altitude checkx#=this\x*checkalt/altitude checky#=this\y*checkalt/altitude checkdestx#=this\x+this\xspeed checkdesty#=this\y+this\yspeed checkdestalt#=Sqr(checkdestx*checkdestx+checkdesty*checkdesty) destalt#=(2*10.0-checkdestalt#)*.995 destx#=checkdestx*destalt/checkdestalt desty#=checkdesty*destalt/checkdestalt this\xspeed=(destx-checkx);this\x this\yspeed=(desty-checky);this\y If destalt<10.0+this\size Then destalt=(10.0+this\size)*2.0-destalt destx#=checkdestx*destalt/checkdestalt desty#=checkdesty*destalt/checkdestalt EndIf ;this\yspeed=-this\yspeed ;this\xspeed=-this\xspeed ;killit=True Else gravforce#=gravity/(altitude*altitude) this\xspeed=this\xspeed-gravforce*this\x/altitude this\yspeed=this\yspeed-gravforce*this\y/altitude EndIf this\x=this\x+this\xspeed this\y=this\y+this\yspeed PositionEntity(this\e,this\x,this\y,0) If killit=True FreeEntity(this\e) Delete(this) For thistrail.trail=Each trail If thistrail\satellite=this FreeEntity(thistrail\e) Delete(thistrail) EndIf Next createsatellite() EndIf Next End Function |
| ||
Not bad. I'd reduce the scale otherwise you're going to run into floating point precision issues and strange things will start to happen. |
| ||
Yeah. I wanted to simulate the actual range issues involved in orbits. (i.e. Mercury vs. the Oort Cloud). I use 1.0/rnd(1.0)-1.0 to generate both the starting altitude and the speed. Then I calculate the escape velocity from that; if it's exceeds the excape velocity it starts from scratch. So even the very distant ones are in orbit, just verrrrry sloooow. As far as going too slow to clear the center star, there's no easy way to measure that, so it just kills them after two bounces sufficiently close in time, and creates a new one. The result is an evolved solar system without limits but still looking pretty good. Next I'll have all the objects interact with each other. Maybe. We'll see. Game ideas: Something like Asteroids but with gravity; you have to defend your home planet (a random orbiter) from all the others. But if you shoot them when they are crossing your orbit the bits will still cross your orbit. Interplanetary war game (slower pace, of course) Planet Pong? :) |