Open DruggedBunny opened 5 years ago
Unimportant source update, but much better control-wise, at least for arcade purposes! Just that little thing of... flying backwards... need media from zip above.
#Import "<std>"
#Import "<mojo>"
#Import "<mojo3d>"
#Import "<mojo3d-loaders>"
#Import "assets/"
Using std..
Using mojo..
Using mojo3d..
Class MyWindow Extends Window
Field scene:Scene
Field camera:Camera
Field light:Light
Field ground:GroundBehaviour
Field plane:PlaneBehaviour
Method New( title:String="Place app",width:Int=640,height:Int=480,flags:WindowFlags=WindowFlags.Resizable )
Super.New( title,width,height,flags )
End
Method OnCreateWindow() Override
'create (current) scene
scene=New Scene
scene.ClearColor = New Color( 0.2, 0.6, 1.0 )
scene.AmbientLight = scene.ClearColor * 0.25
scene.FogColor = scene.ClearColor
scene.FogNear = 1.0
scene.FogFar = 5120.0
'create camera
camera=New Camera()
' camera.AddComponent<FlyBehaviour>()
' camera.Move( 0,0,-512 )
camera.Far = 10240.0
'create light
light=New Light
light.CastsShadow=True
light.Rotate( 45, 45, 0 )
'create ground
Local ground_size:Float = 4096 * 0.5
Local ground_box:Boxf = New Boxf( -ground_size,-ground_size * 0.5,-ground_size,ground_size,0,ground_size )
'Local groundMaterial:=New PbrMaterial( Color.Lime )
Local ground_model:Model=Model.Load ("asset::model_gltf_6G3x4Sgg6iX_7QCCWe9sgpb\model.gltf")'CreateBox( groundBox,1,1,1,groundMaterial )
ground_model.Mesh.FitVertices (ground_box, False)
' ground_model.Scale = New Vec3f (100, 100, 100)
' ground_model.Move (0, 100, 0)
ground_model.CastsShadow=True
ground = New GroundBehaviour (ground_model)
Local ground_collider:MeshCollider = ground.Entity.AddComponent <MeshCollider> ()
ground_collider.Mesh = Cast <Model> (ground.Entity).Mesh
Local ground_body:RigidBody = ground.Entity.AddComponent <RigidBody> ()
ground_body.Mass = 0.0
Local plane_size:Float = 16.83 * 0.5
Local plane_box:Boxf = New Boxf (-plane_size, -plane_size, -plane_size, plane_size, plane_size, plane_size)
Local plane_model:Model = Model.Load ("asset::1397 Jet_gltf_3B3Pa6BHXn1_fKZwaiJPXpf\1397 Jet.gltf")
plane_model.Mesh.FitVertices (plane_box)
camera.Parent = plane_model
camera.Move (0, 0, -20)
Local plane_coll_radius:Float = plane_size * 0.5
Local plane_coll_length:Float = plane_size * 1.5
Local plane_vis:Model = Model.CreateCylinder (plane_coll_radius, plane_coll_length, Axis.Z, 16, New PbrMaterial (Color.White), plane_model)
plane_vis.Alpha = 0.25
plane_vis.Visible = False
plane_model.Move (0.0, 5.0, 0.0)
' plane_model.Rotate (0.0, 180.0, 0.0)
plane = New PlaneBehaviour (plane_model)
' Local plane_collider:SphereCollider = plane.Entity.AddComponent <SphereCollider> ()
Local plane_collider:CylinderCollider = plane.Entity.AddComponent <CylinderCollider> ()
' apply to collider??? plane_model.Basis.Rotate (0.0, 180.0, 0.0)
plane_collider.Radius = plane_coll_radius
plane_collider.Axis = Axis.Z
plane_collider.Length = plane_coll_length
Local plane_body:RigidBody = plane.Entity.AddComponent <RigidBody> ()
plane_body.Mass = 1.0
plane_body.Restitution = 0.5
plane_body.AngularDamping = 0.5
plane_body.LinearDamping = 0.5
' plane_body.ApplyTorqueImpulse (New Vec3f (0.0, 0.0, -15.0))
plane_body.ApplyImpulse (plane.Entity.Basis * New Vec3f (0.0, 0.0, 33.0))
End
Method OnRender( canvas:Canvas ) Override
'camera.PointAt (plane.Entity)
' camera.FOV = 200.0 - Clamp (Float (camera.Position.Distance (plane.Entity.Position)), 22.5, 150.0)
If Keyboard.KeyHit (Key.Escape) Then App.Terminate ()
Local speed:Float = 1.0
Local roll_rate:Float = 25.0
Local pitch_rate:Float = 33.0
' -Scene.GetCurrent ().World.Gravity.Y
plane.Entity.GetComponent <RigidBody> ().ApplyForce (plane.Entity.Basis * New Vec3f (0.0, -Scene.GetCurrent ().World.Gravity.Y, 75.0))
If Keyboard.KeyDown (Key.LeftShift)
speed = speed * 2.0
Endif
If Keyboard.KeyDown (Key.Left)
plane.Entity.GetComponent <RigidBody> ().ApplyTorque (plane.Entity.Basis * New Vec3f (0.0, 0.0, roll_rate))
Endif
If Keyboard.KeyDown (Key.Right)
plane.Entity.GetComponent <RigidBody> ().ApplyTorque (plane.Entity.Basis * New Vec3f (0.0, 0.0, -roll_rate))
Endif
If Keyboard.KeyDown (Key.Up)
plane.Entity.GetComponent <RigidBody> ().ApplyTorque (plane.Entity.Basis * New Vec3f (pitch_rate, 0.0, 0.0))
plane.Entity.GetComponent <RigidBody> ().ApplyForce (plane.Entity.Basis * New Vec3f (0.0, Scene.GetCurrent ().World.Gravity.Y * 0.5, Scene.GetCurrent ().World.Gravity.Y * 0.5))
Endif
If Keyboard.KeyDown (Key.Down)
plane.Entity.GetComponent <RigidBody> ().ApplyTorque (plane.Entity.Basis * New Vec3f (-pitch_rate, 0.0, 0.0))
plane.Entity.GetComponent <RigidBody> ().ApplyForce (plane.Entity.Basis * New Vec3f (0.0, -Scene.GetCurrent ().World.Gravity.Y * 0.5, Scene.GetCurrent ().World.Gravity.Y * 0.5))
Endif
RequestRender()
scene.Update()
camera.Render( canvas )
canvas.DrawText( "FPS="+App.FPS,0,0 )
canvas.DrawText( "FOV="+camera.FOV,0,20 )
End
End
Function Main()
New AppInstance
New MyWindow
App.Run()
End
Class PlaneBehaviour Extends Behaviour
Method New (entity:Entity)
Super.New (entity)
AddInstance ()
End
Method OnStart () Override
'Local spacer:Float = 50.0
'Entity.Move (Rnd (-spacer, spacer), Rnd (-spacer, spacer), Rnd (-spacer, spacer))
Local model:Model = Cast <Model> (Entity)
For Local mat:Material = Eachin model.Materials
mat.CullMode = CullMode.Back
Next
End
Method OnUpdate (elapsed:Float) Override
'Local body:RigidBody = Cast <Model> (Entity).GetComponent <RigidBody> ()
'body.ApplyForce (Scene.GetCurrent ().World.Gravity * New Vec3f (1.0, -1.0, 1.0))
End
End
Class GroundBehaviour Extends Behaviour
Method New (entity:Entity)
Super.New (entity)
AddInstance ()
End
Method OnStart () Override
Local model:Model = Cast <Model> (Entity)
For Local mat:Material = Eachin model.Materials
mat.CullMode = CullMode.Back
Next
End
Method OnUpdate (elapsed:Float) Override
End
End
Function Degrees:Float (radians:Float)
Return radians * RAD_DIVIDER
End
Function Radians:Float (degrees:Float)
Return degrees * DEG_DIVIDER
End
Const RAD_DIVIDER:Float = 180.0 / Pi
Const DEG_DIVIDER:Float = Pi / 180.0
This works for me:
Local matrix := AffineMat4f.Rotation( 0, Radians(180), 0 )
plane_model.Mesh.TransformVertices( matrix )
On a side note, ground model shadows are totally killing the performance on my little laptop, like around 20 fps. Turning them off with ground_model.CastsShadow=False
jumps to 60fps, and I still get the plane's shadow on the ground. I wonder if it's related to the model size.
Oh, thanks, DW, will give that a go later. I'd ended up setting model alpha to 0 and loading (and rotating) a parented copy to work around it!
Interesting about the shadows, a lot of self-shadowing going on, I suppose...
It's only going to be a very simple 'how-to' physics demo anyway.
Just stuck it in -- that's worked a treat, thanks very much!
Current version much more controllable and with my rocket game camera hacked-in, looks pretty nice -- will just tidy this up (a lot) and tweak a bit more.
#Import "<std>"
#Import "<mojo>"
#Import "<mojo3d>"
#Import "<mojo3d-loaders>"
#Import "assets/"
Using std..
Using mojo..
Using mojo3d..
Class MyWindow Extends Window
Const WINDOW_WIDTH:Int = 1920
Const WINDOW_HEIGHT:Int = 1080
Const WINDOW_FLAGS:WindowFlags = WindowFlags.Fullscreen
' Const WINDOW_WIDTH:Int = 640
' Const WINDOW_HEIGHT:Int = 480
' Const WINDOW_FLAGS:WindowFlags = WindowFlags.Resizable
Field scene:Scene
'Field camera:Camera
Field camera:GameCamera
Field light:Light
Field ground:GroundBehaviour
Field plane:PlaneBehaviour
Method New( title:String="Place app",width:Int=WINDOW_WIDTH,height:Int=WINDOW_HEIGHT,flags:WindowFlags=WINDOW_FLAGS )
Super.New( title,width,height,flags )
End
Method OnCreateWindow() Override
'create (current) scene
scene=New Scene
scene.ClearColor = New Color( 0.2, 0.6, 1.0 )
scene.AmbientLight = scene.ClearColor * 0.25
scene.FogColor = scene.ClearColor
scene.FogNear = 128.0
scene.FogFar = 2048.0
' 'create camera
' camera=New Camera()
'' camera.AddComponent<FlyBehaviour>()
' ' camera.Move( 0,0,-512 )
' camera.Far = 10240.0
' camera.Viewport = App.ActiveWindow.Rect
'
camera=New GameCamera(App.ActiveWindow.Rect, Null, 10240)
' camera.AddComponent<FlyBehaviour>()
' camera.Move( 0,0,-512 )
'camera.Far = 10240.0
'camera.Viewport = App.ActiveWindow.Rect
'create light
light=New Light
light.CastsShadow=True
light.Rotate( 45, 45, 0 )
'create ground
Local ground_size:Float = 4096 * 0.5
Local ground_box:Boxf = New Boxf( -ground_size,-ground_size * 0.5,-ground_size,ground_size,0,ground_size )
'Local groundMaterial:=New PbrMaterial( Color.Lime )
Local ground_model:Model=Model.Load ("asset::model_gltf_6G3x4Sgg6iX_7QCCWe9sgpb\model.gltf")'CreateBox( groundBox,1,1,1,groundMaterial )
ground_model.Mesh.FitVertices (ground_box, False)
' ground_model.Scale = New Vec3f (100, 100, 100)
' ground_model.Move (0, 100, 0)
ground_model.CastsShadow=True
ground = New GroundBehaviour (ground_model)
Local ground_collider:MeshCollider = ground.Entity.AddComponent <MeshCollider> ()
ground_collider.Mesh = Cast <Model> (ground.Entity).Mesh
Local ground_body:RigidBody = ground.Entity.AddComponent <RigidBody> ()
ground_body.Mass = 0.0
Local plane_size:Float = 16.83 * 0.5
Local plane_box:Boxf = New Boxf (-plane_size, -plane_size, -plane_size, plane_size, plane_size, plane_size)
Local plane_model:Model = Model.Load ("asset::1397 Jet_gltf_3B3Pa6BHXn1_fKZwaiJPXpf\1397 Jet.gltf")
plane_model.Mesh.FitVertices (plane_box)
Local matrix := AffineMat4f.Rotation( 0, Radians(180), 0 )
plane_model.Mesh.TransformVertices( matrix )
' -------------------------------------------------
' HACK! To work around lack of Mesh.Rotate!
' -------------------------------------------------
' Local plane_dummy:Model = plane_model.Copy ()
' plane_dummy.Parent = plane_model
' plane_dummy.Rotate (0, 180, 0)
'
' plane_model.Alpha = 0.0
'
' -------------------------------------------------
' camera.Camera3D.Parent = plane_model
' camera.Move (0, 0, -20)
Local plane_coll_radius:Float = plane_size * 0.5
Local plane_coll_length:Float = plane_size * 1.5
Local plane_vis:Model = Model.CreateCylinder (plane_coll_radius, plane_coll_length, Axis.Z, 16, New PbrMaterial (Color.White), plane_model)
plane_vis.Alpha = 0.25
plane_vis.Visible = False
plane_model.Move (0.0, 5.0, 0.0)
' plane_model.Rotate (0.0, 180.0, 0.0)
plane = New PlaneBehaviour (plane_model)
' Local plane_collider:SphereCollider = plane.Entity.AddComponent <SphereCollider> ()
Local plane_collider:CylinderCollider = plane.Entity.AddComponent <CylinderCollider> ()
' apply to collider??? plane_model.Basis.Rotate (0.0, 180.0, 0.0)
plane_collider.Radius = plane_coll_radius
plane_collider.Axis = Axis.Z
plane_collider.Length = plane_coll_length
Local plane_body:RigidBody = plane.Entity.AddComponent <RigidBody> ()
plane_body.Mass = 1.0
plane_body.Restitution = 0.5
plane_body.AngularDamping = 0.9
plane_body.LinearDamping = 0.5
plane_body.Friction = 0.0
' plane_body.ApplyTorqueImpulse (New Vec3f (0.0, 0.0, -15.0))
plane_body.ApplyImpulse (plane.Entity.Basis * New Vec3f (0.0, 0.0, 33.0))
Mouse.PointerVisible = False
End
Method OnRender( canvas:Canvas ) Override
'camera.PointAt (plane.Entity)
' camera.FOV = 200.0 - Clamp (Float (camera.Position.Distance (plane.Entity.Position)), 22.5, 150.0)
If Keyboard.KeyHit (Key.Escape) Then App.Terminate ()
Local speed:Float = 1.0
Local roll_rate:Float = 50.0
Local pitch_rate:Float = 30.0
Local plane_body:RigidBody = plane.Entity.GetComponent <RigidBody> ()
' -Scene.GetCurrent ().World.Gravity.Y
plane_body.ApplyForce (plane.Entity.Basis * New Vec3f (0.0, -Scene.GetCurrent ().World.Gravity.Y, 75.0))
If Keyboard.KeyDown (Key.LeftShift)
speed = speed * 2.0
Endif
If Keyboard.KeyDown (Key.Left)
plane_body.ApplyTorque (plane.Entity.Basis * New Vec3f (0.0, 0.0, roll_rate))
Endif
If Keyboard.KeyDown (Key.Right)
plane_body.ApplyTorque (plane.Entity.Basis * New Vec3f (0.0, 0.0, -roll_rate))
Endif
If Keyboard.KeyDown (Key.Up)
plane_body.ApplyTorque (plane.Entity.Basis * New Vec3f (pitch_rate, 0.0, 0.0))
plane_body.ApplyForce (plane.Entity.Basis * New Vec3f (0.0, Scene.GetCurrent ().World.Gravity.Y * 0.5, Scene.GetCurrent ().World.Gravity.Y * 0.5))
Endif
If Keyboard.KeyDown (Key.Down)
plane_body.ApplyTorque (plane.Entity.Basis * New Vec3f (-pitch_rate, 0.0, 0.0))
plane_body.ApplyForce (plane.Entity.Basis * New Vec3f (0.0, -Scene.GetCurrent ().World.Gravity.Y * 0.5, Scene.GetCurrent ().World.Gravity.Y * 0.5))
Endif
RequestRender()
scene.Update()
camera.Update (plane)'Render( canvas )
camera.Camera3D.Render (canvas)
canvas.DrawText( "FPS="+App.FPS,0,0 )
canvas.DrawText( "FOV="+camera.Camera3D.FOV,0,20 )
End
End
Function Main()
New AppInstance
New MyWindow
App.Run()
End
Class PlaneBehaviour Extends Behaviour
Method New (entity:Entity)
Super.New (entity)
AddInstance ()
End
Method OnStart () Override
'Local spacer:Float = 50.0
'Entity.Move (Rnd (-spacer, spacer), Rnd (-spacer, spacer), Rnd (-spacer, spacer))
Local model:Model = Cast <Model> (Entity)
For Local mat:Material = Eachin model.Materials
mat.CullMode = CullMode.Back
Next
End
Method OnUpdate (elapsed:Float) Override
'Local body:RigidBody = Cast <Model> (Entity).GetComponent <RigidBody> ()
'body.ApplyForce (Scene.GetCurrent ().World.Gravity * New Vec3f (1.0, -1.0, 1.0))
End
End
Class GroundBehaviour Extends Behaviour
Method New (entity:Entity)
Super.New (entity)
AddInstance ()
End
Method OnStart () Override
Local model:Model = Cast <Model> (Entity)
For Local mat:Material = Eachin model.Materials
mat.CullMode = CullMode.Back
Next
End
Method OnUpdate (elapsed:Float) Override
End
End
Function Degrees:Float (radians:Float)
Return radians * RAD_DIVIDER
End
Function Radians:Float (degrees:Float)
Return degrees * DEG_DIVIDER
End
Const RAD_DIVIDER:Float = 180.0 / Pi
Const DEG_DIVIDER:Float = Pi / 180.0
' -----------------------------------------------------------------------------
' What is it?
' -----------------------------------------------------------------------------
Class GameCamera
Public
Property CameraDistance:Float ()
Return camera_distance
Setter (distance:Float)
camera_distance = distance
End
Property Camera3D:Camera ()
Return real_camera
Setter (new_cam:Camera)
real_camera = new_cam
End
Method New (viewport:Recti, current_camera:GameCamera, range_far:Float)
If current_camera Then current_camera.Destroy ()
camera_pivot = New Pivot
Camera3D = New Camera (camera_pivot)
Camera3D.Near = 0.01
Camera3D.Far = range_far * Sqrt (3.0) ' Terrain cube diagonal
Camera3D.FOV = 90.0 ' Mojo3d default
Camera3D.Viewport = viewport
' Chase target -- position camera tries to move towards...
chase_target = Model.CreateSphere (1, 32, 32, New PbrMaterial (Color.Red))
chase_target.Alpha = 0.5
chase_target.Material.CullMode = CullMode.None
chase_target.Visible = False
up = New Vec3f (0.0, up_y_default, 0.0)
Reset ()
End
Method Destroy ()
camera_pivot?.Destroy ()
real_camera?.Destroy ()
chase_target?.Destroy ()
End
Method Reset ()
Camera3D.FOV = 90.0
' chase_target.Position = New Vec3f (Game.CurrentLevel.SpawnX, Game.CurrentLevel.SpawnY, Game.CurrentLevel.SpawnZ)
' camera_pivot.Position = New Vec3f (Game.CurrentLevel.SpawnX, Game.CurrentLevel.SpawnY, Game.CurrentLevel.SpawnZ - 10.0)
lastvel = New Vec3f (0, 0, 15)
prevvel = lastvel
End
Method Update (target:PlaneBehaviour)
' Camera positioning...
prevvel = lastvel
Local plane_body:RigidBody = target.Entity.GetComponent <RigidBody> ()
Local plane_model:Model = Cast <Model> (target.Entity)
' If plane_body.LinearVelocity.XZ.Length > 5.0
lastvel = lastvel.Blend (plane_body.LinearVelocity, 0.045)
' Endif
chase_target.Position = (plane_model.Position + up) - (lastvel * CameraDistance)
camera_pivot.Move ((chase_target.Position - camera_pivot.Position) * 0.95, True)
camera_pivot.PointAt (plane_model)
Local cam_dist:Float = plane_model.Position.Distance (Camera3D.Position)
Local closeup:Float = 10.5
Local closer:Float = 0.1
If cam_dist < closeup
Camera3D.FOV = Blend (Camera3D.FOV, TransformRange (cam_dist, 1.0, closeup, 130.0, 90.0), closer)
up.Y = Blend (up.Y, 3.0, 0.01)
Else
Camera3D.FOV = Blend (Camera3D.FOV, 90.0, 0.075)
up.Y = Blend (up.Y, up_y_default, 0.01)
Endif
End
'Method ShortestVec:Vec3f (v1:Vec3f, v2:Vec3f)
' If v1.Length < v2.Length Then Return v1 Else Return v2
'End
'Method LongestVec:Vec3f (v1:Vec3f, v2:Vec3f)
' If v1.Length > v2.Length Then Return v1 Else Return v2
'End
Method Move (tv:Vec3f, localSpace:Bool = False)
camera_pivot.Move (tv, localSpace)
End
Method Move (tx:Float, ty:Float, tz:Float)
camera_pivot.Move (tx, ty, tz)
End
Method PointAt (target:Entity)
camera_pivot.PointAt (target)
End
Method Position (v3:Vec3f)
camera_pivot.Position = v3
End
Private
Field camera_pivot:Pivot
Field real_camera:Camera
Field chase_target:Model
Field lastvel:Vec3f
Field prevvel:Vec3f
Field up:Vec3f
Field up_y_default:Float = 2.5
Field camera_distance:Float = 0.4
End
Function TransformRange:Float (input_value:Float, from_min:Float, from_max:Float, to_min:Float, to_max:Float)
' Algorithm via jerryjvl at https://stackoverflow.com/questions/929103/convert-a-number-range-to-another-range-maintaining-ratio
Local from_delta:Float = from_max - from_min ' Input range, eg. 0.0 - 1.0
Local to_delta:Float = to_max - to_min ' Output range, eg. 5.0 - 10.0
Assert (from_delta <> 0.0, "TransformRange: Invalid input range!")
Return (((input_value - from_min) * to_delta) / from_delta) + to_min
End
Function Blend:Float (in:Float, target:Float, delta:Float = 0.1)
If Abs (target - in) < Abs (delta) Then Return target
Return in + ((target - in) * delta)
End
Maybe closed this issue.
This is a very messy WIP test using two Google Poly models, an island and a plane.
When I load the plane, it's rotated 180 degrees on the y-axis, so faces the camera, so I can only fly with my plane pointing in reverse, as this loaded orientation is what the CylinderCollider's Axis.Z aligns with.
Blitz3D had a RotateMesh command to take care of this, but there doesn't seem to be any way to do the same thing in mojo3d.
This is the crap demo, controls are weird (not taking into account proper plane movement) and plane flies backwards!
island.zip