Particle effect example

From JPCT
Revision as of 06:13, 21 September 2017 by Corey (Talk | contribs)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

Particle effect example

Details

A straightforward particle effect demonstration that uses the opengl renderer.

Screen shot

Firepit particle.png

Source code


import java.awt.Color;
import java.io.File;

import org.lwjgl.LWJGLException;
import org.lwjgl.input.Keyboard;
import org.lwjgl.input.Mouse;
import org.lwjgl.opengl.Display;

import com.threed.jpct.*;

/**
 * A simple particle demonstration.
 * In the demo we use a fire model, with 2 types of particles: flames and smoke.
 *
 * The code is not the best, but it should give you a general idea
 * on how to create particle effects for your own project.
 * 
 * @author 'words' - jPCT.net
 */
public class ParticleDemo {

	private World world;
	private FrameBuffer frameBuffer;

	private Object3D fireModel;
	private GenericParticle particleTest;

	public ParticleDemo() {
		try {
			initGL();
		} catch (LWJGLException e) {
			e.printStackTrace();
			System.exit(1);
		}

		/*
		 * Initialize the world
		 */
		this.world = new World();
		world.setAmbientLight(60, 60, 60);

		/*
		 * Load the model
		 */
		TextureManager.getInstance().addTexture("flame", new Texture("res/flame.jpg"));
		TextureManager.getInstance().addTexture("smoke", new Texture("res/smoke.jpg"));
		fireModel = Object3D.mergeAll(Loader.load3DS("res/firepit.3ds", 4f));
		TextureManager.getInstance().addTexture("firepit", new Texture("res/firepit.jpg"));
		fireModel.setTexture("firepit");
		fireModel.rotateX((float) (-.5 * Math.PI)); // correct the rotation
		fireModel.rotateMesh();
		fireModel.setRotationMatrix(new Matrix());

		/*
		 * Setup the camera
		 */
		Camera camera = world.getCamera();
		camera.moveCamera(Camera.CAMERA_MOVEOUT, 45); // zoom
		camera.moveCamera(Camera.CAMERA_MOVEUP, 45); // height
		camera.lookAt(new SimpleVector(10, 0, 10));
		camera.setFOV(1.5f);

		// Example!
		addFire(10, 0, 10);

		/*
		 * Start the main loop:
		 */
		boolean running = true;
		while (running) {
			if (Display.isCloseRequested()) {
				running = false;
				return;
			}
			render();
			if (particleTest != null) {
				particleTest.update(world);
			}
		}
		shutdown();
	}

	private void addFire(float x, float y, float z) {
		Object3D fire = fireModel.cloneObject();
		fire.translate(x, y ,z);
		world.addObject(fire);
		this.particleTest = new GenericParticle(world, fire.getTransformedCenter());

	}

	private void initGL() throws LWJGLException {
		Logger.setLogLevel(Logger.LL_ONLY_ERRORS);
		Logger.setOnError(Logger.ON_ERROR_THROW_EXCEPTION);

		Config.glWindowName = "Particle Demo - jPCT " + Config.getVersion();
		Config.maxPolysVisible = 5000; // The maximum size of the VisList.

		this.frameBuffer = new FrameBuffer(640, 480, FrameBuffer.SAMPLINGMODE_HARDWARE_ONLY);
		frameBuffer.disableRenderer(IRenderer.RENDERER_SOFTWARE);
		frameBuffer.enableRenderer(IRenderer.RENDERER_OPENGL);
		Display.setResizable(true);
		Mouse.create();
	}

	private void render() {
		frameBuffer.clear(Color.BLACK);
		world.renderScene(frameBuffer);
		world.draw(frameBuffer);
		frameBuffer.update();
		frameBuffer.displayGLOnly();

		pollKeyboard();
		pollMouse();
	}

	private void pollKeyboard() {
		while (Keyboard.next()) {
			final int keyCode = Keyboard.getEventKey();
			@SuppressWarnings("unused")
			final boolean pressed = Keyboard.getEventKeyState();
			if (keyCode == Keyboard.KEY_ESCAPE) {
				frameBuffer.dispose();
				System.exit(0);
			}
		}
	}

	private void pollMouse() {
		while (Mouse.next()) {
			if (Mouse.getEventButtonState()) {
				switch (Mouse.getEventButton()) {
				case 0: // left mouse button was clicked
					break;
				case 1: // right mouse button was clicked
					break;
				}
			}
		}
	}

	private void shutdown() {
		frameBuffer.dispose();
		Display.destroy();
		System.exit(0);
	}

