#//
#// Draws a gear.
#//
#// Portions of self code have been borrowed from Brian Paul's Mesa
#// distribution.
#//

#include <qgl.h>
#include <qapplication.h>
#include <math.h>
=begin
/*
 * Draw a gear wheel.  You'll probably want to call self function when
 * building a display list since we do a lot of trig here.
 *
 * Input:  inner_radius - radius of hole at center
 *	   outer_radius - radius at center of teeth
 *	   width - width of gear
 *	   teeth - number of teeth
 *	   tooth_depth - depth of tooth
 */
=end
require "qt2"
require "opengl"
require "qt2gl"
include Qt2
include GL
include Qt2gl
include Math

def  gear( inner_radius, outer_radius, width,
		  teeth, tooth_depth )



    r0 = inner_radius * 1.0
    r1 = outer_radius - tooth_depth/2.0
    r2 = outer_radius + tooth_depth/2.0

    pi = 3.14159264
    da = 2.0*pi / teeth / 4.0

    ShadeModel( FLAT )

    Normal( 0.0,0.0,1.0 )

    #/* draw front face */
    Begin( QUAD_STRIP )
    for i in 0..teeth #(i=0 i<=teeth i++)
	$Angle = i * 2.0*pi / teeth
	Vertex( r0*cos($Angle), r0*sin($Angle), width*0.5 )
	Vertex( r1*cos($Angle), r1*sin($Angle), width*0.5 )
	Vertex( r0*cos($Angle), r0*sin($Angle), width*0.5 )
	Vertex( r1*cos($Angle+3*da), r1*sin($Angle+3*da), width*0.5 )
    end
    End()

    #/* draw front sides of teeth */
    Begin( QUADS )
    da = 2.0*pi / teeth / 4.0
    for i in 0..teeth #(i=0 i<teeth i++)
	$Angle = i * 2.0*pi / teeth

	Vertex( r1*cos($Angle),      r1*sin($Angle),	  width*0.5 )
	Vertex( r2*cos($Angle+da),   r2*sin($Angle+da),	  width*0.5 )
	Vertex( r2*cos($Angle+2*da), r2*sin($Angle+2*da), width*0.5 )
	Vertex( r1*cos($Angle+3*da), r1*sin($Angle+3*da), width*0.5 )
    end
    End()


    Normal( 0.0, 0.0, -1.0 )

    #/* draw back face */
    Begin( QUAD_STRIP )
    for i in 0..teeth #(i=0 i<=teeth i++) {
	$Angle = i * 2.0*pi / teeth
	Vertex( r1*cos($Angle), r1*sin($Angle), -width*0.5 )
	Vertex( r0*cos($Angle), r0*sin($Angle), -width*0.5 )
	Vertex( r1*cos($Angle+3*da), r1*sin($Angle+3*da), -width*0.5 )
	Vertex( r0*cos($Angle), r0*sin($Angle), -width*0.5 )
    end
    End()

    #/* draw back sides of teeth */
    Begin( QUADS )
    da = 2.0*pi / teeth / 4.0
    for i in 0..teeth #(i=0 i<teeth i++) {
	$Angle = i * 2.0*pi / teeth

	Vertex( r1*cos($Angle+3*da), r1*sin($Angle+3*da), -width*0.5 )
	Vertex( r2*cos($Angle+2*da), r2*sin($Angle+2*da), -width*0.5 )
	Vertex( r2*cos($Angle+da),   r2*sin($Angle+da),	  -width*0.5 )
	Vertex( r1*cos($Angle),      r1*sin($Angle),	  -width*0.5 )
    end
    End()


    #/* draw outward faces of teeth */
    Begin( QUAD_STRIP )
    for i in 0..teeth #(i=0 i<teeth i++) {
	$Angle = i * 2.0*pi / teeth

	Vertex( r1*cos($Angle),      r1*sin($Angle),	   width*0.5 )
	Vertex( r1*cos($Angle),      r1*sin($Angle),	  -width*0.5 )
	u = r2*cos($Angle+da) - r1*cos($Angle)
	v = r2*sin($Angle+da) - r1*sin($Angle)
	len = sqrt( u*u + v*v )
	u /= len
	v /= len
	Normal( v, -u, 0.0 )
	Vertex( r2*cos($Angle+da),   r2*sin($Angle+da),	   width*0.5 )
	Vertex( r2*cos($Angle+da),   r2*sin($Angle+da),	  -width*0.5 )
	Normal( cos($Angle), sin($Angle), 0.0 )
	Vertex( r2*cos($Angle+2*da), r2*sin($Angle+2*da),  width*0.5 )
	Vertex( r2*cos($Angle+2*da), r2*sin($Angle+2*da), -width*0.5 )
	u = r1*cos($Angle+3*da) - r2*cos($Angle+2*da)
	v = r1*sin($Angle+3*da) - r2*sin($Angle+2*da)
	Normal( v, -u, 0.0 )
	Vertex( r1*cos($Angle+3*da), r1*sin($Angle+3*da),  width*0.5 )
	Vertex( r1*cos($Angle+3*da), r1*sin($Angle+3*da), -width*0.5 )
	Normal( cos($Angle), sin($Angle), 0.0 )
    end

    Vertex( r1*cos(0.0), r1*sin(0.0), width*0.5 )
    Vertex( r1*cos(0.0), r1*sin(0.0), -width*0.5 )

    End()


    ShadeModel( SMOOTH )

    #/* draw inside radius cylinder */
    Begin( QUAD_STRIP )
    for i in 0..teeth #(i=0 i<=teeth i++) {
	$Angle = i * 2.0*pi / teeth
	Normal( -cos($Angle), -sin($Angle), 0.0 )
	Vertex( r0*cos($Angle), r0*sin($Angle), -width*0.5 )
	Vertex( r0*cos($Angle), r0*sin($Angle), width*0.5 )
    end
    End()

