Package wolf.gui

Source Code of wolf.gui.Camera

package wolf.gui;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.InputStreamReader;
import java.nio.ByteBuffer;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.util.ArrayList;
import java.util.Random;

import org.lwjgl.BufferUtils;
import org.lwjgl.LWJGLException;
import org.lwjgl.input.Keyboard;
import org.lwjgl.input.Mouse;
import org.lwjgl.opengl.ARBFragmentShader;
import org.lwjgl.opengl.ARBShaderObjects;
import org.lwjgl.opengl.ARBVertexShader;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL20;
import org.lwjgl.util.glu.GLUtessellator;
import org.lwjgl.util.glu.GLUtessellatorCallback;
import org.lwjgl.util.glu.GLUtessellatorCallbackAdapter;
import org.lwjgl.util.glu.Sphere;
import org.lwjgl.util.vector.Matrix3f;
import org.lwjgl.util.vector.Vector3f;

import com.vividsolutions.jts.algorithm.CGAlgorithms;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Geometry;

import wolf.city.City;
import wolf.city.block.CityBlock;
import wolf.city.block.Lot;
import wolf.city.buildings.FakeBuilding;
import wolf.city.road.Road;
import wolf.util.tess.TessCallback;
import wolf.util.tess.VertexData;

import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.util.glu.GLU.*;


public class Camera {
  private static final String WINDOW_TITLE = "World";
  public Vector3f pos;
  public Vector3f force;
  public Vector3f rot;
  private int windowWidth = 800;
  private int windowHeight = 640;
  private float fov = 80;
  private float zFar = 4000f;
  private float zNear = 4f;
  private float mouseSensitivity = .2f;
  private boolean lookAtCenter;
  private boolean renderBuildings = true;
  private boolean renderBlocksAndLots = false;
  private GLUtessellator tess = gluNewTess();

  private int shader = 0;
  private int vertShader = 0;
  private int fragShader = 0;

  private boolean useShader = true;
  private int program=0;

  private int cityList;
  private City c;
  private long lastNanoTime;


