383 lines
8.2 KiB
Java
Executable File
383 lines
8.2 KiB
Java
Executable File
package projectzombie.entity.particle;
|
|
|
|
import static org.lwjgl.opengl.GL15.glBindBuffer;
|
|
import static org.lwjgl.opengl.GL15.glBufferData;
|
|
import static org.lwjgl.opengl.GL15.glGenBuffers;
|
|
|
|
import java.util.Random;
|
|
|
|
import org.lwjgl.opengl.GL33;
|
|
|
|
import gl_engine.MathHelpers;
|
|
import gl_engine.matrix.Matrix4;
|
|
import gl_engine.texture.TextureRef3D;
|
|
import gl_engine.vec.Vec2d;
|
|
import gl_engine.vec.Vec2i;
|
|
import gl_engine.vec.Vec3d;
|
|
import projectzombie.Main;
|
|
import projectzombie.entity.EntityParticle;
|
|
import projectzombie.init.Models;
|
|
import projectzombie.model.IModel;
|
|
import projectzombie.model.Model;
|
|
import projectzombie.model.ModelVertical;
|
|
import projectzombie.world.chunk.Chunk;
|
|
import projectzombie.world.layer.Layer;
|
|
|
|
public class ParticleBreak extends EntityParticle implements IModel
|
|
{
|
|
protected static final Random rand = new Random();
|
|
|
|
protected class Break {
|
|
TextureRef3D ref;
|
|
Vec3d velocity;
|
|
Vec3d pos;
|
|
boolean moving;
|
|
int time, flags;
|
|
}
|
|
|
|
protected Break[] particles;
|
|
private int ibo, vbo, vao;
|
|
private boolean generated;
|
|
protected int dead, still, time;
|
|
protected double still_ypos;
|
|
protected boolean do_gravity;
|
|
|
|
public Vec2d getParticleSize() {
|
|
return new Vec2d(0.1, 0.1);
|
|
}
|
|
|
|
public ParticleBreak(Vec3d pos, Vec3d velocity, IModel model) {
|
|
this(pos, velocity, model, 200, 0.05);
|
|
}
|
|
|
|
public ParticleBreak(Vec3d pos, Vec3d velocity, IModel model, int count) {
|
|
this(pos, velocity, model, count, 0.05);
|
|
}
|
|
|
|
protected Break createParticle(
|
|
IModel model, TextureRef3D ref, int tex_id,
|
|
Vec3d pos, Vec3d velocity, float[] verticies,
|
|
double velocity_up_multiplier, double model_height, int i)
|
|
{
|
|
Break particle = new Break();
|
|
|
|
particle.pos = pos.add(new Vec3d(0, rand.nextDouble() * model_height, 0));
|
|
particle.velocity = velocity.multiply(rand.nextDouble()).add(
|
|
MathHelpers.moveTowards2(0.01, rand.nextDouble() * MathHelpers.TWO_PI).xny().add(
|
|
new Vec3d(0, rand.nextDouble() * velocity_up_multiplier, 0)));
|
|
particle.ref = ref;
|
|
particle.moving = true;
|
|
particle.flags = ((int)verticies[tex_id * Model.SIZE + Model.SIZE - 1] & 0b0110) | 0b1000;
|
|
|
|
return particle;
|
|
}
|
|
|
|
protected ParticleBreak(Vec3d pos, Vec3d velocity, IModel model, int count, double velocity_up_multiplier) {
|
|
super(new Vec3d(pos.x, 0, pos.z), new Vec3d(0, 0, 0));
|
|
|
|
if(pos.squareDistance(Main.player.getPos()) > 32) {
|
|
count = 0;
|
|
}
|
|
|
|
this.hasGravity = false;
|
|
|
|
double model_height = model.getHeight();
|
|
TextureRef3D[] textures = model.getTextures();
|
|
float[] verticies = model.getVerticies();
|
|
|
|
count *= model_height;
|
|
particles = new Break[count];
|
|
|
|
for(int i=0;i<particles.length;i++)
|
|
{
|
|
int tex_id = (int)(rand.nextDouble() * textures.length);
|
|
TextureRef3D texture = textures[tex_id];
|
|
TextureRef3D ref = new TextureRef3D();
|
|
|
|
float dx = texture.ex - texture.sx;
|
|
float dy = texture.ey - texture.sy;
|
|
float w = (float)model.getWidth();
|
|
float h = (float)model.getHeight();
|
|
|
|
ref.sx = (float)MathHelpers.map((int)(rand.nextDouble()*16*w), 0, 16*w, texture.sx, texture.ex - dx/(16*w));
|
|
ref.sy = (float)MathHelpers.map((int)(rand.nextDouble()*16*h), 0, 16*h, texture.sy, texture.ey - dy/(16*h));
|
|
ref.ex = ref.sx + dx/(16*w);
|
|
ref.ey = ref.sy + dy/(16*h);
|
|
|
|
ref.texmap = texture.texmap;
|
|
ref.z = texture.z;
|
|
|
|
Break particle = createParticle(
|
|
model, ref, tex_id, pos, velocity,
|
|
verticies, velocity_up_multiplier,
|
|
model_height, i);
|
|
|
|
particles[i] = particle;
|
|
}
|
|
|
|
time = 1000;
|
|
generated = false;
|
|
do_gravity = true;
|
|
still = 0;
|
|
dead = 0;
|
|
}
|
|
|
|
protected void onAllStill() {
|
|
if(time < 0 && rand.nextDouble() > 0.75) {
|
|
dead += 1;
|
|
}
|
|
}
|
|
|
|
protected void onAllDead() {
|
|
if(getPos().squareDistance(Main.player.getPos()) > 32) {
|
|
kill();
|
|
}
|
|
}
|
|
|
|
protected boolean isStill(Break particle) {
|
|
return particle.pos.y < 0;
|
|
}
|
|
|
|
protected void onStill(Break particle) {
|
|
particle.moving = false;
|
|
particle.pos.y = still_ypos;
|
|
still += 1;
|
|
}
|
|
|
|
@Override
|
|
public void tick(Chunk chunk, Layer layer) {
|
|
super.tick(chunk, layer);
|
|
|
|
if(isDead()) {
|
|
return;
|
|
}
|
|
|
|
time -= 1;
|
|
|
|
if(dead == particles.length - 1) {
|
|
onAllDead();
|
|
return;
|
|
}
|
|
|
|
if(still == particles.length) {
|
|
onAllStill();
|
|
return;
|
|
}
|
|
|
|
for(int i=0;i<(particles.length - dead);i++)
|
|
{
|
|
Break particle = particles[i];
|
|
|
|
if(!particle.moving) {
|
|
continue;
|
|
}
|
|
|
|
if(isStill(particle)) {
|
|
onStill(particle);
|
|
continue;
|
|
}
|
|
|
|
if(do_gravity) {
|
|
particle.velocity.y -= MathHelpers.FallSpeed;
|
|
}
|
|
|
|
particle.pos = particle.pos.add(particle.velocity);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void kill() {
|
|
this.free();
|
|
super.kill();
|
|
}
|
|
|
|
@Override
|
|
public IModel getModel()
|
|
{
|
|
if(isDead()) {
|
|
return Models.EMPTY;
|
|
}
|
|
|
|
return this;
|
|
}
|
|
|
|
@Override
|
|
public int[] getIndicies()
|
|
{
|
|
int[] indicies = new int[getIndexSize()];
|
|
int upto = 0;
|
|
|
|
for(int i=0;i<indicies.length;i+=6)
|
|
{
|
|
indicies[i+0] = upto+0;
|
|
indicies[i+1] = upto+1;
|
|
indicies[i+2] = upto+2;
|
|
indicies[i+3] = upto+2;
|
|
indicies[i+4] = upto+3;
|
|
indicies[i+5] = upto+0;
|
|
upto += 4;
|
|
}
|
|
|
|
return indicies;
|
|
}
|
|
|
|
@Override
|
|
public float[] getVerticies()
|
|
{
|
|
float[] verticies = new float[getSize() * Model.SIZE];
|
|
Vec3d ppos = getPos();
|
|
|
|
int upto = 0;
|
|
float k = Model.OFFSET;
|
|
float x = (float)getParticleSize().x/2;
|
|
float y = (float)getParticleSize().y;
|
|
|
|
for(int i=0;i<(particles.length - dead);i++)
|
|
{
|
|
Break particle = particles[i];
|
|
TextureRef3D ref = particle.ref;
|
|
|
|
float f = particle.flags;
|
|
float px = (float)(particle.pos.x - ppos.x);
|
|
float py = (float)(particle.pos.y - ppos.y);
|
|
float pz = (float)(particle.pos.z - ppos.z);
|
|
float a = y, b = 0, c = 0;
|
|
|
|
if(!particle.moving) {
|
|
f = particle.flags & 0b0110;
|
|
a = 0.001f;
|
|
b = y / 2;
|
|
c = a;
|
|
}
|
|
|
|
float[] p = {
|
|
-x, c,-b, ref.sx+k, ref.sy+k, ref.z, ref.sy, ref.ey, px, py, pz, 1, 1, f,
|
|
x, c,-b, ref.ex-k, ref.sy+k, ref.z, ref.sy, ref.ey, px, py, pz, 1, 1, f,
|
|
x, a, b, ref.ex-k, ref.ey-k, ref.z, ref.sy, ref.ey, px, py, pz, 1, 1, f,
|
|
-x, a, b, ref.sx+k, ref.ey-k, ref.z, ref.sy, ref.ey, px, py, pz, 1, 1, f,
|
|
};
|
|
|
|
for(int j=0;j<p.length;j++) {
|
|
verticies[upto+j] = p[j];
|
|
}
|
|
|
|
upto += 4*Model.SIZE;
|
|
}
|
|
|
|
return verticies;
|
|
}
|
|
|
|
@Override
|
|
public TextureRef3D[] getTextures()
|
|
{
|
|
TextureRef3D[] textures = new TextureRef3D[getSize()];
|
|
int upto = 0;
|
|
|
|
for(int i=0;i<particles.length;i++) {
|
|
textures[upto+0] = particles[i].ref;
|
|
textures[upto+1] = particles[i].ref;
|
|
textures[upto+2] = particles[i].ref;
|
|
textures[upto+3] = particles[i].ref;
|
|
upto += 4;
|
|
}
|
|
|
|
return textures;
|
|
}
|
|
|
|
@Override
|
|
public double getHeight() {
|
|
return 1;
|
|
}
|
|
|
|
@Override
|
|
public int getIndexSize() {
|
|
return 6 * (particles.length - dead);
|
|
}
|
|
|
|
@Override
|
|
public int getSize() {
|
|
return 4 * (particles.length - dead);
|
|
}
|
|
|
|
@Override
|
|
public void bind()
|
|
{
|
|
if(isDead()) {
|
|
return;
|
|
}
|
|
|
|
if(!generated)
|
|
{
|
|
int[] indicies = this.getIndicies();
|
|
|
|
vao = GL33.glGenVertexArrays();
|
|
GL33.glBindVertexArray(vao);
|
|
|
|
vbo = GL33.glGenBuffers();
|
|
GL33.glBindBuffer(GL33.GL_ARRAY_BUFFER, vbo);
|
|
GL33.glBufferData(GL33.GL_ARRAY_BUFFER, getVerticies(), GL33.GL_DYNAMIC_DRAW);
|
|
|
|
Model.setGLArrayAttributes();
|
|
|
|
ibo = glGenBuffers();
|
|
glBindBuffer(GL33.GL_ELEMENT_ARRAY_BUFFER, ibo);
|
|
glBufferData(GL33.GL_ELEMENT_ARRAY_BUFFER, indicies, GL33.GL_STATIC_DRAW);
|
|
}
|
|
|
|
else {
|
|
GL33.glBindVertexArray(vao);
|
|
}
|
|
|
|
generated = true;
|
|
Model.bound = this;
|
|
}
|
|
|
|
@Override
|
|
public void render()
|
|
{
|
|
if(isDead()) {
|
|
return;
|
|
}
|
|
|
|
if(Model.bound != this) {
|
|
bind();
|
|
}
|
|
|
|
if(still != particles.length) {
|
|
GL33.glBindBuffer(GL33.GL_ARRAY_BUFFER, vbo);
|
|
GL33.glBufferSubData(GL33.GL_ARRAY_BUFFER, 0, getVerticies());
|
|
}
|
|
|
|
GL33.glDrawElements(GL33.GL_TRIANGLES, getIndexSize(), GL33.GL_UNSIGNED_INT, 0);
|
|
}
|
|
|
|
@Override
|
|
public void free()
|
|
{
|
|
if(generated)
|
|
{
|
|
GL33.glDeleteBuffers(ibo);
|
|
GL33.glDeleteBuffers(vbo);
|
|
GL33.glDeleteVertexArrays(vao);
|
|
generated = false;
|
|
}
|
|
}
|
|
|
|
public void setModel(Matrix4 model) {
|
|
GL33.glUniformMatrix4fv(Main.window.glsl_model, true, model.getArray());
|
|
}
|
|
|
|
@Override
|
|
public boolean isLoaded() {
|
|
return generated;
|
|
}
|
|
|
|
@Override
|
|
public double getWidth() {
|
|
return 1;
|
|
}
|
|
|
|
|
|
|
|
}
|