Package com.bulletphysics.demos.applet

Source Code of com.bulletphysics.demos.applet.Graphics3D

/*
* Software OpenGL-like 3D renderer (c) 2008 Martin Dvorak <jezek2@advel.cz>
*
* This software is provided 'as-is', without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from
* the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
*    claim that you wrote the original software. If you use this software
*    in a product, an acknowledgment in the product documentation would be
*    appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
*    misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*/

package com.bulletphysics.demos.applet;

import javax.vecmath.Color3f;
import javax.vecmath.Matrix4f;
import javax.vecmath.Tuple3f;
import javax.vecmath.Vector3f;
import javax.vecmath.Vector4f;

/**
*
* @author jezek2
*/
public class Graphics3D {

  public static final int COLOR_BUFFER = Rasterizer.COLOR_BUFFER;
  public static final int DEPTH_BUFFER = Rasterizer.DEPTH_BUFFER;
 
  public static final int TRIANGLES    = 1;
  public static final int TRIANGLE_FAN = 2;
  public static final int QUADS        = 3;
  public static final int QUAD_STRIP   = 4;
  public static final int LINES        = 5;
 
  private Rasterizer rasterizer = new Rasterizer();
  private Vector4f[] vertices = new Vector4f[64];
  private Vector3f[] normals = new Vector3f[64];
  private Color3f[] colors = new Color3f[64];

  private int clippedCount;
  private Vector4f[] clippedVertices = new Vector4f[64];
  private Color3f[] clippedColors = new Color3f[64];
 
  private int primitiveType, primitivePos;
  private Vector3f currentNormal = new Vector3f();
  private Color3f currentColor = new Color3f();
 
  private Matrix4f projMatrix = new Matrix4f();
  private Matrix4f viewMatrix = new Matrix4f();
  private Matrix4f mergedMatrix = new Matrix4f();
  private boolean matrixDirty = false;
 
  private Color3f clearColor = new Color3f();
 
  private Matrix4f[] viewMatStack = new Matrix4f[16];
  private int viewMatStackTop = 0;
 
  private boolean lightingEnabled = false;
  private Light[] lights = new Light[4];
 
  private Vector3f origColor = new Vector3f();
  private Vector3f tmpVec3 = new Vector3f();
  private Vector3f[] lightResult = new Vector3f[lights.length];

  public Graphics3D() {
    for (int i=0; i<vertices.length; i++) vertices[i] = new Vector4f();
    for (int i=0; i<normals.length; i++) normals[i] = new Vector3f();
    for (int i=0; i<colors.length; i++) colors[i] = new Color3f();

    for (int i=0; i<clippedVertices.length; i++) clippedVertices[i] = new Vector4f();
    for (int i=0; i<clippedColors.length; i++) clippedColors[i] = new Color3f();
   
    viewMatrix.setIdentity();
   
    for (int i=0; i<viewMatStack.length; i++) viewMatStack[i] = new Matrix4f();
    for (int i=0; i<lights.length; i++) lights[i] = new Light();
    for (int i=0; i<lightResult.length; i++) lightResult[i] = new Vector3f();
  }
 
  public void init(int[] pixels, int width, int height) {
    rasterizer.init(pixels, width, height);
  }

  public void setClearColor(float r, float g, float b) {
    this.clearColor.set(r, g, b);
  }
 
  public void clear(int bufferMask) {
    rasterizer.clear(bufferMask, clearColor);
  }
 
  public void begin(int type) {
    if (primitiveType != 0) throw new IllegalStateException();
    primitiveType = type;
    primitivePos = 0;
  }
 
  public void end() {
    switch (primitiveType) {
      case TRIANGLE_FAN:
        transform(0, primitivePos);
        drawPolygon(primitivePos);
        break;
    }
   
    primitiveType = 0;
  }
 
  public void setNormal(float x, float y, float z) {
    currentNormal.set(x, y, z);
  }
 
  public void setColor(float r, float g, float b) {
    currentColor.set(r, g, b);
  }
 
