Skip to content

Instantly share code, notes, and snippets.

@wasabili
Created November 9, 2010 17:01
Show Gist options
  • Save wasabili/669389 to your computer and use it in GitHub Desktop.
Save wasabili/669389 to your computer and use it in GitHub Desktop.
DIY 3D Library
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import java.io.*;
import java.util.*;
import static java.lang.Math.*;
public class Test extends JPanel {
private ArrayList<Vertex> vertices = null;
private ArrayList<Face> faces = null;
private Point center = null;
private Point mousePos = null;
private double scale;
private double phi; // x axis
private double theta; // y axis
private int WIDTH;
private int HEIGHT;
public Test(int width, int height) {
super(true);
this.WIDTH = width;
this.HEIGHT = height;
this.center = new Point(WIDTH/2, HEIGHT/2);
this.scale = WIDTH * 0.8 / 2;
setSize(width, height);
setPreferredSize(new Dimension(WIDTH,HEIGHT));
this.vertices = new ArrayList<Vertex>();
this.faces = new ArrayList<Face>();
this.mousePos = new Point(0,0);
// Angles of rotation
this.phi = 0.0;
this.theta = 0.0;
MouseInputListener adapter = new MouseInputAdapter() {
public void mouseDragged(MouseEvent e){
theta += (e.getX() - mousePos.x) * 0.01;
phi += (e.getY() - mousePos.y) * 0.01;
phi = min(phi, PI/2);
phi = max(phi, -PI/2);
mousePos.setLocation(e.getX(), e.getY());
refreshScreenPosition();
repaint();
}
public void mousePressed(MouseEvent e){
mousePos.setLocation(e.getX(), e.getY());
}
};
addMouseMotionListener(adapter);
addMouseListener(adapter);
setModelData();
}
public void paintComponent(Graphics g) {
drawModel(g);
}
private void refreshScreenPosition() {
for(Vertex v:vertices){
v.rx = v.x * cos(theta) + v.z * sin(theta);
v.ry = v.x * sin(phi) * sin(theta) + v.y * cos(phi) - v.z * sin(phi) * cos(theta);
v.rz = -v.x * cos(phi) * sin(theta) + v.y * sin(phi) + v.z * cos(phi) * cos(theta);
}
for(Face face:faces){
// refresh a depth
face.z = 0.0;
for(int i=0;i<3;i++) face.z += face.v[i].rz;
face.z /= 3.0;
double ax = face.v[1].rx - face.v[0].rx;
double ay = face.v[1].ry - face.v[0].ry;
double az = face.v[1].rz - face.v[0].rz;
double bx = face.v[2].rx - face.v[0].rx;
double by = face.v[2].ry - face.v[0].ry;
double bz = face.v[2].rz - face.v[0].rz;
face.nx = ay * bz - az * by;
face.ny = az * bx - ax * bz;
face.nz = ax * by - ay * bx;
double l = sqrt(face.nx * face.nx + face.ny * face.ny + face.nz * face.nz);
face.nx /= l;
face.ny /= l;
face.nz /= l;
}
Collections.sort(faces, new Comparator<Face>() {
public int compare(Face f1, Face f2) {
return (f1.z > f2.z)? 1:-1;
}
});
}
public void setModelData() {
double modelSize = 0.0;
try{
Scanner scn = new Scanner(new FileInputStream("file.obj"));
while(scn.hasNext("[vf]")){
String cmd = scn.next("[vf]");
if(cmd.equals("v")){
double x = scn.nextDouble();
double y = scn.nextDouble();
double z = scn.nextDouble();
modelSize = max(modelSize, x, y, z);
vertices.add(new Vertex(x, y, z));
}else if(cmd.equals("f")){
int v0 = scn.nextInt();
int v1 = scn.nextInt();
int v2 = scn.nextInt();
faces.add(new Face(vertices.get(v0-1),
vertices.get(v1-1),
vertices.get(v2-1)));
}
}
}catch(Exception e){
e.printStackTrace();
System.exit(1);
}
System.out.println("V:"+vertices.size()+"F:"+faces.size());
for(Vertex v:vertices){
v.x /= modelSize;
v.y /= modelSize;
v.z /= modelSize;
}
}
private void drawModel(Graphics g) {
g.setColor(Color.WHITE);
g.fillRect(0,0,WIDTH,HEIGHT);
for(Face face:faces){
int[] px = new int[3];
int[] py = new int[3];
for(int i=0;i<3;i++){
px[i] = (int)(center.x + face.v[i].rx * scale);
py[i] = (int)(center.y - face.v[i].ry * scale);
}
g.setColor(Color.getHSBColor((float)0.4, (float)0.5, (float)face.nz));
g.fillPolygon(px, py, 3);
g.setColor(Color.BLACK);
g.drawPolygon(px, py, 3);
}
}
private double max(double... args){
double result = args[0];
for(int i=1;i<args.length;i++){
result = (result < args[i])? args[i]:result;
}
return result;
}
}
class Vertex {
public double x,y,z;
public double rx,ry,rz;
public Vertex(double x,double y,double z){
this.x = x;
this.y = y;
this.z = z;
}
}
class Face {
public Vertex[] v = new Vertex[3];
public double nx,ny,nz;
public double z; // depth
public Face(Vertex v0,Vertex v1,Vertex v2){
v[0] = v0;
v[1] = v1;
v[2] = v2;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment