package efruchter.particles.sample.constraints; import static org.lwjgl.opengl.GL11.*; import java.util.ArrayList; import java.util.List; import org.lwjgl.Sys; import org.lwjgl.input.Keyboard; import org.lwjgl.opengl.Display; import org.lwjgl.opengl.DisplayMode; import org.lwjgl.util.Dimension; import efruchter.particles.constraints.Constraint; import efruchter.particles.datatypes.Particle; import efruchter.particles.integrators.CommonForceFunctions; import efruchter.particles.integrators.NewtonianIntegrators; import efruchter.particles.integrators.NewtonianIntegrators.AccelerationFunction; import efruchter.particles.integrators.NewtonianIntegrators.RKState; import efruchter.vectorutils.Vector3; /** * A tinker toy with a hard constraint, rather than soft springs. * * @author Eric * */ public class TinkerToyHard { /** Title */ static final String GAME_TITLE = "Tinker Toy 3D by Eric Fruchter"; /** Desired frame time */ static final int FRAMERATE = 60; /** Exit the game */ static boolean finished; static Dimension screen = new Dimension(600, 600); static float aspect = (float) screen.getWidth() / screen.getHeight(); /** * Standard gravity */ static float gScalar = 1f; /** * Stuff worth changing */ static Vector3 gravity = new Vector3(0, -9.806f * gScalar, 0); static float stepSize = .1f; static Particle anchor; static List<Particle> system = new ArrayList<Particle>(); static List<Constraint> constraints = new ArrayList<Constraint>(); /** * Application init * * @param args * Commandline args */ public static void main(String[] args) { try { init(false); run(); } catch (Exception e) { e.printStackTrace(System.err); Sys.alert(GAME_TITLE, "An error occured and the game will exit."); } finally { cleanup(); } System.exit(0); } /** * Initialize the game * * @throws Exception * if init fails */ private static void init(boolean fullscreen) throws Exception { Display.setTitle(GAME_TITLE); Display.setVSyncEnabled(true); Display.setDisplayMode(new DisplayMode(screen.getWidth(), screen.getHeight())); Display.create(); /* * GL Setup. */ glEnable(GL_DEPTH_TEST); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); /* * Add some particles! */ final Particle anchor = new Particle(new Vector3(0, 0, 0)); system.add(anchor); /* * Build the point that will swing */ final Particle p = new Particle(new Vector3(200, 200, 0)); constraints.add(new Constraint(anchor, p)); final float correctorRestlength = p.x.distance(anchor.x); p.accelerationFunction = new AccelerationFunction() { public Vector3 getAcceleration(final RKState state, float time) { Vector3 force = gravity; force = force.add(CommonForceFunctions.radialVirtual(state, anchor, force, p.m)); force = force.add(CommonForceFunctions.anchoredSpring(state, anchor, p.m, 1f, correctorRestlength)); return force; } }; system.add(p); } /** * Runs the game (the "main loop") */ private static void run() { while (!finished) { Display.update(); if (Display.isCloseRequested()) { finished = true; } else { logic(); render(); Display.sync(FRAMERATE); } } } /** * Do any game-specific cleanup */ private static void cleanup() { Display.destroy(); } /** * Do all calculations, handle input, etc. */ private static void logic() { if (Keyboard.isKeyDown(Keyboard.KEY_ESCAPE)) { finished = true; } // Clear for (Particle p : system) { p.clearForces(); } // Apply current accel function for (Particle p : system) { p.accumulateAccelFunction(); } // Accumulate / Integrate for (Particle p : system) { NewtonianIntegrators.rungeKutta4(p, stepSize); } /* * if (p.x.z > 100) { System.out.println("Energy gain : " + (p.x.z - * 100)); } System.out.println("Constraint diffe : " + * (p.x.distance(anchor.x))); */ } /** * Render the current frame */ private static void render() { glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0, screen.getWidth(), 0, screen.getHeight(), 0, 100); glMatrixMode(GL_MODELVIEW); glClearColor(.5f, 0.5f, 0.5f, .5f); // clear the screen glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glPushMatrix(); { glTranslatef(screen.getWidth() / 2, screen.getHeight() / 2, 0); /* * Draw the particle in the system */ glColor3f(1.0f, 0.0f, 0.0f); glPointSize(5.0f); glBegin(GL_POINTS); { for (Particle p : system) glVertex3f(p.x.x, p.x.y, p.x.z); } glEnd(); /* * Draw the lines */ glColor3f(0.0f, 0.0f, 1.0f); glLineWidth(2.0f); glBegin(GL_LINES); { for (Constraint p : constraints) { glVertex3f(p.getA().x.x, p.getA().x.y, p.getA().x.z); glVertex3f(p.getB().x.x, p.getB().x.y, p.getB().x.z); } } glEnd(); } glPopMatrix(); } }