  public Camera(City city){
    pos = new Vector3f(0,0,-1000);
    rot = new Vector3f(0,0,0);
    force = new Vector3f(0,0,0);
    c = city;
    try {
      Display.setDisplayMode(new DisplayMode(windowWidth, windowHeight));
      Display.create();
    } catch (LWJGLException e) {
      System.setProperty("org.lwjgl.opengl.Display.allowSoftwareOpenGL", "true");
      try {
        Display.setDisplayMode(new DisplayMode(windowWidth, windowHeight));
        Display.create();
      } catch (LWJGLException e1) {
        e.printStackTrace();
        e1.printStackTrace();
        System.exit(0);
      }
    }

    Display.setTitle(WINDOW_TITLE);
    Display.setVSyncEnabled(true);
    glEnable(GL_LINE_SMOOTH);
    //glEnable(GL_CULL_FACE);
    //glEnable(GL_LIGHTING);
    glEnable(GL_DEPTH_TEST);
    //    glEnable(GL_LIGHTING);
    //glEnable(GL_LIGHT0);
    //glEnable(GL_COLOR_MATERIAL);
    //glColorMaterial(GL_FRONT,GL_AMBIENT_AND_DIFFUSE);
    //glEnable(GL_BLEND);
    //glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
    glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glViewport(0,0,windowWidth,windowHeight);
    gluPerspective(fov, (float)windowWidth/(float)windowHeight, zNear, zFar);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
   
    tess.gluTessProperty(GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_POSITIVE);
    GLUtessellatorCallback callback = new TessCallback();
        tess.gluTessCallback(GLU_TESS_VERTEX, callback);
        tess.gluTessCallback(GLU_TESS_BEGIN, callback);
        tess.gluTessCallback(GLU_TESS_END, callback);
        tess.gluTessCallback(GLU_TESS_COMBINE, callback);
    /*
     * create the shader program. If OK, create vertex
     * and fragment shaders
     */
    try {
      vertShader = createShader("shaders/basic.vert",ARBVertexShader.GL_VERTEX_SHADER_ARB);
      fragShader = createShader("shaders/basic.frag",ARBFragmentShader.GL_FRAGMENT_SHADER_ARB);
    }
    catch(Exception exc) {
      exc.printStackTrace();
      return;
    }
    finally {
      if(vertShader == 0 || fragShader == 0){
        System.out.println("Shaders broke or something");
        return;
      }
    }

    program = ARBShaderObjects.glCreateProgramObjectARB();

    if(program == 0)
      return;

    /*
     * if the vertex and fragment shaders setup sucessfully,
     * attach them to the shader program, link the sahder program
     * (into the GL context I suppose), and validate
     */
    ARBShaderObjects.glAttachObjectARB(program, vertShader);
    ARBShaderObjects.glAttachObjectARB(program, fragShader);

    ARBShaderObjects.glLinkProgramARB(program);
    if (ARBShaderObjects.glGetObjectParameteriARB(program, ARBShaderObjects.GL_OBJECT_LINK_STATUS_ARB) == GL_FALSE) {
      System.err.println(getLogInfo(program));
      return;
    }

    ARBShaderObjects.glValidateProgramARB(program);
    if (ARBShaderObjects.glGetObjectParameteriARB(program, ARBShaderObjects.GL_OBJECT_VALIDATE_STATUS_ARB) == GL_FALSE) {
      System.err.println(getLogInfo(program));
      return;
    }

    useShader = true;



    //set up 3d info
    //Random r = new Random(1);
    cityList = glGenLists(1);

    glNewList(cityList, GL_COMPILE);
    //    Sphere s = new Sphere();
    //    s.draw(150, 25, 25);
    //make the display list
    if(c.rm.roads != null && c.rm.roads.size() > 0){ //road render
      int red = 0;
      int blue = 0;
      int alpha = 0;
      int green = 0;
      ArrayList<Road> roadList = (ArrayList<Road>) c.rm.roads.queryAll();
      for(int i=0; i<roadList.size(); i++){
        Road road =roadList.get(i);
        Geometry g = road.getGeometry();
        switch(road.getType()){
        case BRIDGE:{ //grey
          red = 50;
          green = 50;
          blue = 50;
          break;
        }
        case HIGHWAY:{
          red = 50;
          green = 50;
          blue = 55;
          break;
        }
        case STREET:{
          red = 50;
          green = 50;
          blue = 55;
          break;
        }
        case MAIN:{
          red = 75;
          green = 75;
          blue = 75;
          break;
        }
        case DEFAULT:{ //red
          red = 255;
          green = 0;
          blue = 0;
          break;
        }
        default:{ //red
          red = 255;
          green = 0;
          blue = 0;
          break;
        }
        }
        Coordinate[] cs = g.reverse().getCoordinates();
        if(cs.length >= 3){
          glBegin(GL_QUADS);
          glColor4ub((byte)red, (byte)green, (byte)blue, (byte)alpha);

          Vector3f n = normal(cs[0], cs[1], cs[2]);
          glNormal3f(n.x, n.y, n.z);
          for(int j=0;j<4;j++){
            Coordinate p = cs[j];
            glVertex3d(p.x,p.y,c.ter.get((int)p.x, (int)p.y));

          }
          glEnd();
        }
      }

    }
    if(renderBlocksAndLots  && c.bm.blocks != null && c.bm.blocks.size() > 0){
      for(CityBlock b : c.bm.blocks){
        if(b.lots != null && b.lots.size()>0){
          for(Lot l: b.lots){

            Coordinate[] cs = l.shape.reverse().getCoordinates();
            glBegin(GL_LINE_LOOP);
            glColor3f(.3f,.3f,.3f);
            //Coordinate q = cs[cs.length-1];
            //glVertex2d(q.x,q.y);
            for(int j=0;j<cs.length;j++){
              Coordinate p = cs[j];
              glVertex3d(p.x,p.y,c.ter.get((int)p.x, (int)p.y));
            }
            glEnd();
          }
          Coordinate[] cs = b.shape.getCoordinates();
          glBegin(GL_LINE_LOOP);
          glColor3f(.2f,.2f,.3f);
          for(int j=0;j<cs.length;j++){
            Coordinate p = cs[j];
            glVertex3d(p.x,p.y,c.ter.get((int)p.x, (int)p.y));

          }
          glEnd();
        }else{
          //render block
        }
      }
    }
    if(renderBuildings && c.fb != null && c.fb.buildings.size() > 0){
      if(useShader){
        ARBShaderObjects.glUseProgramObjectARB(program);
        GL20.glUniform1f(GL20.glGetUniformLocation(program, "shininess"), 1f);
        System.out.println("Using shader");
      }
      for(FakeBuilding b : c.fb.buildings){
        Coordinate[] cs = b.g.getCoordinates();
        if(!CGAlgorithms.isCCW(cs)) cs = b.g.reverse().getCoordinates();
        if(cs.length >= 3){
          glBegin(GL11.GL_POLYGON);
          Vector3f n = normal(cs[0], cs[1], cs[2]);
          //render top of building
//          tess.gluTessBeginPolygon(null);
//          tess.gluTessBeginContour();
//          tess.gluTessNormal(n.x, n.y, n.z);
          glNormal3f(n.x,n.y,n.z);
          for(int j=cs.length-1; j>=0; j--){
            Coordinate p = cs[j];
            glVertex3d(p.x,p.y,p.z+b.height);
//            double[] vert = new double[]{p.x,p.y,p.z+b.height};
//            tess.gluTessVertex(vert, 0, new VertexData(vert));
          }
//          tess.gluTessEndContour();
//          tess.gluTessEndPolygon();
          glEnd();
          /*glBegin(GL_LINES);
          glVertex3d(cs[0].x,cs[0].y,cs[0].z+b.height);
          float normalLen = 50;
          glVertex3d(cs[0].x+(n.x*normalLen),cs[0].y+(n.y*normalLen),cs[0].z+b.height+(n.z*normalLen));
          glEnd();*/
          glBegin(GL_POLYGON);
          //render bottom of building
//          tess.gluBeginPolygon();
//          tess.gluTessBeginContour();
//          tess.gluTessNormal(n.x, n.y, -n.z);
          glNormal3f(n.x,n.y,-n.z);
          for(int j=0;j<cs.length;j++){
            Coordinate p = cs[j];
            glVertex3d(p.x,p.y,p.z);

          }
//          tess.gluTessEndContour();
//          tess.gluEndPolygon();
          glEnd();

          //float rand = r.nextFloat()/5;
          //glColor3f(.3f+rand,.3f+rand,.3f+rand);

          if(cs.length>0){
            Coordinate q = cs[0];

            for(int j=cs.length-1;j>=0;j--){
              //glColor3f(r.nextFloat(),r.nextFloat(),r.nextFloat());
              Coordinate p = cs[j];
              Vector3f n1 = normal(new Coordinate(q.x,q.y,p.z), new Coordinate(q.x,q.y,p.z+b.height), new Coordinate(p.x,p.y,p.z+b.height));
              glBegin(GL_QUADS);
              glNormal3f(n1.x, n1.y, n1.z);
              glVertex3d(q.x,q.y,p.z);
              glVertex3d(q.x,q.y,p.z+b.height);
              glVertex3d(p.x,p.y,p.z+b.height);             
              glVertex3d(p.x,p.y,p.z);
              glEnd();

              q = cs[j];
            }
           
            /*
            Coordinate q = cs[cs.length-1];

            for(int j=0;j<cs.length;j++){
              //glColor3f(r.nextFloat(),r.nextFloat(),r.nextFloat());
              Coordinate p = cs[j];
              Vector3f n1 = normal(new Coordinate(q.x,q.y,p.z), new Coordinate(q.x,q.y,p.z+b.height), new Coordinate(p.x,p.y,p.z+b.height));
              glBegin(GL_QUADS);
              glNormal3f(n1.x, n1.y, n1.z);
              glVertex3d(q.x,q.y,p.z);
              glVertex3d(q.x,q.y,p.z+b.height);
              glVertex3d(p.x,p.y,p.z+b.height);             
              glVertex3d(p.x,p.y,p.z);
              glEnd();

              q = cs[j];
            }
             */
          }

        }
      }
      //release the shader
      ARBShaderObjects.glUseProgramObjectARB(0);
    }
    ByteBuffer posbuff = ByteBuffer.allocateDirect(4*Float.SIZE/8);
    posbuff.putFloat(1.0f).putFloat(1.0f).putFloat(1.0f).putFloat(0.0f).flip();
    glLight(GL_LIGHT0, GL_POSITION, posbuff.asFloatBuffer());
    glEndList();

  }

