Ooops
October 28, 2021, 05:25:42

Author Topic: Question about free 3d rotation  (Read 552 times)

Offline Pappons

  • Jr. Member
  • **
  • Posts: 3
Question about free 3d rotation
« on: September 15, 2021, 20:17:55 »
Hi guys,

I'm having a spot of trouble with free rotation in 3D. I am trying to recreate controls similar to those of that old Freelancer game where you direct your ship with the mouse, and it sort of works, but not fully.

My code:
Code: [Select]
'
'
'
Strict

Framework Openb3dmax.B3dglgraphics

'- init -----------------------------------------------------------------------------------
Graphics3D DesktopWidth(),DesktopHeight(), 32, 60

ClearTextureFilters

Local cam:TCamera=CreateCamera()
PositionEntity cam, 0, 3, 0
CameraRange cam, .1, 750  ' set the camera range To something reasonable

'- light ---------------------------------------------------------------------------------
Local light:TLight=CreateLight(2,cam)
LightColor light,100,100,100
PositionEntity light,0,0,0

AmbientLight 255,255,255

'- sky box ---------------------------------------------------------------------------------
Local sky:TMesh=CreateSphere(24)
ScaleEntity sky,500,500,500
FlipMesh sky
EntityFX sky,1
Local sky_tex:TTexture=LoadTexture("data\tilingspacebackground.jpg")
ScaleTexture sky_tex, 0.5, 0.5
EntityTexture sky,sky_tex

'- player ship ---------------------------------------------------------------------------------
Local ship:TEntity = LoadMesh("data\InterstellarRunner.b3d")
ScaleEntity ship, 0.15, 0.15, 0.15
PositionEntity ship, 5, 0.1, 4

Local shiptex:TTexture=LoadTexture("data\InterstellarRunner.png")
EntityTexture ship, shiptex
EntityShininess(ship,0.1)

'- player ship ---------------------------------------------------------------------------------
Local cx:Float = DesktopWidth() / 2
Local cy:Float = DesktopHeight() / 2

While Not KeyDown(KEY_ESCAPE)

If KeyHit(KEY_ENTER) Then DebugStop

MoveEntity ship,0,0,0.10 ' move straight forward

Local dx:Float = ( MouseX() - cx ) / (cx ) ' get the mouse position
Local dy:Float = ( MouseY() - cy ) / (cy ) ' relative to the center of the screen

If MouseDown(1)
TurnEntity ship,(dy), -(dx),0 ' turn the ship in direction of the mouse
EndIf

PointEntity( cam, ship ) ' point camera at ship

If EntityDistance( cam, ship ) > 10
MoveEntity cam, 0, 0, 0.1 ' move towards ship if at a certain distance
EndIf

UpdateWorld
RenderWorld

Flip
GCCollect

Wend

I have a feeling the solution has to do with quaternions, but my experience with it is limited and any tinkering I've done has been fruitless so far.

Would anyone be able to nudge me in the right direction here?

Thanks in advance!

Offline markcwm

  • Hero Member
  • *****
  • Posts: 508
Re: Question about free 3d rotation
« Reply #1 on: September 17, 2021, 20:47:52 »
Hi,

I tried your code but I don't know what type of controls are in Freelancer even after watching a video.

I assume your main problem is that the ship ends up dis-orientated, upside down, etc. so I tried to implement a simple self-correcting system where it stabilizes itself automatically but I couldn't really manage it, it was trickier than I thought it would be. It shouldn't be a problem with quaternions they should work fine.

One thing that might help is to use RotateEntity instead of TurnEntity because then it's easier to know where you are and can start re-balancing the ship. Another thing that might help is to limit the value of dx and dy to a maximum so you don't end up over-turning the ship.

Offline STEVIE G

  • Hero Member
  • *****
  • Posts: 628
Re: Question about free 3d rotation
« Reply #2 on: September 17, 2021, 22:08:38 »
I'm assuming minib3d works like b3d in terms of rotations. Turnentity should use quarternions. The problem is turning on 2 axis at the same time.  You could try turnentity separately on each axis or do this ...

Make your ship entity a pivot. Load and parent your ship model to this pivot. Turnentity the pivot only  on the yaw axis. Turnentity the ship model only on the local pitch axis. 

Offline Pappons

  • Jr. Member
  • **
  • Posts: 3
Re: Question about free 3d rotation
« Reply #3 on: September 17, 2021, 23:30:02 »
Thanks for the replies, guys. I really appreciate it!

Turning on each axis didn't seem to change much. I'm noticing a certain behavior where I can pretty much keep turning to either side but if I keep guiding the ship either up or down, it causes it to "flip" and turn in the opposite direction once it passes 180 degrees.

Here's a video that shows what I am aiming to do:
Code: [Select]
https://www.youtube.com/watch?v=NODc1lXn0ak&t=27s - Watching the video again, makes it seem like it's barely rotating compared to the camera.

That leads me to wonder; could it be that the camera chasing the ship could be confusing the view and the ship indeed is moving as it should?
« Last Edit: September 17, 2021, 23:32:27 by Pappons »

Offline angros47

  • Jr. Member
  • **
  • Posts: 75
Re: Question about free 3d rotation
« Reply #4 on: September 19, 2021, 18:50:56 »
I'm assuming minib3d works like b3d in terms of rotations. Turnentity should use quarternions.

OpenB3D uses quaternions (like b3d). Minib3d doesn't (unless you are using the version patched by Warner or the one patched by EdzUp)

Offline markcwm

  • Hero Member
  • *****
  • Posts: 508
