
Среда программирования:
NetBeans 7.4
Статья по теме:
В классе Mandelbrot хранятся переменные вектора позиции и вращения.
Сама програма очень проста и состоит из следующего кода:
public Mandelbrot() { createDisplay(); setUpOpenGL(); setUpMandelbrot(); delta = getDelta(); // start timer while(!Display.isCloseRequested()) { draw(); processInput(); Display.sync(60); Display.update(); delta = getDelta(); } Display.destroy(); }
Функции:
createDisplay() создает экран
setUpOpenGL() инициализирует OpenGL
setUpMandelbrot() строит множество Мндельброта
и основной цикл:
draw(); вызов перересовки всех элементов
processInput(); обработать клавиатуру и мышь
Display.sync(60); Display.update(); delta = getDelta(); 60 кадров в секунду, обновить экран и таймер
Само построение множества делается при помощи OpenGL List, для того чтобы его каждый раз не пересчитывать:
mandelbrotDisplayList = glGenLists(1); glNewList(mandelbrotDisplayList, GL_COMPILE); glBegin(GL_QUADS); for (float y = -bound; y < bound; y += step) { for (float x = -bound; x < bound; x += step) { float X = 0; float Y = 0; int iter = 0; while (X*X + Y*Y < 4 && iter < maxIter) { float xtemp = X*X - Y*Y + x; Y = 2*X*Y + y; X = xtemp; iter++; } if (iter == 1000) continue; int r = (40 * iter) % 256; int g = (80 * iter) % 256; int b = (120 * iter) % 256; glColor3f(r/256.0f, g/256.0f, b/256.0f); glVertex3f(x, y, iter/1000.0f); glVertex3f(x + step, y, iter/1000.0f); glVertex3f(x + step, y + step, iter/1000.0f); glVertex3f(x, y + step, iter/1000.0f); } } glEnd(); glEndList();
Исходники прикреплены. Для запуска приложения на компьютере необходимо, чтобы была установлена Java. Запускать файл Mandelbrot.jar
Код программы:
package net.ilyi; import static org.lwjgl.util.glu.GLU.gluPerspective; import static org.lwjgl.opengl.GL11.*; import java.nio.ByteBuffer; import org.lwjgl.opengl.*; import org.lwjgl.input.*; import org.lwjgl.*; import org.newdawn.slick.Color; import java.nio.FloatBuffer; import org.lwjgl.util.vector.Vector3f; public class Mandelbrot { private static final int DISPLAY_WIDTH = 1270; private static final int DISPLAY_HEIGHT = 720; private Vector3f position = new Vector3f(0.0f, 0.0f, 0.0f); private Vector3f rotation = new Vector3f(90.0f, 0.0f, 0.0f); private int mandelbrotDisplayList; private int delta; public static void main(String[] args) { new Mandelbrot(); } public Mandelbrot() { createDisplay(); setUpOpenGL(); setUpMandelbrot(); delta = getDelta(); // start timer while(!Display.isCloseRequested()) { draw(); processInput(); Display.sync(60); Display.update(); delta = getDelta(); } Display.destroy(); } private void createDisplay() { try { Display.setDisplayMode(new DisplayMode(DISPLAY_WIDTH, DISPLAY_HEIGHT)); Display.setTitle("Mandelbrot"); ByteBuffer[] iconBuffer = new ByteBuffer[1]; // no icon iconBuffer[0] = BufferUtils.createByteBuffer(1); Display.setIcon(iconBuffer); Display.create(); } catch (LWJGLException ex) { ex.printStackTrace(); } } private void setUpOpenGL() { glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(90, (float)DISPLAY_WIDTH/DISPLAY_HEIGHT, 0.01F, 250.0f); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glEnable(GL_DEPTH_TEST); glEnable(GL_TEXTURE_2D); glEnable(GL_BLEND); glEnable(GL_ALPHA_TEST); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); setUpFog(); } private void setUpFog() { glEnable(GL_FOG); Color fogColor = new Color(0.0f, 0.0f, 0.0f, 1.0f); FloatBuffer fogColours = BufferUtils.createFloatBuffer(4); fogColours.put(new float[]{fogColor.r, fogColor.g, fogColor.b, fogColor.a}); glClearColor(fogColor.r, fogColor.g, fogColor.b, fogColor.a); fogColours.flip(); glFog(GL_FOG_COLOR, fogColours); glFogi(GL_FOG_MODE, GL_LINEAR); glHint(GL_FOG_HINT, GL_NICEST); glFogf(GL_FOG_START, 10.0f); glFogf(GL_FOG_END, 250.0f); glFogf(GL_FOG_DENSITY, 0.005f); } private final float bound = 2.0f; private float step = bound / 400.0f; private final int maxIter = 1000; private void setUpMandelbrot() { mandelbrotDisplayList = glGenLists(1); glNewList(mandelbrotDisplayList, GL_COMPILE); glBegin(GL_QUADS); for (float y = -bound; y < bound; y += step) { for (float x = -bound; x < bound; x += step) { float X = 0; float Y = 0; int iter = 0; while (X*X + Y*Y < 4 && iter < maxIter) { float xtemp = X*X - Y*Y + x; Y = 2*X*Y + y; X = xtemp; iter++; } if (iter == 1000) continue; int r = (40 * iter) % 256; int g = (80 * iter) % 256; int b = (120 * iter) % 256; glColor3f(r/256.0f, g/256.0f, b/256.0f); glVertex3f(x, y, iter/1000.0f); glVertex3f(x + step, y, iter/1000.0f); glVertex3f(x + step, y + step, iter/1000.0f); glVertex3f(x, y + step, iter/1000.0f); } } glEnd(); glEndList(); } private void draw() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glCallList(mandelbrotDisplayList); } private void processInput() { glLoadIdentity(); glRotatef(rotation.x, -1.0f, 0.0f, 0.0f); glRotatef(rotation.y, 0.0f, 1.0f, 0.0f); glRotatef(rotation.z, 0.0f, 0.0f, 1.0f); glTranslatef(-position.x, -position.y, -position.z); // mouse rotation float mouseSpeed = 0.16f; if (Mouse.isGrabbed()) { float mouseDX = Mouse.getDX() * mouseSpeed; float mouseDY = Mouse.getDY() * mouseSpeed; // horizontal rotation rotation.z += mouseDX; if (rotation.z >= 360.0f) rotation.z -= 360.0f; else if (rotation.z < 0.0f) rotation.z += 360.0f; // vertical rotation float maxLookDown = 5.0f; float maxLookUp = 175.0f; rotation.x += mouseDY; if (rotation.x < maxLookDown) rotation.x = maxLookDown; else if (rotation.x > maxLookUp) rotation.x = maxLookUp; } // mouse clicks while (Mouse.next()) { if (Mouse.isButtonDown(0)) Mouse.setGrabbed(true); if (Mouse.isButtonDown(1)) Mouse.setGrabbed(false); } // buttons boolean keyUp = Keyboard.isKeyDown(Keyboard.KEY_UP) || Keyboard.isKeyDown(Keyboard.KEY_W); boolean keyDown = Keyboard.isKeyDown(Keyboard.KEY_DOWN) || Keyboard.isKeyDown(Keyboard.KEY_S); boolean keyLeft = Keyboard.isKeyDown(Keyboard.KEY_LEFT) || Keyboard.isKeyDown(Keyboard.KEY_A); boolean keyRight = Keyboard.isKeyDown(Keyboard.KEY_RIGHT) || Keyboard.isKeyDown(Keyboard.KEY_D); boolean flyUp = Keyboard.isKeyDown(Keyboard.KEY_SPACE); boolean flyDown = Keyboard.isKeyDown(Keyboard.KEY_LCONTROL); boolean moveFaster = Keyboard.isKeyDown(Keyboard.KEY_LSHIFT); boolean moveSlower = Keyboard.isKeyDown(Keyboard.KEY_LMENU); // movement speed float walkingSpeed = 0.0004f; if (moveFaster && !moveSlower) walkingSpeed *= 20f; if (moveSlower && !moveFaster) walkingSpeed /= 10f; // horizontal movement (trigonometry) if (keyUp || keyRight || keyLeft || keyDown) { float angle = rotation.z + directionAngle(keyUp, keyRight, keyDown, keyLeft); float hyp = walkingSpeed * delta; float opp = hyp * (float) Math.sin(Math.toRadians(angle)); float adj = hyp * (float) Math.cos(Math.toRadians(angle)); position.x += opp; position.y += adj; } // vertical movement if (flyUp && !flyDown) position.z += walkingSpeed * delta; if (flyDown && !flyUp) position.z -= walkingSpeed * delta; // reset button while (Keyboard.next()) { if (Keyboard.isKeyDown(Keyboard.KEY_C)) { position = new Vector3f(0, 0, 0); rotation = new Vector3f(0, 0, 0); } } } /** * Returns proper angle for key combinations * @param keyUp Forward button. * @param keyRight Right button. * @param keyDown Down button. * @param keyLeft Left button. * @return Angle to add in degrees. */ private float directionAngle(boolean keyUp, boolean keyRight, boolean keyDown, boolean keyLeft) { if (keyUp && !keyRight && !keyDown && !keyLeft) return 0.0f; else if (keyUp && keyRight && !keyDown && !keyLeft) return 45.0f; else if (!keyUp && keyRight && !keyDown && !keyLeft) return 90.0f; else if (!keyUp && keyRight && keyDown && !keyLeft) return 135.0f; else if (!keyUp && !keyRight && keyDown && !keyLeft) return 180.0f; else if (!keyUp && !keyRight && keyDown && keyLeft) return 225.0f; else if (!keyUp && !keyRight && !keyDown && keyLeft) return 270.0f; else return 315.0f; } /** * Get delta-time value used in movement calculation. * @return delta-value. */ private static long prevTime; public static int getDelta() { long currTime = (Sys.getTime() * 1000) / Sys.getTimerResolution(); int delta = (int)(currTime - prevTime); prevTime = currTime; return delta; } }
Прикрепленный файл | Размер |
---|---|
Mandelbrot.zip | 1.94 Мб |