  public void addVertex(float x, float y, float z) {
    colors[primitivePos].set(currentColor);
    normals[primitivePos].set(currentNormal);
    vertices[primitivePos].set(x, y, z, 1f);
    primitivePos++;
   
    switch (primitiveType) {
      case TRIANGLES:
        if (primitivePos == 3) {
          transform(0, 3);
          drawPolygon(3);
          primitivePos = 0;
        }
        break;
       
      case QUADS:
        if (primitivePos == 4) {
          transform(0, 4);
          drawPolygon(4);
          primitivePos = 0;
        }
        break;
       
      case QUAD_STRIP:
        if (primitivePos == 2) {
          transform(0, 2);
        }
       
        if (primitivePos == 3) {
          transform(2, 3);
          drawPolygon(3);
          shift(1, 3, 1);
          primitivePos = 2;
        }
        break;
       
      case LINES:
        if (primitivePos == 2) {
          transform(0, 2);
          drawLine();
          primitivePos = 0;
        }
        break;
    }
  }
 
  private void shift(int start, int count, int amount) {
    for (int i=start; i<count; i++) {
      vertices[i-amount].set(vertices[i]);
      normals[i-amount].set(normals[i]);
      colors[i-amount].set(colors[i]);
    }
  }

  public void setProjMatrix(Matrix4f mat) {
    projMatrix.set(mat);
    matrixDirty = true;
  }

  public void mulProjMatrix(Matrix4f mat) {
    projMatrix.mul(mat);
    matrixDirty = true;
  }
 
  public void setViewMatrix(Matrix4f mat) {
    viewMatrix.set(mat);
    matrixDirty = true;
  }

  public void mulViewMatrix(Matrix4f mat) {
    viewMatrix.mul(mat);
    matrixDirty = true;
  }

  public void pushViewMatrix() {
    viewMatStack[viewMatStackTop++].set(viewMatrix);
  }
 
  public void pushViewMatrix(Matrix4f mat, boolean multiply) {
    viewMatStack[viewMatStackTop++].set(viewMatrix);
    if (multiply) {
      viewMatrix.mul(mat);
    }
    else {
      viewMatrix.set(mat);
    }
    matrixDirty = true;
  }
 
  public void popViewMatrix() {
    viewMatrix.set(viewMatStack[--viewMatStackTop]);
    matrixDirty = true;
  }
 
  public void flush() {
  }

  public void setLightingEnabled(boolean b) {
    lightingEnabled = b;
  }

  public Light getLight(int num) {
    return lights[num];
  }
 
  ////////////////////////////////////////////////////////////////////////////
 
  private void updateMatrix() {
    mergedMatrix.mul(projMatrix, viewMatrix);
    matrixDirty = false;
  }
 
  private void transform(int start, int num) {
    if (matrixDirty) {
      updateMatrix();
    }
   
    for (int i=start; i<num; i++) {
      mergedMatrix.transform(vertices[i]);
      mergedMatrix.transform(normals[i]);
      normals[i].normalize();
     
      if (lightingEnabled && primitiveType != LINES) {
        for (int j=0; j<lights.length; j++) {
          Light l = lights[j];
          if (!l.enabled) continue;

          lightResult[j].set(l.ambient.x, l.ambient.y, l.ambient.z);
          tmpVec3.set(l.position.x, l.position.y, l.position.z);
          float dot = normals[i].dot(tmpVec3);
          if (dot < 0f) dot = 0f;
          tmpVec3.set(l.diffuse.x, l.diffuse.y, l.diffuse.z);
          lightResult[j].scaleAdd(dot, tmpVec3, lightResult[j]);
          lightResult[j].x = lightResult[j].x * colors[i].x;
          lightResult[j].y = lightResult[j].y * colors[i].y;
          lightResult[j].z = lightResult[j].z * colors[i].z;
        }

        colors[i].set(0f, 0f, 0f);
        for (int j=0; j<lights.length; j++) {
          if (!lights[j].enabled) continue;

          colors[i].add(lightResult[j]);
        }

        clamp(colors[i], 0f, 1f);
      }
    }
  }
 