Re: Question about free 3d rotation
« Reply #5 on: September 20, 2021, 22:31:15 »
Stevie G has the right idea, you need to use pivots to control the rotations. The controls are very similar to airplane controls, so I ported the xfighter sample from Blitz3D and added your mouse controls. It's not that far away from the Freelancer controls but needs work, mainly it will jump when you click somewhere else, so you would need to store the last mouse values and then move from there, there's mouselook code that should help you fix it.
Code: BlitzMax
  1. ' plane controls from Blitz3D/samples/mak/xfighter
  2.  
  3. Strict
  4.  
  5. Framework Openb3dmax.B3dglgraphics
  6.  
  7. '- init -----------------------------------------------------------------------------------
  8. Graphics3D DesktopWidth(),DesktopHeight(), 32, 60
  9.  
  10. ClearTextureFilters
  11.  
  12. Global use_fog%=False
  13.  
  14. Type Player
  15.         Field entity:TEntity,camera:TCamera
  16.         Field ctrl_mode%,cam_mode%,ignition%
  17.         Field pitch#,yaw#,pitch_speed#,yaw_speed#,roll#,thrust#
  18.         Field cx#,cy#,dx#,dy#
  19. End Type
  20.  
  21. '- player ship ---------------------------------------------------------------------------------
  22. Local plane:TPivot=LoadAirPlane("../openb3dmax.docs/media/rallycar1.3ds")
  23.  
  24. 'Local plane:TPivot=LoadAirPlane("data\InterstellarRunner.b3d")
  25. 'Local planetex:TTexture=LoadTexture("data\InterstellarRunner.png")
  26. 'EntityTexture plane, planetex
  27. 'EntityShininess(plane,0.1)
  28.  
  29. Local player1:Player=CreatePlayer( plane,0,0,GraphicsWidth(),GraphicsHeight(),2 )
  30.  
  31. player1.cx = DesktopWidth() / 2
  32. player1.cy = DesktopHeight() / 2
  33.  
  34. '- light ---------------------------------------------------------------------------------
  35. Local light:TLight=CreateLight(2,player1.camera)
  36. LightColor light,100,100,100
  37. PositionEntity light,0,0,0
  38.  
  39. AmbientLight 255,255,255
  40.  
  41. '- sky box ---------------------------------------------------------------------------------
  42. Local sky:TMesh=CreateSphere(24)
  43. ScaleEntity sky,3000,3000,3000
  44. FlipMesh sky
  45. EntityFX sky,1
  46. Local sky_tex:TTexture=LoadTexture("../openb3dmax.docs/media/sky.bmp")
  47. 'Local sky_tex:TTexture=LoadTexture("data\tilingspacebackground.jpg")
  48. ScaleTexture sky_tex, 0.5, 0.5
  49. EntityTexture sky,sky_tex
  50.  
  51. While Not KeyDown(KEY_ESCAPE)          
  52.  
  53.         UpdatePlayer(player1)
  54.         UpdateWorld
  55.         RenderWorld
  56.        
  57.         Text 0,20,"dx="+player1.dx+" dy="+player1.dy
  58.        
  59.         Flip
  60.         GCCollect
  61.  
  62. Wend
  63.  
  64. Function LoadAirPlane:TPivot( file$ )
  65.         UseMeshTransform 1 ' mesh transforms, default is False
  66.         Local pivot:TPivot=CreatePivot()
  67.         Local plane:TMesh
  68.         If file$="" Then plane=CreateCube() Else plane=LoadMesh( file$,pivot )
  69.         'ScaleEntity plane,.08,.08,.08
  70.         ScaleMesh plane,.05,.05,.05     'make it more spherical!
  71.         plane.RotateMesh(90,180,0)
  72.         'RotateEntity plane,0,180,0     'And align To z axis
  73.         EntityRadius pivot,1
  74.         EntityType pivot,1
  75.         HideEntity pivot
  76.         Return pivot
  77. End Function
  78.  
  79. Function CreatePlayer:Player( plane:TPivot,vp_x%,vp_y%,vp_w%,vp_h%,ctrl_mode% )
  80.         Local p:Player=New Player
  81.         p.ctrl_mode=ctrl_mode
  82.         p.cam_mode=1
  83.         Local x#=ctrl_mode*10
  84.         Local z#=ctrl_mode*10-2500
  85.        
  86.         p.entity=TPivot( CopyEntity( plane ) )
  87.         PositionEntity p.entity,x,50,z
  88.         RotateEntity p.entity,0,180,0
  89.         ResetEntity p.entity
  90.        
  91.         p.camera=CreateCamera( p.entity )
  92.         PositionEntity p.camera,0,3,-10
  93.         CameraViewport p.camera,vp_x,vp_y,vp_w,vp_h
  94.         CameraClsColor p.camera,0,192,255
  95.         CameraFogColor p.camera,0,192,255
  96.         CameraFogRange p.camera,1000,3000
  97.         CameraRange p.camera,1,6000
  98.         'CameraRange cam, .1, 750  ' set the camera range to something reasonable
  99. '       CameraZoom p.camera,1.5
  100.         If use_fog Then CameraFogMode p.camera,1
  101.         Return p
  102. End Function
  103.  
  104. Function UpdatePlayer( p:Player )
  105.  
  106.         Local x_dir%,y_dir%,z_dir%
  107.        
  108.         Select p.ctrl_mode
  109.         Case 1
  110.                 If KeyDown(KEY_LEFT) x_dir=-1
  111.                 If KeyDown(KEY_RIGHT) x_dir=1
  112.                
  113.                 If KeyDown(KEY_UP) y_dir=-1
  114.                 If KeyDown(KEY_DOWN) y_dir=1
  115.                
  116.                 If KeyDown(KEY_A) z_dir=1
  117.                 If KeyDown(KEY_Z) z_dir=-1
  118.                
  119.                 If KeyHit(KEY_F1) p.cam_mode=1
  120.                 If KeyHit(KEY_F2) p.cam_mode=2
  121.                 If KeyHit(KEY_F3) p.cam_mode=3
  122.                 If KeyHit(KEY_F4) p.cam_mode=4
  123.                
  124.         If x_dir<0
  125.                 p.yaw_speed=p.yaw_speed + (4-p.yaw_speed)*.04
  126.         Else If x_dir>0
  127.                 p.yaw_speed=p.yaw_speed + (-4-p.yaw_speed)*.04
  128.         Else
  129.                 p.yaw_speed=p.yaw_speed + (-p.yaw_speed)*.02
  130.         EndIf
  131.                
  132.         If y_dir<0
  133.                 p.pitch_speed=p.pitch_speed + (2-p.pitch_speed)*.2
  134.         Else If y_dir>0
  135.                 p.pitch_speed=p.pitch_speed + (-2-p.pitch_speed)*.2
  136.         Else
  137.                 p.pitch_speed=p.pitch_speed + (-p.pitch_speed)*.1
  138.         EndIf
  139.                
  140.         Case 2
  141.                 p.dx = ( MouseX() - p.cx ) / p.cx       ' get the mouse position
  142.                 p.dy = ( MouseY() - p.cy ) / p.cy       ' relative to the center of the screen
  143.                
  144.                 If MouseDown(1)
  145.                         x_dir=1
  146.                         y_dir=1
  147.                         z_dir=1
  148.                 EndIf
  149.                 If MouseDown(2)
  150.                         z_dir=-1
  151.                 EndIf
  152.                
  153.                 If x_dir>0
  154.                         p.yaw_speed=p.yaw_speed + (-(p.dx*4)-p.yaw_speed)*.8
  155.                 Else If p.dx=0
  156.                         p.yaw_speed=p.yaw_speed + (p.dx-p.yaw_speed)*.4
  157.                 EndIf
  158.                 If y_dir>0
  159.                         p.pitch_speed=p.pitch_speed + ((p.dy*4)-p.pitch_speed)*1.5
  160.                 Else If p.dy=0
  161.                         p.pitch_speed=p.pitch_speed + (p.dy-p.pitch_speed)*.75
  162.                 EndIf
  163.        
  164.                
  165.                 If KeyHit(KEY_F5) p.cam_mode=1
  166.                 If KeyHit(KEY_F6) p.cam_mode=2
  167.                 If KeyHit(KEY_F7) p.cam_mode=3
  168.                 If KeyHit(KEY_F8) p.cam_mode=4
  169.                
  170.         End Select
  171.        
  172.         p.yaw=p.yaw+p.yaw_speed
  173.         If p.yaw<-180 Then p.yaw=p.yaw+360
  174.         If p.yaw>=180 Then p.yaw=p.yaw-360
  175.        
  176.         p.pitch=p.pitch+p.pitch_speed
  177.         If p.pitch<-45 Then p.pitch=-45
  178.         If p.pitch>=45 Then p.pitch=45
  179.        
  180.         p.roll=p.yaw_speed*30
  181.         RotateEntity p.entity,p.pitch,p.yaw,p.roll
  182.        
  183.         'see If y/p/r funcs are working...
  184.         Local t_p#=EntityPitch( p.entity )
  185.         Local t_y#=EntityYaw( p.entity )
  186.         Local t_r#=EntityRoll( p.entity )
  187.         RotateEntity p.entity,t_p,t_y,t_r
  188.        
  189.         If p.ignition
  190.                 If z_dir>0                      'faster?
  191.                         p.thrust=p.thrust + (1.5-p.thrust)*.04  '1.5
  192.                 Else If z_dir<0         'slower?
  193.                         p.thrust=p.thrust + (-p.thrust)*.04
  194.                 EndIf
  195.                 MoveEntity p.entity,0,0,p.thrust
  196.         Else If z_dir>0
  197.                 p.ignition=True
  198.         EndIf
  199.        
  200.         If p.camera
  201.                 Select p.cam_mode
  202.                 Case 1
  203.                         EntityParent p.camera,p.entity
  204.                         RotateEntity p.camera,0,p.yaw,0,True
  205.                         PositionEntity p.camera,EntityX(p.entity),EntityY(p.entity),EntityZ(p.entity),True
  206.                         MoveEntity p.camera,0,1,-5
  207.                         PointEntity p.camera,p.entity,p.roll/2
  208.                 Case 2
  209.                         EntityParent p.camera,Null
  210.                         PositionEntity p.camera,EntityX(p.entity),EntityY(p.entity),EntityZ(p.entity)
  211.                         TranslateEntity p.camera,0,1,-5
  212.                         PointEntity p.camera,p.entity,0
  213.                 Case 3
  214.                         EntityParent p.camera,p.entity
  215.                         PositionEntity p.camera,0,.25,0
  216.                         RotateEntity p.camera,0,0,0
  217.                 Case 4
  218.                         EntityParent p.camera,Null
  219.                         PointEntity p.camera,p.entity,0
  220.                 End Select
  221.         EndIf
  222.        
  223. End Function
  224.  

 

SimplePortal 2.3.6 © 2008-2014, SimplePortal