diff --git a/src/cad/Cad.java b/src/cad/Cad.java index 894fd56c..02951e4a 100644 --- a/src/cad/Cad.java +++ b/src/cad/Cad.java @@ -1,13 +1,23 @@ package cad; +import cad.fx.Plane; +import cad.fx.Utils3D; +import cad.math.Vector; import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.util.gl2.GLUT; +import gnu.trove.map.TIntObjectMap; +import gnu.trove.map.hash.TIntObjectHashMap; +import javax.media.opengl.GL; import javax.media.opengl.GL2; import javax.media.opengl.GLAutoDrawable; import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLEventListener; import javax.media.opengl.GLProfile; import javax.media.opengl.Threading; +import javax.media.opengl.glu.GLU; +import java.util.ArrayList; +import java.util.List; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.ThreadPoolExecutor; @@ -19,12 +29,17 @@ public class Cad implements GLEventListener, com.jogamp.newt.event.MouseListener GLProfile.initSingleton(); // The method allows JOGL to prepare some Linux-specific locking optimizations } + public static List initObjects = Utils3D.createCube(1); + + static TIntObjectMap scene = new TIntObjectHashMap<>(); + private static GLWindow window; ExecutorService updater = Executors.newSingleThreadExecutor(); - + public static void main(String[] args) throws NoSuchMethodException, ClassNotFoundException { + // Get the default OpenGL profile, reflecting the best for your running platform GLProfile glp = GLProfile.getDefault(); // Specifies a set of OpenGL capabilities, based on your profile. @@ -50,12 +65,13 @@ public class Cad implements GLEventListener, com.jogamp.newt.event.MouseListener // } // }); + window.addGLEventListener(new Cad()); window.setSize(640, 480); window.setTitle("CAD"); window.setVisible(true); - + Executors.newSingleThreadExecutor().execute(() -> { Object monitor = new Object(); while (true) { @@ -67,13 +83,17 @@ public class Cad implements GLEventListener, com.jogamp.newt.event.MouseListener } } }); - + // animator.start(); } + float red[] = {0.8f, 0.1f, 0.0f, 1.0f}; + float green[] = {0.0f, 0.8f, 0.2f, 1.0f}; + float blue[] = {0.2f, 0.2f, 1.0f, 1.0f}; + float white[] = {1.0f, 1.0f, 1.0f}; + + private float view_rotx = 20.0f, view_roty = 30.0f, view_rotz = 0.0f; - private int gear1; - private float angle = 0.0f; private int prevMouseX, prevMouseY; private boolean mouseRButtonDown = false; @@ -88,46 +108,88 @@ public class Cad implements GLEventListener, com.jogamp.newt.event.MouseListener System.err.println("Chosen GLCapabilities: " + drawable.getChosenGLCapabilities()); - gl.setSwapInterval(1); + gl.setSwapInterval(0); - float pos[] = {5.0f, 5.0f, 10.0f, 0.0f}; - float red[] = {0.8f, 0.1f, 0.0f, 1.0f}; - float green[] = {0.0f, 0.8f, 0.2f, 1.0f}; - float blue[] = {0.2f, 0.2f, 1.0f, 1.0f}; + float pos0[] = { 0.0f, 0.0f, 0.0f, 1.0f }; + gl.glLightfv(GL2.GL_LIGHT0, GL2.GL_POSITION, pos0, 0); - gl.glLightfv(GL2.GL_LIGHT0, GL2.GL_POSITION, pos, 0); gl.glEnable(GL2.GL_CULL_FACE); + gl.glEnable(GL2.GL_DEPTH_TEST); gl.glEnable(GL2.GL_LIGHTING); gl.glEnable(GL2.GL_LIGHT0); - gl.glEnable(GL2.GL_DEPTH_TEST); - - /* make the gears */ - gear1 = gl.glGenLists(1); - gl.glNewList(gear1, GL2.GL_COMPILE); - gl.glMaterialfv(GL2.GL_FRONT, GL2.GL_AMBIENT_AND_DIFFUSE, red, 0); - gear(gl, 1.0f, 4.0f, 1.0f, 20, 0.7f); - gl.glEndList(); + + initNodes(gl); gl.glEnable(GL2.GL_NORMALIZE); - - if (drawable instanceof GLWindow) { GLWindow awtDrawable = (GLWindow) drawable; awtDrawable.addMouseListener(this); } } + private void initNodes(GL2 gl) { + for (Plane plane : initObjects) { + int id = gl.glGenLists(1); + scene.put(id, plane); + gl.glNewList(id, GL2.GL_COMPILE); + + //http://devernay.free.fr/cours/opengl/materials.html +// float[] amb = {0f, 0f, 0f, 0f}; +// gl.glMaterialfv(GL2.GL_FRONT, GL2.GL_AMBIENT, amb, 0); + + float[] diff = {0.6901961f, 0.76862746f, 0.87058824f}; + gl.glMaterialfv(GL2.GL_FRONT, GL2.GL_DIFFUSE, diff, 0); + +// float[] spec = {0f, 0f, 0f}; +// gl.glMaterialfv(GL2.GL_FRONT, GL2.GL_SPECULAR, spec, 0); +// float shine = 0.6f; +// gl.glMaterialf(GL2.GL_FRONT, GL2.GL_SHININESS, shine * 128.0f); +// gl.glMaterialfv(GL2.GL_FRONT, GL2.GL_AMBIENT_AND_DIFFUSE, blue, 0); + + gl.glShadeModel(GL2.GL_SMOOTH); + + gl.glEnable(GL2.GL_LIGHTING); + + gl.glBegin(GL2.GL_TRIANGLES); + gl.glNormal3d(plane.normal.x, plane.normal.y, plane.normal.z); //very important!! + for (Vector[] tr : plane.getTriangles()) { + gl.glVertex3d(tr[0].x, tr[0].y, tr[0].z); + gl.glVertex3d(tr[1].x, tr[1].y, tr[1].z); + gl.glVertex3d(tr[2].x, tr[2].y, tr[2].z); + } + gl.glEnd(); + + gl.glEndList(); + } + for (Plane plane : initObjects) { + int id = gl.glGenLists(1); + scene.put(id, plane); + gl.glNewList(id, GL2.GL_COMPILE); + gl.glShadeModel(GL2.GL_FLAT); + gl.glLineWidth(1.5f); + gl.glColor3f(255.0f, 255.0f, 255.0f); + gl.glDisable(GL2.GL_LIGHTING); + + gl.glNormal3d(plane.normal.x, plane.normal.y, plane.normal.z); + for (int i = 0; i < plane.shell.size(); i++) { + gl.glBegin(GL2.GL_LINES); + Vector a = Plane.get(plane.shell, i); + Vector b = Plane.get(plane.shell, i + 1); + gl.glVertex3d(a.x, a.y, a.z); + gl.glVertex3d(b.x, b.y, b.z); + gl.glEnd(); + } + gl.glEndList(); + } + } + public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { GL2 gl = drawable.getGL().getGL2(); float h = (float) height / (float) width; gl.glMatrixMode(GL2.GL_PROJECTION); - - System.err.println("GL_VENDOR: " + gl.glGetString(GL2.GL_VENDOR)); - System.err.println("GL_RENDERER: " + gl.glGetString(GL2.GL_RENDERER)); - System.err.println("GL_VERSION: " + gl.glGetString(GL2.GL_VERSION)); gl.glLoadIdentity(); gl.glFrustum(-1.0f, 1.0f, -h, h, 5.0f, 60.0f); gl.glMatrixMode(GL2.GL_MODELVIEW); @@ -140,149 +202,60 @@ public class Cad implements GLEventListener, com.jogamp.newt.event.MouseListener } public void display(GLAutoDrawable drawable) { - // Turn the gears' teeth -// angle += 2.0f; - - // Get the GL corresponding to the drawable we are animating GL2 gl = drawable.getGL().getGL2(); - // Special handling for the case where the GLJPanel is translucent - // and wants to be composited with other Java 2D content + gl.glClearColor(0.5019608f, 0.5019608f, 0.5019608f, 0f); gl.glClear(GL2.GL_COLOR_BUFFER_BIT | GL2.GL_DEPTH_BUFFER_BIT); - // Rotate the entire assembly of gears based on how the user - // dragged the mouse around gl.glPushMatrix(); + gl.glScalef(scale, scale, scale); + + gl.glPushMatrix(); + gl.glRotatef(view_rotx, 1.0f, 0.0f, 0.0f); gl.glRotatef(view_roty, 0.0f, 1.0f, 0.0f); gl.glRotatef(view_rotz, 0.0f, 0.0f, 1.0f); - // Place the first gear and call its display list - gl.glPushMatrix(); - gl.glTranslatef(1.0f, 1.0f, 0.0f); - gl.glRotatef(angle, 0.0f, 0.0f, 1.0f); - gl.glCallList(gear1); + for (int id : scene.keys()) { + gl.glCallList(id); + } + +// +// gl.glPushMatrix(); +// gl.glScalef(3,3,3); +// gl.glBegin(GL2.GL_QUADS); +// gl.glNormal3f( 0.0F, 0.0F, 1.0F); +// gl.glVertex3f( 0.5F, 0.5F, 0.5F); gl.glVertex3f(-0.5F, 0.5F, 0.5F); +// gl.glVertex3f(-0.5F,-0.5F, 0.5F); gl.glVertex3f( 0.5F,-0.5F, 0.5F); +// +// gl.glNormal3f( 0.0F, 0.0F,-1.0F); +// gl.glVertex3f(-0.5F,-0.5F,-0.5F); gl.glVertex3f(-0.5F, 0.5F,-0.5F); +// gl.glVertex3f( 0.5F, 0.5F,-0.5F); gl.glVertex3f( 0.5F,-0.5F,-0.5F); +// +// gl.glNormal3f( 0.0F, 1.0F, 0.0F); +// gl.glVertex3f( 0.5F, 0.5F, 0.5F); gl.glVertex3f( 0.5F, 0.5F,-0.5F); +// gl.glVertex3f(-0.5F, 0.5F,-0.5F); gl.glVertex3f(-0.5F, 0.5F, 0.5F); +// +// gl.glNormal3f( 0.0F,-1.0F, 0.0F); +// gl.glVertex3f(-0.5F,-0.5F,-0.5F); gl.glVertex3f( 0.5F,-0.5F,-0.5F); +// gl.glVertex3f( 0.5F,-0.5F, 0.5F); gl.glVertex3f(-0.5F,-0.5F, 0.5F); +// +// gl.glNormal3f( 1.0F, 0.0F, 0.0F); +// gl.glVertex3f( 0.5F, 0.5F, 0.5F); gl.glVertex3f( 0.5F,-0.5F, 0.5F); +// gl.glVertex3f( 0.5F,-0.5F,-0.5F); gl.glVertex3f( 0.5F, 0.5F,-0.5F); +// +// gl.glNormal3f(-1.0F, 0.0F, 0.0F); +// gl.glVertex3f(-0.5F,-0.5F,-0.5F); gl.glVertex3f(-0.5F,-0.5F, 0.5F); +// gl.glVertex3f(-0.5F, 0.5F, 0.5F); gl.glVertex3f(-0.5F, 0.5F,-0.5F); +// gl.glEnd(); +// gl.glPopMatrix(); + + gl.glPopMatrix(); - - - // Remember that every push needs a pop; this one is paired with - // rotating the entire gear assembly gl.glPopMatrix(); } - public void displayChanged(GLAutoDrawable drawable, boolean modeChanged, boolean deviceChanged) { - } - - public static void gear(GL2 gl, - float inner_radius, - float outer_radius, - float width, - int teeth, - float tooth_depth) { - int i; - float r0, r1, r2; - float angle, da; - float u, v, len; - - r0 = inner_radius; - r1 = outer_radius - tooth_depth / 2.0f; - r2 = outer_radius + tooth_depth / 2.0f; - - da = 2.0f * (float) Math.PI / teeth / 4.0f; - - gl.glShadeModel(GL2.GL_FLAT); - - gl.glNormal3f(0.0f, 0.0f, 1.0f); - - /* draw front face */ - gl.glBegin(GL2.GL_QUAD_STRIP); - for (i = 0; i <= teeth; i++) { - angle = i * 2.0f * (float) Math.PI / teeth; - gl.glVertex3f(r0 * (float) Math.cos(angle), r0 * (float) Math.sin(angle), width * 0.5f); - gl.glVertex3f(r1 * (float) Math.cos(angle), r1 * (float) Math.sin(angle), width * 0.5f); - if (i < teeth) { - gl.glVertex3f(r0 * (float) Math.cos(angle), r0 * (float) Math.sin(angle), width * 0.5f); - gl.glVertex3f(r1 * (float) Math.cos(angle + 3.0f * da), r1 * (float) Math.sin(angle + 3.0f * da), width * 0.5f); - } - } - gl.glEnd(); - - /* draw front sides of teeth */ - gl.glBegin(GL2.GL_QUADS); - for (i = 0; i < teeth; i++) { - angle = i * 2.0f * (float) Math.PI / teeth; - gl.glVertex3f(r1 * (float) Math.cos(angle), r1 * (float) Math.sin(angle), width * 0.5f); - gl.glVertex3f(r2 * (float) Math.cos(angle + da), r2 * (float) Math.sin(angle + da), width * 0.5f); - gl.glVertex3f(r2 * (float) Math.cos(angle + 2.0f * da), r2 * (float) Math.sin(angle + 2.0f * da), width * 0.5f); - gl.glVertex3f(r1 * (float) Math.cos(angle + 3.0f * da), r1 * (float) Math.sin(angle + 3.0f * da), width * 0.5f); - } - gl.glEnd(); - - /* draw back face */ - gl.glBegin(GL2.GL_QUAD_STRIP); - for (i = 0; i <= teeth; i++) { - angle = i * 2.0f * (float) Math.PI / teeth; - gl.glVertex3f(r1 * (float) Math.cos(angle), r1 * (float) Math.sin(angle), -width * 0.5f); - gl.glVertex3f(r0 * (float) Math.cos(angle), r0 * (float) Math.sin(angle), -width * 0.5f); - gl.glVertex3f(r1 * (float) Math.cos(angle + 3 * da), r1 * (float) Math.sin(angle + 3 * da), -width * 0.5f); - gl.glVertex3f(r0 * (float) Math.cos(angle), r0 * (float) Math.sin(angle), -width * 0.5f); - } - gl.glEnd(); - - /* draw back sides of teeth */ - gl.glBegin(GL2.GL_QUADS); - for (i = 0; i < teeth; i++) { - angle = i * 2.0f * (float) Math.PI / teeth; - gl.glVertex3f(r1 * (float) Math.cos(angle + 3 * da), r1 * (float) Math.sin(angle + 3 * da), -width * 0.5f); - gl.glVertex3f(r2 * (float) Math.cos(angle + 2 * da), r2 * (float) Math.sin(angle + 2 * da), -width * 0.5f); - gl.glVertex3f(r2 * (float) Math.cos(angle + da), r2 * (float) Math.sin(angle + da), -width * 0.5f); - gl.glVertex3f(r1 * (float) Math.cos(angle), r1 * (float) Math.sin(angle), -width * 0.5f); - } - gl.glEnd(); - - /* draw outward faces of teeth */ - gl.glBegin(GL2.GL_QUAD_STRIP); - for (i = 0; i < teeth; i++) { - angle = i * 2.0f * (float) Math.PI / teeth; - gl.glVertex3f(r1 * (float) Math.cos(angle), r1 * (float) Math.sin(angle), width * 0.5f); - gl.glVertex3f(r1 * (float) Math.cos(angle), r1 * (float) Math.sin(angle), -width * 0.5f); - u = r2 * (float) Math.cos(angle + da) - r1 * (float) Math.cos(angle); - v = r2 * (float) Math.sin(angle + da) - r1 * (float) Math.sin(angle); - len = (float) Math.sqrt(u * u + v * v); - u /= len; - v /= len; - gl.glNormal3f(v, -u, 0.0f); - gl.glVertex3f(r2 * (float) Math.cos(angle + da), r2 * (float) Math.sin(angle + da), width * 0.5f); - gl.glVertex3f(r2 * (float) Math.cos(angle + da), r2 * (float) Math.sin(angle + da), -width * 0.5f); - gl.glNormal3f((float) Math.cos(angle), (float) Math.sin(angle), 0.0f); - gl.glVertex3f(r2 * (float) Math.cos(angle + 2 * da), r2 * (float) Math.sin(angle + 2 * da), width * 0.5f); - gl.glVertex3f(r2 * (float) Math.cos(angle + 2 * da), r2 * (float) Math.sin(angle + 2 * da), -width * 0.5f); - u = r1 * (float) Math.cos(angle + 3 * da) - r2 * (float) Math.cos(angle + 2 * da); - v = r1 * (float) Math.sin(angle + 3 * da) - r2 * (float) Math.sin(angle + 2 * da); - gl.glNormal3f(v, -u, 0.0f); - gl.glVertex3f(r1 * (float) Math.cos(angle + 3 * da), r1 * (float) Math.sin(angle + 3 * da), width * 0.5f); - gl.glVertex3f(r1 * (float) Math.cos(angle + 3 * da), r1 * (float) Math.sin(angle + 3 * da), -width * 0.5f); - gl.glNormal3f((float) Math.cos(angle), (float) Math.sin(angle), 0.0f); - } - gl.glVertex3f(r1 * (float) Math.cos(0), r1 * (float) Math.sin(0), width * 0.5f); - gl.glVertex3f(r1 * (float) Math.cos(0), r1 * (float) Math.sin(0), -width * 0.5f); - gl.glEnd(); - - gl.glShadeModel(GL2.GL_SMOOTH); - - /* draw inside radius cylinder */ - gl.glBegin(GL2.GL_QUAD_STRIP); - for (i = 0; i <= teeth; i++) { - angle = i * 2.0f * (float) Math.PI / teeth; - gl.glNormal3f(-(float) Math.cos(angle), -(float) Math.sin(angle), 0.0f); - gl.glVertex3f(r0 * (float) Math.cos(angle), r0 * (float) Math.sin(angle), -width * 0.5f); - gl.glVertex3f(r0 * (float) Math.cos(angle), r0 * (float) Math.sin(angle), width * 0.5f); - } - gl.glEnd(); - } - - @Override public void mouseClicked(com.jogamp.newt.event.MouseEvent e) { } @@ -332,14 +305,14 @@ public class Cad implements GLEventListener, com.jogamp.newt.event.MouseListener view_rotx += thetaX; view_roty += thetaY; - + update(window::display); } - + volatile boolean updating = false; - + private void update(Runnable op) { if (updating) { return; @@ -357,11 +330,11 @@ public class Cad implements GLEventListener, com.jogamp.newt.event.MouseListener } } }); - + // updater.execute(() -> { // try { // updating = true; -// +// // op.run(); // } finally { // updating = false; @@ -369,7 +342,13 @@ public class Cad implements GLEventListener, com.jogamp.newt.event.MouseListener // }); } + final double SCALE_DELTA = 1.1; + float scale = 1; + @Override public void mouseWheelMoved(com.jogamp.newt.event.MouseEvent e) { + double scaleFactor = e.getRotation()[1] > 0 ? SCALE_DELTA : 1 / SCALE_DELTA; + scale *= scaleFactor; + update(window::display); } }