end


View_rotx=20.0
$View_roty=30.0
View_rotz=0.0
$Angle = 0.0


def draw()
    $Angle += 2.0
    $View_roty += 1.0

    Clear( COLOR_BUFFER_BIT | DEPTH_BUFFER_BIT )

    PushMatrix()
    Rotate(  View_rotx, 1.0, 0.0, 0.0 )
    Rotate( $View_roty, 0.0, 1.0, 0.0 )
    Rotate( View_rotz, 0.0, 0.0, 1.0 )

    PushMatrix()
    Translate( -3.0, -2.0, 0.0 )
    Rotate( $Angle, 0.0, 0.0, 1.0 )
    CallList(@gear1)
    PopMatrix()

    PushMatrix()
    Translate( 3.1, -2.0, 0.0 )
    Rotate( -2.0*$Angle-9.0, 0.0, 0.0, 1.0 )
    CallList(@gear2)
    PopMatrix()

    PushMatrix()
    Translate( -3.1, 2.2, -1.8 )
    Rotate( 90.0, 1.0, 0.0, 0.0 )
    Rotate( 2.0*$Angle-2.0, 0.0, 0.0, 1.0 )
    CallList(@gear3)
    PopMatrix()

    PopMatrix()
end



class GearWidget < QGLWidget



def initializeGL()

    pos = [5.0, 5.0, 10.0, 1.0 ]
    red = [0.8, 0.1, 0.0, 1.0 ]
    green = [0.0, 0.8, 0.2, 1.0 ]
    blue = [0.2, 0.2, 1.0, 1.0 ]

    Light( LIGHT0, POSITION, pos )
    Enable( CULL_FACE )
    Enable( LIGHTING )
    Enable( LIGHT0 )
    Enable( DEPTH_TEST )

    #/* make the gears */
    @gear1 = GenLists(1)
    NewList(@gear1, COMPILE)
    Material( FRONT, AMBIENT_AND_DIFFUSE, red )
    gear( 1.0, 4.0, 1.0, 20, 0.7 )
    EndList()

    @gear2 = GenLists(1)
    NewList(@gear2, COMPILE)
    Material( FRONT, AMBIENT_AND_DIFFUSE, green )
    gear( 0.5, 2.0, 2.0, 10, 0.7 )
    EndList()

    @gear3 = GenLists(1)
    NewList(@gear3, COMPILE)
    Material( FRONT, AMBIENT_AND_DIFFUSE, blue )
    gear( 1.3, 2.0, 0.5, 10, 0.7 )
    EndList()

    Enable( NORMALIZE )
    resizeEvent nil
    startTimer(10)
    catchEvent
end

def resizeEvent e
    resizeGL(self.width,self.height)
end

def resizeGL( width, height )

    w = 1.0 * width /  height
    h = 1.0

    Viewport( 0, 0, width, height )
    MatrixMode(PROJECTION)
    LoadIdentity()
    Frustum( -w, w, -h, h, 5.0, 60.0 )
    MatrixMode(MODELVIEW)
    LoadIdentity()
    Translate( 0.0, 0.0, -40.0 )
end

def paintEvent e
    paintGL
end

def paintGL()

    draw()
end

def timerEvent( e )
    paintGL
    updateGL()
end
end


    QApplication::setColorSpec( QApplication::CustomColor )
    a = QApplication.new([$0]+ARGV)

    if ( !QGLFormat::hasOpenGL() )
	warning( "self system has no OpenGL support. Exiting." )
	exit -1
    end

    w = GearWidget.new(QGLFormat.new)
    a.setMainWidget( w )
    w.show()
    w.initializeGL
    a.exec()

