/** * 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! */ for (int k = 0; k < 1; k++) for (int i = 0; i < cloth.length; i++) { for (int j = 0; j < cloth[0].length; j++) { float x = j * 5 + (k == 0 ? 0 : 10); float y = -200 + i * 30; float z = 500 + j * 30; system.add(cloth[i][j][k] = new Particle(new Vector3(x, y, z))); if (i > 0) constraints.add(new DistanceConstraint(cloth[i][j][k], cloth[i - 1][j][k])); if (j > 0) constraints.add(new DistanceConstraint(cloth[i][j][k], cloth[i][j - 1][k])); if (k > 0) { constraints.add(new DistanceConstraint(cloth[i][j][k], cloth[i][j][k - 1])); } } } // for (int i = 0; i < 1000; i++) { // constraints.remove((int) (constraints.size() * Math.random())); // } anchorL = cloth[0][0][0].x; anchorR = cloth[cloth[0].length - 1][0][0].x; }
/** * A particle constraint toy. * * @author toriscope */ public class ClothSim { /** 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; /** Angle of rotating square */ static float angle; static Dimension screen = new Dimension(800, 600); static float aspect = (float) screen.getWidth() / screen.getHeight(); static Vector3 anchorL; static Vector3 anchorR; /* * TESTBED */ static List<Particle> system = new LinkedList<Particle>(); static List<Constraint> constraints = new LinkedList<Constraint>(); /** Standard gravity */ static float gScalar = .5f; /** Stuff worth changing */ static Vector3 gravity = new Vector3(0, 0, -9.806f * gScalar); static Particle[][][] cloth = new Particle[50][50][1]; static float stepSize = .3f, moveS = 50; static int integrationIterations = 20; static UniverseCube cube; static { cube = new UniverseCube(120); cube.pos = new Vector3(cube.pos.x, cube.pos.y, cube.sideLength / 2); cube.recalcBoundaries(); DistanceConstraint.DEFAULT_SQUISH = 1.0f; } /** * 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! */ for (int k = 0; k < 1; k++) for (int i = 0; i < cloth.length; i++) { for (int j = 0; j < cloth[0].length; j++) { float x = j * 5 + (k == 0 ? 0 : 10); float y = -200 + i * 30; float z = 500 + j * 30; system.add(cloth[i][j][k] = new Particle(new Vector3(x, y, z))); if (i > 0) constraints.add(new DistanceConstraint(cloth[i][j][k], cloth[i - 1][j][k])); if (j > 0) constraints.add(new DistanceConstraint(cloth[i][j][k], cloth[i][j - 1][k])); if (k > 0) { constraints.add(new DistanceConstraint(cloth[i][j][k], cloth[i][j][k - 1])); } } } // for (int i = 0; i < 1000; i++) { // constraints.remove((int) (constraints.size() * Math.random())); // } anchorL = cloth[0][0][0].x; anchorR = cloth[cloth[0].length - 1][0][0].x; } /** 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; } int dx = Mouse.getDX(), dy = Mouse.getDY(), dz = Mouse.getDWheel(); if (Mouse.isButtonDown(0) && Mouse.isInsideWindow()) { Vector3 d = new Vector3(dx, dy, 0); anchorL = anchorL.sub(d); anchorR = anchorR.sub(d); } if (Mouse.isButtonDown(1) && Mouse.isInsideWindow()) { Vector3 d = new Vector3(0, dy, 0); anchorL = anchorL.sub(d); anchorR = anchorR.add(d); } Vector3 zChange = new Vector3(0, 0, dz / 4); anchorL = anchorL.add(zChange); anchorR = anchorR.add(zChange); /* * Move those particles! */ // Clear force accumulator for (Particle p : system) p.clearForces(); // Accumulate forces for (Particle p : system) p.addForce(gravity); // Integrate for (Particle p : system) NewtonianIntegrators.verlet(p, stepSize); /* * Formal and informal constraint check. */ for (int i = 0; i < integrationIterations; i++) { cloth[0][0][0].x = anchorL; cloth[cloth[0].length / 2][0][0].x = anchorL.add(anchorR).scale(.5f); cloth[cloth[0].length - 1][0][0].x = anchorR; // bounds check float dragFloat = 10; Vector3 zFloor = new Vector3(0, 0, 1); for (Particle p : system) { if (p.x.z <= 0 + 1) { p.x = p.x.add(zFloor); p.xOld = p.x.add(p.xOld.scale(dragFloat)).scale(1f / (dragFloat + 1)); } } // for (Particle p : system) { // if (cube.isWithin(p.x)) { // cube.escape(p); // } // } for (Constraint c : constraints) c.satisfy(); } } /** Render the current frame */ private static void render() { glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(30f, aspect, 1f, 10000000f); float look = anchorL.z * 5; gluLookAt(look, look, anchorL.z, 0, 0, 0, 0, 0, 1); glClearColor(.5f, 0.5f, 0.5f, .5f); // clear the screen glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glPushMatrix(); { // int systemDimLength = cube.sideLength / 2; // rotate square according to angle glRotatef(angle, 0, 0, 1.0f); // glColor3f(1f, 1f, 1f); // cube.glSurfaceDraw(); /* * Draw the particle in the system */ glColor3f(0.0f, 1.0f, 0.0f); glPointSize(3.0f); /* * glBegin(GL_POINTS); { for (Particle p : system) { * glVertex3f(p.x.x, p.x.y, p.x.z); } } glEnd(); */ /* * Draw the lines */ glLineWidth(2.0f); for (Constraint p : constraints) { glBegin(GL_LINES); { 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(); } /* * Shadows, just for effect! */ glColor4f(0, 0, 0, .5f); /* * glBegin(GL_POINTS); { for (Particle p : system) { * glVertex3f(p.x.x, p.x.y, -systemDimLength); } } glEnd(); */ /* * Draw the line shadows */ for (Constraint p : constraints) { glBegin(GL_LINES); { glVertex3f(p.getA().x.x, p.getA().x.y, -0); glVertex3f(p.getB().x.x, p.getB().x.y, -0); } glEnd(); } glBegin(GL_LINES); { glVertex3f(anchorL.x, anchorL.y, -0); glVertex3f(anchorR.x, anchorR.y, -0); } glEnd(); glColor3f(1, 0, 0); /* * Draw the tension line */ glBegin(GL_LINES); { glVertex3f(anchorL.x, anchorL.y, -0); glVertex3f(anchorL.x, anchorL.y, anchorL.z); glVertex3f(anchorL.x, anchorL.y, anchorL.z); glVertex3f(anchorR.x, anchorR.y, anchorR.z); glVertex3f(anchorR.x, anchorR.y, anchorR.z); glVertex3f(anchorR.x, anchorR.y, -0); } glEnd(); } glPopMatrix(); } }
@Override public void render(GameContainer gameContainer, StateBasedGame stateBasedGame, Graphics graphics) throws SlickException { background.draw(0, 0); tandwiel1.draw( -tandwiel1.getWidth() / 2, AsaGame.SOURCE_RESOLUTION.height / 2 - tandwiel1.getHeight() / 2); tandwiel2.draw( tandwiel1.getWidth() / 2 - tandwielOffset - 40, AsaGame.SOURCE_RESOLUTION.height / 2 - tandwiel2.getHeight()); graphics.setFont(fontBlack); if (baseImage != null) { webcamFeed .getSubImage(80, 0, 480, 480) .draw(center.getWidth() - ((500) / 2), center.getHeight() - (500 / 2), 500, 500); background_spinner_half.draw( center.getWidth() - background_spinner.getWidth() / 2, center.getHeight() + 45); } else { background_spinner.draw( center.getWidth() - background_spinner.getWidth() / 2, center.getHeight() - background_spinner.getHeight() / 2); } if (mode == 1) { spinner.draw( center.getWidth() - spinner.getWidth() / 2, center.getHeight() - spinner.getHeight() / 2); spinneroverlay.draw( center.getWidth() - spinner.getWidth() / 2, center.getHeight() - spinner.getHeight() / 2); selectImage.draw(center.getWidth() / 2 - 20, 60); choise.draw( choise.getWidth() * 0.15f, center.getHeight() * 2 - choise.getHeight() * 1.6f, pulseScale); for (int i = 0; i < wheelOptions.size(); i++) { float offsetDegree = 360 / wheelOptions.size(); float degrees = (270 + ((rotation + rotationDelta) % 360 + offsetDegree * i) % 360) % 360; if (degrees < 0) { degrees = degrees + 360; } float rad = (float) (degrees * (Math.PI / 180)); float radius = 313; float x = (float) (center.getWidth() + radius * Math.cos(rad)); float y = (float) (center.getHeight() + radius * Math.sin(rad)); WheelOptionYesNo option = wheelOptions.get(i); Image optionIcon = option.getIcon(); float biggerThanDegrees = 270 + (offsetDegree / 2); if (biggerThanDegrees > 360) { biggerThanDegrees = biggerThanDegrees - 360; } if (degrees >= 270 - (offsetDegree / 2) && degrees < biggerThanDegrees) { x = x - (float) (optionIcon.getWidth() * 1.3 / 2); y = y - (float) (optionIcon.getHeight() * 1.3 / 2); option.getIcon().draw(x, y, (float) 1.3); } else { x = x - (float) (optionIcon.getWidth() * 1 / 2); y = y - (float) (optionIcon.getHeight() * 1 / 2); option.getIcon().draw(x, y); } if (degrees >= 270 - (offsetDegree / 2) && degrees < biggerThanDegrees) { selectedOption = i; } } } else { lens.draw(center.getWidth() - (550 / 2), center.getHeight() - (550 / 2)); spinner.draw( center.getWidth() - spinner.getWidth() / 2, center.getHeight() - spinner.getHeight() / 2); spinneroverlay.draw( center.getWidth() - spinner.getWidth() / 2, center.getHeight() - spinner.getHeight() / 2); if (drawCountdown) { countdown.draw(center.getWidth() - 75, center.getHeight() + 75, 150, 150); } } }