'
' This is the BaCon port of the 'Molehill' OpenGL program.
'
' See also: http://www.opengl.org/resources/code/samples/glut_examples/examples/examples.html
'
' Port by Peter van Eerten - February 2010.
'

INCLUDE "gl.bac"
INCLUDE "glu.bac"
INCLUDE "glut.bac"

DECLARE mat_red_diffuse[] = { 0.7, 0.0, 0.1, 1.0 } TYPE float
DECLARE mat_green_diffuse[] = { 0.0, 0.7, 0.1, 1.0 } TYPE float
DECLARE mat_blue_diffuse[] = { 0.0, 0.1, 0.7, 1.0 } TYPE float
DECLARE mat_yellow_diffuse[] = { 0.7, 0.8, 0.1, 1.0 } TYPE float
DECLARE mat_specular[] = { 1.0, 1.0, 1.0, 1.0 } TYPE float
DECLARE mat_shininess[] = { 100.0 } TYPE float
DECLARE knots[8] = { 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0 } TYPE float
DECLARE pts1[4][4][3] TYPE float
DECLARE pts2[4][4][3] TYPE float
DECLARE pts3[4][4][3] TYPE float
DECLARE pts4[4][4][3] TYPE float
DECLARE nurb
DECLARE u, v TYPE int

SUB display

  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
  glCallList(1)
  glFlush()

END SUB

SUB mainprog

    glutCreateWindow("molehill")
    glMaterialfv(GL_FRONT, GL_SPECULAR, ADDRESS(mat_specular))
    glMaterialfv(GL_FRONT, GL_SHININESS, ADDRESS(mat_shininess))
    glEnable(GL_LIGHTING)
    glEnable(GL_LIGHT0)
    glEnable(GL_DEPTH_TEST)
    glEnable(GL_AUTO_NORMAL)
    glEnable(GL_NORMALIZE)
    nurb = gluNewNurbsRenderer()
    gluNurbsProperty(nurb, GLU_SAMPLING_TOLERANCE, 25.0)
    gluNurbsProperty(nurb, GLU_DISPLAY_MODE, GLU_FILL)

    ' Build control points for NURBS mole hills.
    FOR u = 0 TO 3
        FOR v = 0 TO 3
            ' Red.
            pts1[u][v][0] = 2.0*((float)u)
            pts1[u][v][1] = 2.0*((float)v)
            IF ((u IS 1 OR u IS 2) AND (v IS 1 OR v IS 2)) THEN
                ' Stretch up middle.
                pts1[u][v][2] = 6.0
            ELSE
                pts1[u][v][2] = 0.0
            END IF

            ' Green.
            pts2[u][v][0] = 2.0*((float)u - 3.0)
            pts2[u][v][1] = 2.0*((float)v - 3.0)
            IF ((u IS 1 OR u IS 2) AND (v IS 1 OR v IS 2)) THEN
                IF (u IS 1 AND v IS 1) THEN
                    ' Pull hard on single middle square.
                    pts2[u][v][2] = 15.0
                ELSE
                    ' Push down on other middle squares.
                    pts2[u][v][2] = -2.0
                END IF
            ELSE
                pts2[u][v][2] = 0.0
            END IF

            ' Blue.
            pts3[u][v][0] = 2.0*((float)u - 3.0)
            pts3[u][v][1] = 2.0*((float)v)
            IF ((u IS 1 OR u IS 2) AND (v IS 1 OR v IS 2)) THEN
                IF (u IS 1 AND v IS 2) THEN
                    ' Pull up on single middple square.
                    pts3[u][v][2] = 11.0
                ELSE
                    ' Pull up slightly on other middle squares.
                    pts3[u][v][2] = 2.0
                END IF
            ELSE
                pts3[u][v][2] = 0.0
            END IF

            ' Yellow.
            pts4[u][v][0] = 2.0*((float)u)
            pts4[u][v][1] = 2.0*((float)v - 3.0)
            IF ((u IS 1 OR u IS 2 OR u IS 3) AND (v IS 1 OR v IS 2)) THEN
                IF v IS 1 THEN
                    ' Push down front middle and right squares.
                    pts4[u][v][2] = -2.0
                ELSE
                    ' Pull up back middle and right squares.
                    pts4[u][v][2] = 5.0
                END IF
            ELSE
                pts4[u][v][2] = 0.0
            END IF
        NEXT v
    NEXT u
    ' Stretch up red's far right corner.
    pts1[3][3][2] = 6
    ' Pull down green's near left corner a little.
    pts2[0][0][2] = -2
    ' Turn up meeting of four corners.
    pts1[0][0][2] = 1
    pts2[3][3][2] = 1
    pts3[3][0][2] = 1
    pts4[0][3][2] = 1

    glMatrixMode(GL_PROJECTION)

    gluPerspective(55.0, 1.0, 2.0, 24.0)
    glMatrixMode(GL_MODELVIEW)
    glTranslatef(0.0, 0.0, -15.0)
    glRotatef(330.0, 1.0, 0.0, 0.0)

    glNewList(1, GL_COMPILE)
    ' Render red hill.
    glMaterialfv(GL_FRONT, GL_DIFFUSE, ADDRESS(mat_red_diffuse))
    gluBeginSurface(nurb)
    gluNurbsSurface(nurb, 8, ADDRESS(knots), 8, ADDRESS(knots), 4 * 3, 3, ADDRESS(pts1), 4, 4, GL_MAP2_VERTEX_3)
    gluEndSurface(nurb)

    ' Render green hill.
    glMaterialfv(GL_FRONT, GL_DIFFUSE, ADDRESS(mat_green_diffuse))
    gluBeginSurface(nurb)
    gluNurbsSurface(nurb, 8, ADDRESS(knots), 8, ADDRESS(knots), 4 * 3, 3, ADDRESS(pts2), 4, 4, GL_MAP2_VERTEX_3)
    gluEndSurface(nurb)

    ' Render blue hill.
    glMaterialfv(GL_FRONT, GL_DIFFUSE, ADDRESS(mat_blue_diffuse))
    gluBeginSurface(nurb)
    gluNurbsSurface(nurb, 8, ADDRESS(knots), 8, ADDRESS(knots), 4 * 3, 3, ADDRESS(pts3), 4, 4, GL_MAP2_VERTEX_3)
    gluEndSurface(nurb)

    ' Render yellow hill.
    glMaterialfv(GL_FRONT, GL_DIFFUSE, ADDRESS(mat_yellow_diffuse))
    gluBeginSurface(nurb)
    gluNurbsSurface(nurb, 8, ADDRESS(knots), 8, ADDRESS(knots), 4 * 3, 3, ADDRESS(pts4), 4, 4, GL_MAP2_VERTEX_3)
    gluEndSurface(nurb)
    glEndList

    glutDisplayFunc(ADDRESS(display))
    glutMainLoop

END SUB

mainprog