  private void clamp(Tuple3f t, float min, float max) {
    t.x = Math.min(Math.max(min, t.x), max);
    t.y = Math.min(Math.max(min, t.y), max);
    t.z = Math.min(Math.max(min, t.z), max);
  }
 
  private void drawPolygon(int num) {
    Boolean needsClip = clip(num);
    if (needsClip == null) return;
   
    rasterizer.drawPolygon(clippedCount, clippedVertices, needsClip? clippedColors : colors);
  }
 
  private void drawLine() {
    Boolean needsClip = clip(2);
    if (needsClip == null) return;
   
    rasterizer.drawLine(clippedVertices, needsClip? clippedColors : colors);
  }
 
  private Boolean clip(int num) {
    boolean needsClip = false, visible = false;
    for (int i=0; i<num; i++) {
      if (vertices[i].z < 0f) {
        needsClip = true;
      }
      else {
        visible = true;
      }
    }
   
    if (!visible) {
      return null;
    }
   
    if (needsClip) {
      clippedCount = 0;
      for (int i=0; i<num; i++) {
        clipEdge(i, (i+1)%num);
      }
    }
    else {
      clippedCount = num;
      for (int i=0; i<num; i++) {
        clippedVertices[i].set(vertices[i]);
      }
    }

    for (int i=0; i<clippedCount; i++) {
      clippedVertices[i].scale(1f / clippedVertices[i].w);
     
      clippedVertices[i].x = (clippedVertices[i].x+1f) * rasterizer.getWidth() * 0.5f;
      clippedVertices[i].y = rasterizer.getHeight() - 1 - (clippedVertices[i].y+1f) * rasterizer.getHeight() * 0.5f;
    }
   
    return needsClip;
  }

  private void clipEdge(int v1, int v2) {
    Vector4f vtx1 = vertices[v1];
    Vector4f vtx2 = vertices[v2];
   
    Color3f c1 = colors[v1];
    Color3f c2 = colors[v2];
   
    float minZ = 0f;
    float m = 1f;
   
    float dold = vtx2.z - vtx1.z;
    float dnew = minZ - vtx1.z;
    if (dold != 0f) {
      m = dnew / dold;
    }
   
    if (vtx1.z >= minZ && vtx2.z >= minZ) {
      clippedVertices[clippedCount].set(vtx2);
      clippedColors[clippedCount].set(c2);
      clippedCount++;
    }
    else if (vtx1.z >= minZ && vtx2.z < minZ) {
      clippedVertices[clippedCount].x = vtx1.x + (vtx2.x - vtx1.x)*m;
      clippedVertices[clippedCount].y = vtx1.y + (vtx2.y - vtx1.y)*m;
      clippedVertices[clippedCount].z = vtx1.z + (vtx2.z - vtx1.z)*m;
      clippedVertices[clippedCount].w = vtx1.w + (vtx2.w - vtx1.w)*m;
      clippedColors[clippedCount].x = c1.x + (c2.x - c1.x)*m;
      clippedColors[clippedCount].y = c1.y + (c2.y - c1.y)*m;
      clippedColors[clippedCount].z = c1.z + (c2.z - c1.z)*m;
      clippedCount++;
    }
    else if (vtx1.z < minZ && vtx2.z >= minZ) {
      clippedVertices[clippedCount].x = vtx1.x + (vtx2.x - vtx1.x)*m;
      clippedVertices[clippedCount].y = vtx1.y + (vtx2.y - vtx1.y)*m;
      clippedVertices[clippedCount].z = vtx1.z + (vtx2.z - vtx1.z)*m;
      clippedVertices[clippedCount].w = vtx1.w + (vtx2.w - vtx1.w)*m;
      clippedColors[clippedCount].x = c1.x + (c2.x - c1.x)*m;
      clippedColors[clippedCount].y = c1.y + (c2.y - c1.y)*m;
      clippedColors[clippedCount].z = c1.z + (c2.z - c1.z)*m;
      clippedCount++;
      clippedVertices[clippedCount].set(vtx2);
      clippedColors[clippedCount].set(c2);
      clippedCount++;
    }
  }
 
TOP

Related Classes of com.bulletphysics.demos.applet.Graphics3D

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.