import f3d.JOGLPanel; import javax.media.opengl.*; import java.lang.Math; import java.lang.System; import f3.ui.*; import f3.ui.canvas.*; public class Gears extends CompositeWidget { attribute gear1: Integer; attribute gear2: Integer; attribute gear3: Integer; attribute angle: Number; attribute frameRate: Number; attribute ticks: Number; attribute view_rotx: Number; attribute view_roty: Number; attribute view_rotz: Number; attribute prevMouseX: Number; attribute prevMouseY: Number; attribute damaged: Boolean; } attribute Gears.view_rotx = 20.0; attribute Gears.view_roty = 30.0; attribute Gears.view_rotz = 0.0; attribute Gears.frameRate = 50; attribute Gears.ticks = bind unitinterval in dur 10000 fps frameRate continue if true; trigger on Gears.frameRate = value { println("frameRate={value}"); } trigger on Gears.ticks = value { angle += 3; damaged = true; } function Gears.composeWidget() = JOGLPanel { damaged: bind this.damaged onMousePressed: operation(e:MouseEvent) { prevMouseX = e.x; prevMouseY = e.y; } onMouseDragged: operation(e:MouseEvent) { var x = e.x; var y = e.y; var size = this.getComponent().getSize(); var thetaY = 360.0 * ( (x-prevMouseX)/size.width); var thetaX = 360.0 * ( (prevMouseY-y)/size.height); prevMouseX = x; prevMouseY = y; view_rotx += thetaX; view_roty += thetaY; } reshape: operation(drawable:GLAutoDrawable, x: Integer, y: Integer, width: Integer, height: Integer) { var gl = drawable.getGL(); var h = height / width; gl.glMatrixMode(GL.GL_PROJECTION); gl.glLoadIdentity(); gl.glFrustum(-1.0, 1.0, -h, h, 5.0, 60.0); gl.glMatrixMode(GL.GL_MODELVIEW); gl.glLoadIdentity(); gl.glTranslatef(0.0, 0.0, -40.0); } display: operation(drawable:GLAutoDrawable) { var gl = drawable.getGL(); if ((drawable instanceof GLJPanel) and not ((GLJPanel) drawable).isOpaque() and ((GLJPanel) drawable).shouldPreserveColorBufferIfTranslucent()) { gl.glClear(GL.GL_DEPTH_BUFFER_BIT); } else { gl.glClear(GL.GL_COLOR_BUFFER_BIT + GL.GL_DEPTH_BUFFER_BIT); } gl.glPushMatrix(); gl.glRotatef(view_rotx, 1.0, 0.0, 0.0); gl.glRotatef(view_roty, 0.0, 1.0, 0.0); gl.glRotatef(view_rotz, 0.0, 0.0, 1.0); gl.glPushMatrix(); gl.glTranslatef(-3.0, -2.0, 0.0); gl.glRotatef(angle, 0.0, 0.0, 1.0); gl.glCallList(gear1); gl.glPopMatrix(); gl.glPushMatrix(); gl.glTranslatef(3.1, -2.0, 0.0); gl.glRotatef(-2.0 * angle - 9.0, 0.0, 0.0, 1.0); gl.glCallList(gear2); gl.glPopMatrix(); gl.glPushMatrix(); gl.glTranslatef(-3.1, 4.2, 0.0); gl.glRotatef(-2.0 * angle - 25.0, 0.0, 0.0, 1.0); gl.glCallList(gear3); gl.glPopMatrix(); gl.glPopMatrix(); } init: operation(drawable:GLAutoDrawable) { var gl = drawable.getGL(); gl.setSwapInterval(1); var pos = [5.0, 5.0, 10.0, 0.0]; var red = [0.8, 0.1, 0.0, 1.0]; var green = [0.0, 0.8, 0.2, 1.0]; var blue = [0.2, 0.2, 1.0, 1.0]; gl.glLightfv(GL.GL_LIGHT0, GL.GL_POSITION, pos, 0); gl.glEnable(GL.GL_CULL_FACE); gl.glEnable(GL.GL_LIGHTING); gl.glEnable(GL.GL_LIGHT0); gl.glEnable(GL.GL_DEPTH_TEST); /* make the gears */ gear1 = gl.glGenLists(1); gl.glNewList(gear1, GL.GL_COMPILE); gl.glMaterialfv(GL.GL_FRONT, GL.GL_AMBIENT_AND_DIFFUSE, red, 0); gear(gl, 1.0, 4.0, 1.0, 20, 0.7); gl.glEndList(); gear2 = gl.glGenLists(1); gl.glNewList(gear2, GL.GL_COMPILE); gl.glMaterialfv(GL.GL_FRONT, GL.GL_AMBIENT_AND_DIFFUSE, green, 0); gear(gl, 0.5, 2.0, 2.0, 10, 0.7); gl.glEndList(); gear3 = gl.glGenLists(1); gl.glNewList(gear3, GL.GL_COMPILE); gl.glMaterialfv(GL.GL_FRONT, GL.GL_AMBIENT_AND_DIFFUSE, blue, 0); gear(gl, 1.3, 2.0, 0.5, 10, 0.7); gl.glEndList(); gl.glEnable(GL.GL_NORMALIZE); } } where gear = operation(gl:GL, inner_radius: Number, outer_radius: Number, width: Number, teeth: Number, tooth_depth: Number) { var i; var r0; var r1; var r2; var angle; var da; var u; var v; var len; r0 = inner_radius; r1 = outer_radius - tooth_depth / 2.0; r2 = outer_radius + tooth_depth / 2.0; da = 2.0 * Math.PI / teeth / 4.0; gl.glShadeModel(GL.GL_FLAT); gl.glNormal3f(0.0, 0.0, 1.0); /* draw front face */ gl.glBegin(GL.GL_QUAD_STRIP); for (i in [0..teeth]) { angle = i * 2.0 * Math.PI / teeth; gl.glVertex3f(r0 * Math.cos(angle), r0 * Math.sin(angle), width * 0.5); gl.glVertex3f(r1 * Math.cos(angle), r1 * Math.sin(angle), width * 0.5); if(i < teeth) { gl.glVertex3f(r0 * Math.cos(angle), r0 * Math.sin(angle), width * 0.5); gl.glVertex3f(r1 * Math.cos(angle + 3.0 * da), r1 * Math.sin(angle + 3.0 * da), width * 0.5); } } gl.glEnd(); /* draw front sides of teeth */ gl.glBegin(GL.GL_QUADS); for (i in [0..teeth-1]) { angle = i * 2.0 * Math.PI / teeth; gl.glVertex3f(r1 * Math.cos(angle), r1 * Math.sin(angle), width * 0.5); gl.glVertex3f(r2 * Math.cos(angle + da), r2 * Math.sin(angle + da), width * 0.5); gl.glVertex3f(r2 * Math.cos(angle + 2.0 * da), r2 * Math.sin(angle + 2.0 * da), width * 0.5); gl.glVertex3f(r1 * Math.cos(angle + 3.0 * da), r1 * Math.sin(angle + 3.0 * da), width * 0.5); } gl.glEnd(); /* draw back face */ gl.glBegin(GL.GL_QUAD_STRIP); for (i in [0..teeth]) { angle = i * 2.0 * Math.PI / teeth; gl.glVertex3f(r1 * Math.cos(angle), r1 * Math.sin(angle), -width * 0.5); gl.glVertex3f(r0 * Math.cos(angle), r0 * Math.sin(angle), -width * 0.5); gl.glVertex3f(r1 * Math.cos(angle + 3 * da), r1 * Math.sin(angle + 3 * da), -width * 0.5); gl.glVertex3f(r0 * Math.cos(angle), r0 * Math.sin(angle), -width * 0.5); } gl.glEnd(); /* draw back sides of teeth */ gl.glBegin(GL.GL_QUADS); for (i in [0..teeth-1]) { angle = i * 2.0 * Math.PI / teeth; gl.glVertex3f(r1 * Math.cos(angle + 3 * da), r1 * Math.sin(angle + 3 * da), -width * 0.5); gl.glVertex3f(r2 * Math.cos(angle + 2 * da), r2 * Math.sin(angle + 2 * da), -width * 0.5); gl.glVertex3f(r2 * Math.cos(angle + da), r2 * Math.sin(angle + da), -width * 0.5); gl.glVertex3f(r1 * Math.cos(angle), r1 * Math.sin(angle), -width * 0.5); } gl.glEnd(); /* draw outward faces of teeth */ gl.glBegin(GL.GL_QUAD_STRIP); for (i in [0..teeth-1]) { angle = i * 2.0 * Math.PI / teeth; gl.glVertex3f(r1 * Math.cos(angle), r1 * Math.sin(angle), width * 0.5); gl.glVertex3f(r1 * Math.cos(angle), r1 * Math.sin(angle), -width * 0.5); u = r2 * Math.cos(angle + da) - r1 * Math.cos(angle); v = r2 * Math.sin(angle + da) - r1 * Math.sin(angle); len = Math.sqrt(u * u + v * v); u /= len; v /= len; gl.glNormal3f(v, -u, 0.0); gl.glVertex3f(r2 * Math.cos(angle + da), r2 * Math.sin(angle + da), width * 0.5); gl.glVertex3f(r2 * Math.cos(angle + da), r2 * Math.sin(angle + da), -width * 0.5); gl.glNormal3f(Math.cos(angle), Math.sin(angle), 0.0); gl.glVertex3f(r2 * Math.cos(angle + 2 * da), r2 * Math.sin(angle + 2 * da), width * 0.5); gl.glVertex3f(r2 * Math.cos(angle + 2 * da), r2 * Math.sin(angle + 2 * da), -width * 0.5); u = r1 * Math.cos(angle + 3 * da) - r2 * Math.cos(angle + 2 * da); v = r1 * Math.sin(angle + 3 * da) - r2 * Math.sin(angle + 2 * da); gl.glNormal3f(v, -u, 0.0); gl.glVertex3f(r1 * Math.cos(angle + 3 * da), r1 * Math.sin(angle + 3 * da), width * 0.5); gl.glVertex3f(r1 * Math.cos(angle + 3 * da), r1 * Math.sin(angle + 3 * da), -width * 0.5); gl.glNormal3f(Math.cos(angle), Math.sin(angle), 0.0); } gl.glVertex3f(r1 * Math.cos(0), r1 * Math.sin(0), width * 0.5); gl.glVertex3f(r1 * Math.cos(0), r1 * Math.sin(0), -width * 0.5); gl.glEnd(); gl.glShadeModel(GL.GL_SMOOTH); /* draw inside radius cylinder */ gl.glBegin(GL.GL_QUAD_STRIP); for (i in [0..teeth]) { angle = i * 2.0 * Math.PI / teeth; gl.glNormal3f(-Math.cos(angle), -Math.sin(angle), 0.0); gl.glVertex3f(r0 * Math.cos(angle), r0 * Math.sin(angle), -width * 0.5); gl.glVertex3f(r0 * Math.cos(angle), r0 * Math.sin(angle), width * 0.5); } gl.glEnd(); } ; Frame { onClose: operation() {System.exit(0);} title: "F3 Gears" height: 430 width: 400 visible: true content: Canvas { content: [Rect { transform: translate(90, 90) height: 220 width: 220 fill: new Color(0, 0, .5, .5) arcHeight: 20 arcWidth: 20 }, View { antialias: true transform: translate(100, 100) content: BorderPanel { top: Button {text : "Click Me!" cursor: DEFAULT} var gears = Gears { cursor: HAND preferredSize: {height: 200, width: 200} } center: gears } }, View { transform: translate(120, 150) content: TextField { columns: 11 value: "this is a text field" } }] } }