  public void rotate(float x, float y, float z){
    rot.x += x;
    rot.y += y;
    rot.z += z;
  }

  public void translate(float x, float y, float z){
    pos.x += x;
    pos.y += y;
    pos.z += z;
  }

  public void addForce(float x, float y, float z){
    force.x += x;
    force.y += y;
    force.z += z;
  }

  public void move(Vector3f v, float dist){
    Vector3f mx = (Vector3f) rotX(rotY(new Vector3f(1,0,0), rot.x), rot.y).scale(v.x);
    Vector3f my = (Vector3f) rotX(rotY(new Vector3f(0,1,0), rot.x), rot.y).scale(v.y);
    Vector3f mz = (Vector3f) rotX(rotY(new Vector3f(0,0,1), rot.x), rot.y).scale(v.z);

    Vector3f posChange1 = new Vector3f();
    Vector3f posChange = new Vector3f();
    Vector3f.add(mx, my, posChange1);
    Vector3f.add(posChange1, mz, posChange);

    Vector3f.add(posChange, pos, pos);
  }

  /*
   *   p += v.x*roty(rotx(vec(1.0, 0.0, 0.0), CameraPhi), CameraTheta) +
   *  v.y*roty(rotx(vec(0.0, 1.0, 0.0), CameraPhi), CameraTheta) +
   *  v.z*roty(rotx(vec(0.0, 0.0, 1.0), CameraPhi), CameraTheta);
   */

  public Vector3f rotX(Vector3f v, double a){
    double c = Math.toRadians(a);
    return new Vector3f(v.x, (float)(v.y*Math.cos(c) - v.z*Math.sin(c)), (float)(v.y*Math.sin(c) + v.z*Math.cos(c)));
  }

  public Vector3f rotY(Vector3f v, double a){
    double c = Math.toRadians(a);
    return new Vector3f((float)(v.x*Math.cos(c) + v.z*Math.sin(c)), v.y, (float)(-v.x*Math.sin(c) + v.z*Math.cos(c)));
  }

  public Vector3f rotZ(Vector3f v, double a){
    double c = Math.toRadians(a);
    return new Vector3f((float)(v.x*Math.cos(c) - v.y*Math.sin(c)), (float)(v.x*Math.sin(c) + v.y*Math.cos(c)), v.z);
  }

  private void update(){
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(fov, (float)windowWidth/(float)windowHeight, zNear, zFar);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    //update matrix

    Vector3f.add(force, pos, pos);
    glRotatef(rot.x, 1, 0, 0);
    glRotatef(rot.y, 0, 1, 0);
    glRotatef(rot.z, 0, 0, 1);

    if(lookAtCenter){
      gluLookAt(-pos.x,-pos.y,-pos.z,0,0,0,0,1,0);
    }else{
      //gluLookAt(-pos.x,-pos.y,-pos.z,0,0,0,0,1,0);
      glTranslatef(pos.x, pos.y, pos.z);
    }
  }

  //newell's method
  private static Vector3f normal(Coordinate[] cs){
    Vector3f normal = new Vector3f(0,0,0);
    for(int i=0; i<cs.length; i++){
      Vector3f cur = new Vector3f((float)cs[i].x, (float)cs[i].y, (float)((cs[i].z != Double.NaN) ? cs[i].z : 0));
      Vector3f next = new Vector3f((float)cs[(i+1) % cs.length].x, (float)cs[(i+1) % cs.length].y, (float)((cs[(i+1) % cs.length].z != Double.NaN) ? cs[(i+1) % cs.length].z : 0));

      normal.x = normal.x + ((cur.y - next.y) * (cur.z - next.z));
      normal.y = normal.y + ((cur.z - next.z) * (cur.x - next.x));
      normal.z = normal.z + ((cur.x - next.x) * (cur.y - next.y));
    }

    //normalize the normal vector!
    normalize(normal);
    return normal;
  }

  private static Vector3f normal(Coordinate a, Coordinate b, Coordinate c){
    Vector3f u = new Vector3f((float)(b.x-a.x), (float)(b.y-a.y), (float)(b.z-a.z));
    Vector3f v = new Vector3f((float)(c.x-a.x), (float)(c.y-a.y), (float)(c.z-a.z));

    return normalize(new Vector3f((u.y*u.z)-(u.z*v.y), ((u.z*v.x)-(u.x*v.z)), ((u.x*v.y)-(u.y*v.x))));
  }

  private static Vector3f normalize(Vector3f v){
    float length = (float)Math.sqrt(Math.pow(v.x,2)+Math.pow(v.y,2)+Math.pow(v.z,2));
    v.x /= length;
    v.y /= length;
    v.z /= length;
    return v;
  }

