Bit of an odd one I've run into while trying to convert my rocket smoke from cubes to sprites, sort of narrowed it down to the sample below.
In short, I'm firing a stream of physics-controlled particles that cycles through white, yellow, orange, red, black, then fade out. It should look like this (extreme debug version using cubes):
However, when using sprites, they start out correctly, then once a few of them are active at once, they start to flicker and jump.
You should be able to see it in the code below. Note that the class is duplicated, just that one uses cubes, other uses sprites.
Hold Space for a constant stream and note the cubes are fine, but the sprites start jumping and flickering. With short taps, the sprites are also OK, but held for a little longer, they start to mess up. (Tap Enter for single particles and note they only screw up if tapped rapidly.)
Thought it was some sort of alpha problem, but replacing alpha with a dummy variable (leaving entity alpha at 1.0 throughout) does the same thing.
Namespace myapp3d
#Import "<std>"
#Import "<mojo>"
#Import "<mojo3d>"
Using std..
Using mojo..
Using mojo3d..
' ---------------------- SPRITE version ----------------------
Class RocketParticle_Sprite Extends Behaviour
Public
Function Create:RocketParticle_Sprite (parent:Entity, thrust:Vec3f, size:Float = 0.5, fadeout:Float = 0.95)
'Game.MainCamera.CameraDistance = 4.0
'RocketParticle.SpriteInit ()
Local sprite:Sprite = New Sprite (New SpriteMaterial (), parent)
Cast <SpriteMaterial> (sprite.Material).ColorFactor = Color.White
'sprite.Move (Rnd (-0.1, 0.1), Rnd (-2.1, -2.5), Rnd (-0.1, 0.1))
sprite.Move (0.0, -2.1, 0.0)
sprite.Parent = Null
sprite.Scale = New Vec3f (size, size, 0.0)
sprite.Alpha = 1.0
Local sp:RocketParticle_Sprite = New RocketParticle_Sprite (sprite)
sp.thrust = thrust
sp.update_fader = fadeout
sp.TMP_fake_alpha = 1.0
Return sp
End
Private
Method New (entity:Entity)
Super.New (entity)
AddInstance ()
End
Method OnStart () Override
Local collider:BoxCollider = Entity.AddComponent <BoxCollider> () ' Unexpected: Collider needs to be added BEFORE applying impulse!
Local body:RigidBody = Entity.AddComponent <RigidBody> ()
' No Boxf!
body.Mass = 0.01
body.Restitution = 0.5
body.Friction = 0.1
body.CollisionMask = 0'COLL_NOTHING
body.ApplyImpulse (thrust)
thrust = Null ' Don't need to keep temp Vec3f object
End
Method OnUpdate (elapsed:Float) Override
' Print Int (color_change * 5.0)
' Cast <Sprite> (Entity).Material = SpriteMat [Int (Entity.Alpha * 5.0)] ' There are 5 sprite materials
' Local sm:SpriteMaterial = Cast <SpriteMaterial> (Cast <Sprite> (Entity).Material)
Local cs:Sprite = Cast <Sprite> (Entity)
Local sm:SpriteMaterial = Cast <SpriteMaterial> (cs.Material)
' Local cs:Model = Cast <Model> (Entity)
' Local sm:PbrMaterial = Cast <PbrMaterial> (cs.Material)
Select Int (color_change * 5.0) ' There are 5 sprite materials
Case 0
sm.ColorFactor = Color.Black
Case 1
sm.ColorFactor = Color.Red
Case 2
sm.ColorFactor = Color.Orange
Case 3
sm.ColorFactor = Color.Yellow
Case 4
sm.ColorFactor = Color.White
End
If sm.ColorFactor = Color.Black
Entity.Alpha = Entity.Alpha * 0.975 ' TODO: Needs adjusting for framerate!
'TMP_fake_alpha = TMP_fake_alpha * 0.975
Else
color_change = color_change * update_fader ' TODO: Needs adjusting for framerate!
End
' Slow particle down (air resistance)... very dependent on start speed and alpha fade amount...
Entity.GetComponent <RigidBody> ().LinearDamping = (1.0 - color_change)' * 0.95 ' Trial and error!
'If TMP_fake_alpha < 0.075'
If Entity.Alpha < 0.075
Entity.Destroy ()
Endif
End
' Rocket thrust level -- need to temp-store here as OnStart can't be passed custom params!
Field thrust:Vec3f
Field update_fader:Float
Field color_change:Float = 0.99
Field TMP_fake_alpha:Float
End
' ---------------------- MESH version ----------------------
Class RocketParticle_Mesh Extends Behaviour
Public
Function Create:RocketParticle_Mesh (parent:Entity, thrust:Vec3f, size:Float = 0.5, fadeout:Float = 0.95)
'Game.MainCamera.CameraDistance = 4.0
'RocketParticle.SpriteInit ()
' Local sprite:Sprite = New Sprite (New SpriteMaterial (), rocket.RocketModel)
Local sprite:Model = Model.CreateBox (New Boxf (-0.5, -0.5, -0.5, 0.5, 0.5, 0.5), 1, 1, 1, New PbrMaterial (Color.White), parent)'New Sprite (New SpriteMaterial (), rocket.RocketModel)
' Cast <SpriteMaterial> (sprite.Material).ColorFactor = Color.White
'sprite.Move (Rnd (-0.1, 0.1), Rnd (-2.1, -2.5), Rnd (-0.1, 0.1))
sprite.Move (0.0, -2.1, 0.0)
sprite.Parent = Null
sprite.Scale = New Vec3f (size, size, size)
sprite.Alpha = 1.0
Local sp:RocketParticle_Mesh = New RocketParticle_Mesh (sprite)
sp.thrust = thrust
sp.update_fader = fadeout
sp.TMP_fake_alpha = 1.0
Return sp
End
Private
Method New (entity:Entity)
Super.New (entity)
AddInstance ()
End
Method OnStart () Override
Local collider:BoxCollider = Entity.AddComponent <BoxCollider> () ' Unexpected: Collider needs to be added BEFORE applying impulse!
Local body:RigidBody = Entity.AddComponent <RigidBody> ()
' No Boxf!
body.Mass = 0.01
body.Restitution = 0.5
body.Friction = 0.1
body.CollisionMask = 0'COLL_NOTHING
body.ApplyImpulse (thrust)
thrust = Null ' Don't need to keep temp Vec3f object
End
Method OnUpdate (elapsed:Float) Override
' Print Int (color_change * 5.0)
' Cast <Sprite> (Entity).Material = SpriteMat [Int (Entity.Alpha * 5.0)] ' There are 5 sprite materials
' Local sm:SpriteMaterial = Cast <SpriteMaterial> (Cast <Sprite> (Entity).Material)
' Local cs:Sprite = Cast <Sprite> (Entity)
' Local sm:SpriteMaterial = Cast <SpriteMaterial> (cs.Material)
Local cs:Model = Cast <Model> (Entity)
Local sm:PbrMaterial = Cast <PbrMaterial> (cs.Material)
Select Int (color_change * 5.0) ' There are 5 sprite materials
Case 0
sm.ColorFactor = Color.Black
Case 1
sm.ColorFactor = Color.Red
Case 2
sm.ColorFactor = Color.Orange
Case 3
sm.ColorFactor = Color.Yellow
Case 4
sm.ColorFactor = Color.White
End
If sm.ColorFactor = Color.Black
Entity.Alpha = Entity.Alpha * 0.975 ' TODO: Needs adjusting for framerate!
' TMP_fake_alpha = TMP_fake_alpha * 0.975
Else
color_change = color_change * update_fader ' TODO: Needs adjusting for framerate!
End
' Slow particle down (air resistance)... very dependent on start speed and alpha fade amount...
Entity.GetComponent <RigidBody> ().LinearDamping = (1.0 - color_change)' * 0.95 ' Trial and error!
'If TMP_fake_alpha < 0.075'
If Entity.Alpha < 0.075
Entity.Destroy ()
Endif
End
' Rocket thrust level -- need to temp-store here as OnStart can't be passed custom params!
Field thrust:Vec3f
Field update_fader:Float
Field color_change:Float = 0.99
Field TMP_fake_alpha:Float
End
Class MyWindow Extends Window
Field _scene:Scene
Field _camera:Camera
Field _light:Light
Field _ground:Model
Field pivot0:Pivot
Field pivot1:Pivot
Method New( title:String="Simple mojo3d 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 = 200.0
'create camera
_camera=New Camera( Self )
_camera.AddComponent<FlyBehaviour>()
_camera.Move( 0,2.5,-5 )
_camera.Rotate (-25, 0, 0)
'create light
_light=New Light
_light.CastsShadow=True
_light.Rotate( 45, 45, 0 )
'create ground
Local groundBox:=New Boxf( -100,-1,-100,100,0,100 )
Local groundMaterial:=New PbrMaterial( Color.Lime )
_ground=Model.CreateBox( groundBox,1,1,1,groundMaterial )
_ground.CastsShadow=False
pivot0 = New Pivot
pivot0.Move (-3, 7.5, 0)
pivot1 = New Pivot
pivot1.Move (3, 7.5, 0)
End
Method OnRender( canvas:Canvas ) Override
Local spread:Float = 0.025
If Keyboard.KeyHit (Key.Enter)
RocketParticle_Mesh.Create (pivot0, New Vec3f (Rnd (-spread, spread), 0.1, Rnd (-spread, spread)))
RocketParticle_Sprite.Create (pivot1, New Vec3f (Rnd (-spread, spread), 0.1, Rnd (-spread, spread)))
Endif
If Keyboard.KeyDown (Key.Space)
For Local loop:Int = 1 To 1
RocketParticle_Mesh.Create (pivot0, New Vec3f (Rnd (-spread, spread), 0.1, Rnd (-spread, spread)))
RocketParticle_Sprite.Create (pivot1, New Vec3f (Rnd (-spread, spread), 0.1, Rnd (-spread, spread)))
Next
Endif
If Keyboard.KeyHit (Key.Escape) Then App.Terminate ()
RequestRender()
_scene.Update()
_camera.Render( canvas )
canvas.DrawText( "FPS="+App.FPS,0,0 )
canvas.DrawText( "SPACE: Stream of particles",0,20 )
canvas.DrawText( "ENTER: Single particles",0,40 )
canvas.DrawText( "RocketParticle_Mesh on left",0,80 )
canvas.DrawText( "RocketParticle_Sprite on right",0,100 )
End
End
Function Main()
New AppInstance
New MyWindow
App.Run()
End
Original Author: DruggedBunny
Hi Mark,
Bit of an odd one I've run into while trying to convert my rocket smoke from cubes to sprites, sort of narrowed it down to the sample below.
In short, I'm firing a stream of physics-controlled particles that cycles through white, yellow, orange, red, black, then fade out. It should look like this (extreme debug version using cubes):
However, when using sprites, they start out correctly, then once a few of them are active at once, they start to flicker and jump.
You should be able to see it in the code below. Note that the class is duplicated, just that one uses cubes, other uses sprites.
Hold Space for a constant stream and note the cubes are fine, but the sprites start jumping and flickering. With short taps, the sprites are also OK, but held for a little longer, they start to mess up. (Tap Enter for single particles and note they only screw up if tapped rapidly.)
Thought it was some sort of alpha problem, but replacing alpha with a dummy variable (leaving entity alpha at 1.0 throughout) does the same thing.