diff --git a/ClassicalSharp/Entities/Particles/Particle.cs b/ClassicalSharp/Entities/Particles/Particle.cs index b45766f9f..d97e15c6f 100644 --- a/ClassicalSharp/Entities/Particles/Particle.cs +++ b/ClassicalSharp/Entities/Particles/Particle.cs @@ -7,25 +7,46 @@ namespace ClassicalSharp.Particles { public Vector3 Position; public Vector3 Velocity; - public Vector2 Size = new Vector2( 0.0625f, 0.0625f ); - public double Lifetime = 0; - public Game Window; + public Vector2 Size = new Vector2( 1 / 16f, 1 / 16f ); + public TextureRectangle Rectangle; + public double Lifetime; + protected Game game; protected Vector3 lastPos, nextPos; public abstract void Render( double delta, float t, VertexPos3fTex2f[] vertices, ref int index ); public abstract void Dispose(); - public Particle( Game window, Vector3 pos, Vector3 velocity, double lifetime ) { - Window = window; + public Particle( Game window, Vector3 pos, Vector3 velocity, double lifetime, TextureRectangle rec ) { + game = window; Position = lastPos = nextPos = pos; Velocity = velocity; Lifetime = lifetime; + Rectangle = rec; } public virtual bool Tick( double delta ) { Lifetime -= delta; return Lifetime < 0; } + + // http://www.opengl-tutorial.org/intermediate-tutorials/billboards-particles/billboards/ + protected void TranslatePoints( out Vector3 p111, out Vector3 p121, out Vector3 p212, out Vector3 p222 ) { + Vector3 centre = Position; + Matrix4 camera = game.View; + Vector3 right = new Vector3( camera.Row0.X, camera.Row1.X, camera.Row2.X ); + Vector3 up = new Vector3( camera.Row0.Y, camera.Row1.Y, camera.Row2.Y ); + float x = Size.X * 8, y = Size.Y * 8; + centre.Y += Size.Y / 2; + + p111 = Transform( -x, -y, ref centre, ref up, ref right ); + p121 = Transform( -x, y, ref centre, ref up, ref right ); + p212 = Transform( x, -y, ref centre, ref up, ref right ); + p222 = Transform( x, y, ref centre, ref up, ref right ); + } + + Vector3 Transform( float x, float y, ref Vector3 centre, ref Vector3 up, ref Vector3 right ) { + return centre + right * x * Size.X + up * y * Size.Y; + } } } \ No newline at end of file diff --git a/ClassicalSharp/Entities/Particles/TerrainParticle.cs b/ClassicalSharp/Entities/Particles/TerrainParticle.cs index 712faa4e3..5c48e1d48 100644 --- a/ClassicalSharp/Entities/Particles/TerrainParticle.cs +++ b/ClassicalSharp/Entities/Particles/TerrainParticle.cs @@ -5,27 +5,26 @@ namespace ClassicalSharp.Particles { public sealed class TerrainParticle : Particle { - public TextureRectangle Rectangle; const float gravity = 2.4f; double maxY = 0; - public TerrainParticle( Game window, Vector3 pos, Vector3 velocity, double lifetime, TextureRectangle rec ) - : base( window, pos, velocity, lifetime ) { - Rectangle = rec; + public TerrainParticle( Game game, Vector3 pos, Vector3 velocity, double lifetime, TextureRectangle rec ) + : base( game, pos, velocity, lifetime, rec ) { maxY = Position.Y; } public override void Render( double delta, float t, VertexPos3fTex2f[] vertices, ref int index ) { Position = Vector3.Lerp( lastPos, nextPos, t ); - float x1 = Position.X, y1 = Position.Y, z1 = Position.Z, - x2 = Position.X + Size.X, y2 = Position.Y + Size.Y; - vertices[index++] = new VertexPos3fTex2f( x1, y1, z1, Rectangle.U1, Rectangle.V2 ); - vertices[index++] = new VertexPos3fTex2f( x1, y2, z1, Rectangle.U1, Rectangle.V1 ); - vertices[index++] = new VertexPos3fTex2f( x2, y2, z1, Rectangle.U2, Rectangle.V1 ); + Vector3 p111, p121, p212, p222; + TranslatePoints( out p111, out p121, out p212, out p222 ); - vertices[index++] = new VertexPos3fTex2f( x1, y1, z1, Rectangle.U1, Rectangle.V2 ); - vertices[index++] = new VertexPos3fTex2f( x2, y1, z1, Rectangle.U2, Rectangle.V2 ); - vertices[index++] = new VertexPos3fTex2f( x2, y2, z1, Rectangle.U2, Rectangle.V1 ); + vertices[index++] = new VertexPos3fTex2f( p111, Rectangle.U1, Rectangle.V2 ); + vertices[index++] = new VertexPos3fTex2f( p121, Rectangle.U1, Rectangle.V1 ); + vertices[index++] = new VertexPos3fTex2f( p222, Rectangle.U2, Rectangle.V1 ); + + vertices[index++] = new VertexPos3fTex2f( p222, Rectangle.U2, Rectangle.V1 ); + vertices[index++] = new VertexPos3fTex2f( p212, Rectangle.U2, Rectangle.V2 ); + vertices[index++] = new VertexPos3fTex2f( p111, Rectangle.U1, Rectangle.V2 ); } public override bool Tick( double delta ) { @@ -34,8 +33,8 @@ namespace ClassicalSharp.Particles { int startY = (int)Math.Floor( Position.Y ); Position += Velocity * (float)delta; int endY = (int)Math.Floor( Position.Y ); - Utils.Clamp( ref Position.X, 0, Window.Map.Width - 0.01f ); - Utils.Clamp( ref Position.Z, 0, Window.Map.Length - 0.01f ); + Utils.Clamp( ref Position.X, 0, game.Map.Width - 0.01f ); + Utils.Clamp( ref Position.Z, 0, game.Map.Length - 0.01f ); if( endY <= startY ) { for( int y = startY; y >= endY; y-- ) { @@ -43,10 +42,10 @@ namespace ClassicalSharp.Particles { return CollideWithGround( 0 ) ? true : base.Tick( delta ); } byte block = GetBlock( (int)Position.X, y, (int)Position.Z ); - if( block == 0 || Window.BlockInfo.IsSprite( block ) || Window.BlockInfo.IsLiquid( block ) ) + if( block == 0 || game.BlockInfo.IsSprite( block ) || game.BlockInfo.IsLiquid( block ) ) continue; - float groundHeight = y + Window.BlockInfo.BlockHeight( block ); + float groundHeight = y + game.BlockInfo.BlockHeight( block ); if( Position.Y < groundHeight ) { return CollideWithGround( groundHeight ) ? true : base.Tick( delta ); } @@ -60,8 +59,8 @@ namespace ClassicalSharp.Particles { byte GetBlock( int x, int y, int z ) { // If particles are spawned at the top of the map, they can occasionally // go outside the top of the map. This is okay, so handle this case. - if( y >= Window.Map.Height ) return 0; - return Window.Map.GetBlock( x, y, z ); + if( y >= game.Map.Height ) return 0; + return game.Map.GetBlock( x, y, z ); } bool CollideWithGround( float y ) { diff --git a/ClassicalSharp/GraphicsAPI/VertexFormats.cs b/ClassicalSharp/GraphicsAPI/VertexFormats.cs index 70f81b577..a556199cd 100644 --- a/ClassicalSharp/GraphicsAPI/VertexFormats.cs +++ b/ClassicalSharp/GraphicsAPI/VertexFormats.cs @@ -1,6 +1,7 @@ using System; using System.Drawing; using System.Runtime.InteropServices; +using OpenTK; namespace ClassicalSharp { @@ -98,6 +99,11 @@ namespace ClassicalSharp { U = u; V = v; } + public VertexPos3fTex2f( Vector3 p, float u, float v ) { + X = p.X; Y = p.Y; Z = p.Z; + U = u; V = v; + } + public const int Size = 20; // (4 + 4 + 4) + (4 + 4) public override string ToString() {