mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-09-15 02:25:32 -04:00
Treat terrain particles as billboards, fixes issue #32 (thanks andrewphorn).
This commit is contained in:
parent
2f9d32fdfd
commit
dfac67c652
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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 ) {
|
||||
|
@ -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() {
|
||||
|
Loading…
x
Reference in New Issue
Block a user