	public static void main(String[] args) {
		String platform = System.getProperty("os.name").toLowerCase();
		String path = "./lib/native/";
		if (platform.indexOf("win") >= 0) {
			System.setProperty("org.lwjgl.librarypath", new File(path + "windows/").getAbsolutePath());
		} else if (platform.indexOf("mac") >= 0) {
			System.setProperty("org.lwjgl.librarypath", new File(path + "macosx/").getAbsolutePath());
		} else if ((platform.indexOf("nix") >= 0 || platform.indexOf("nux") >= 0 || platform.indexOf("aix") > 0)) {
			System.setProperty("org.lwjgl.librarypath", new File(path + "linux/").getAbsolutePath());
		} else if (platform.indexOf("sunos") >= 0) {
			System.setProperty("org.lwjgl.librarypath", new File(path + "solaris/").getAbsolutePath());
		}
		new ParticleDemo();
	}

}

import java.awt.Color;

import com.threed.jpct.Matrix;
import com.threed.jpct.Object3D;
import com.threed.jpct.Primitives;
import com.threed.jpct.SimpleVector;
import com.threed.jpct.World;
import com.threed.jpct.util.Light;

/**
 * A generic particle handler.
 *
 */
public class GenericParticle {

	private final SimpleVector origin;
	private final Particle[] particles;
	private final int PARTICLE_COUNT = 1;
	private int count = 0;
	private long delay = System.currentTimeMillis();
	private int cycle = 0;
	private boolean firstTick = false;

	public GenericParticle(final World world, final SimpleVector origin) {
		this.origin = origin;
		this.particles = new Particle[25];
	}
	
	public void update(final World world) {
		if (!firstTick) {
			firstTick = true;
			Light light = new Light(world);
			light.setPosition(new SimpleVector(origin.x, origin.y - 40, origin.z));
			light.setAttenuation(-1);
			light.setIntensity(255, 255, 255);
			light.setDiscardDistance(500);
			light.enable();
		}
		if (System.currentTimeMillis() - delay > 120) {
			cycle++;
			if (cycle % 2 == 0) {
				for (int i = 0; i < PARTICLE_COUNT; i++) {
					// add particle
					Particle p = getParticle(world);
					p.setTranslationMatrix(new Matrix());
					p.setOrigin(origin);
					p.setVelocity(new SimpleVector(1 - Math.random() * 1,  -1.4 - (Math.random() / 2f), 1 - Math.random() * 1));
					p.reset();

				}
				// move the visible particles
				for (int i = 0; i < count; i++) {
					Particle pp = particles[i];
					if (pp.getVisibility()) {
						pp.move(1);
					}
				}
			}
			delay = System.currentTimeMillis();
		}

	}
	
	private Particle getParticle(World w) {
		for (int i = 0; i < count; i++) {
			Particle pp = particles[i];
			if (!pp.getVisibility()) {
				pp.setVisibility(Object3D.OBJ_VISIBLE);
				return pp;
			}
		}
		Particle p = new Particle();
		w.addObject(p);
		particles[count] = p;
		count++;
		return p;
	}

}

@SuppressWarnings("serial")
class Particle extends Object3D {

	private SimpleVector vel = new SimpleVector();
	private long time = 0;
	private long maxTime = 2000;
	private static final SimpleVector GRAV = new SimpleVector(0, -0.50f, 0);

	Particle() {
		super(Primitives.getPlane(2, 5));
		this.setBillboarding(true);
		this.setVisibility(true);
		this.setTransparency(12);
		this.setAdditionalColor(Color.WHITE);
		this.setLighting(Object3D.LIGHTING_NO_LIGHTS);
		this.enableLazyTransformations();
		this.build();
		reset();
	}

	void setVelocity(SimpleVector vel) {
		this.vel.set(vel);
	}

	void reset() {
		this.setTexture("flame");
		time = System.currentTimeMillis();
		getTranslationMatrix().setIdentity();
	}

	void move(int ticks) {
		if (getVisibility()) {
			if (System.currentTimeMillis() - time > 333) {
				this.setTexture("smoke");
			}
			for (int i = 0; i < ticks; i++) {
				vel.add(GRAV);
				this.translate(vel);
			}
			if (System.currentTimeMillis() - time > maxTime) {
				reset();
				this.setVisibility(Object3D.OBJ_INVISIBLE);
			}
		}
	}
	
}

Download Link

http://www.mediafire.com/file/qzoo4arg67loa4z/fireparticle_res.zip