  private void input(){
    long nanoTime = System.nanoTime();
    long deltaTime = nanoTime-lastNanoTime;
    lastNanoTime = nanoTime;
    if(Mouse.isButtonDown(0) && Mouse.isInsideWindow()){
      //Mouse.setGrabbed(true);
      rot.y += Mouse.getDX()*mouseSensitivity;
      rot.x -= Mouse.getDY()*mouseSensitivity;
    }else{
      //Mouse.setGrabbed(false);
      Mouse.getDX();
      Mouse.getDY();
    }
    float speed;
    if(Keyboard.isKeyDown(Keyboard.KEY_LSHIFT)){
      speed = .0000000005f;
    }else{
      speed = .0000000001f;
    }

    if(Keyboard.isKeyDown(Keyboard.KEY_Q)){
      //move(new Vector3f(0,0,1),.000001f);
      addForce(0,0,-speed*deltaTime);
    }
    if(Keyboard.isKeyDown(Keyboard.KEY_E)){
      //move(new Vector3f(0,0,1),.000001f);
      addForce(0,0,speed*deltaTime);
    }
    if(Keyboard.isKeyDown(Keyboard.KEY_S)){
      //move(new Vector3f(0,0,1),.000001f);
      addForce(0,speed*deltaTime,0);
    }
    if(Keyboard.isKeyDown(Keyboard.KEY_W)){
      //move(new Vector3f(0,0,1),.000001f);
      addForce(0,-speed*deltaTime,0);
    }
    if(Keyboard.isKeyDown(Keyboard.KEY_A)){
      //move(new Vector3f(0,0,1),.000001f);
      addForce(speed*deltaTime,0,0);
    }
    if(Keyboard.isKeyDown(Keyboard.KEY_D)){
      //move(new Vector3f(0,0,1),.000001f);
      addForce(-speed*deltaTime,0,0);
    }
    if(Keyboard.isKeyDown(Keyboard.KEY_Z)){
      force = new Vector3f(0,0,0);
    }
    if(Keyboard.isKeyDown(Keyboard.KEY_SPACE)){
      lookAtCenter = true;
    }else{
      lookAtCenter = false;
    }
  }

  public void render(){
    if(!Display.isCloseRequested()){
      glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

      input();
      //rotate(0,0,.01f);
      update();
      glCallList(cityList);

      Display.update();
    }else{
      Display.destroy();
      c.windowClosed();
      System.exit(0);
    }
  }

  /*
   * With the exception of syntax, setting up vertex and fragment shaders
   * is the same.
   * @param the name and path to the vertex shader
   */
  private int createShader(String filename, int shaderType) throws Exception {
    int shader = 0;
    try {
      shader = ARBShaderObjects.glCreateShaderObjectARB(shaderType);

      if(shader == 0)
        return 0;

      ARBShaderObjects.glShaderSourceARB(shader, readFileAsString(filename));
      ARBShaderObjects.glCompileShaderARB(shader);

      if (ARBShaderObjects.glGetObjectParameteriARB(shader, ARBShaderObjects.GL_OBJECT_COMPILE_STATUS_ARB) == GL_FALSE)
        throw new RuntimeException("Error creating shader: " + getLogInfo(shader));

      return shader;
    }
    catch(Exception exc) {
      ARBShaderObjects.glDeleteObjectARB(shader);
      throw exc;
    }
  }

  private static String getLogInfo(int obj) {
    return ARBShaderObjects.glGetInfoLogARB(obj, ARBShaderObjects.glGetObjectParameteriARB(obj, ARBShaderObjects.GL_OBJECT_INFO_LOG_LENGTH_ARB));
  }

  private String readFileAsString(String filename) throws Exception {
    StringBuilder source = new StringBuilder();

    FileInputStream in = new FileInputStream(filename);

    Exception exception = null;

    BufferedReader reader;
    try{
      reader = new BufferedReader(new InputStreamReader(in,"UTF-8"));

      Exception innerExc= null;
      try {
        String line;
        while((line = reader.readLine()) != null)
          source.append(line).append('\n');
      }
      catch(Exception exc) {
        exception = exc;
      }
      finally {
        try {
          reader.close();
        }
        catch(Exception exc) {
          if(innerExc == null)
            innerExc = exc;
          else
            exc.printStackTrace();
        }
      }

      if(innerExc != null)
        throw innerExc;
    }
    catch(Exception exc) {
      exception = exc;
    }
    finally {
      try {
        in.close();
      }
      catch(Exception exc) {
        if(exception == null)
          exception = exc;
        else
          exc.printStackTrace();
      }

      if(exception != null)
        throw exception;
    }

    return source.toString();
  }
}
TOP

Related Classes of wolf.gui.Camera

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.