from OpenGL.GL import *
from OpenGL.GLUT import *
from OpenGL.GLU import *
import sys
import math

q_key = '\161'
s_key = '\163'
f_key = '\146'
B_key = '\102'
b_key = '\142'
C_key = '\103'
c_key = '\143'
D_key = '\104'
d_key = '\144'
O_key = '\117'
o_key = '\157'
P_key = '\120'
p_key = '\160'

XMIN = -10.0
XMAX = 10.0
YMIN = -10.0
YMAX = 10.0
M_PI = 3.14159265358979323846
kut = 0.0

verzija = 0
nn = 16

bijelo = [1.0, 1.0, 1.0, 1.0]
crno = [0.0, 0.0, 0.0, 1.0]
crveno = [1.0, 0.0, 0.0, 1.0]
smedje = [238.0 / 255.0, 154.0 / 255.0, 73.0 / 255.0]

def strelica(x, y, z, vx, vy, vz):
    glMaterialfv(GL_FRONT, GL_EMISSION, bijelo)
    glBegin(GL_LINES)
    glVertex3d(x,y,z)
    glVertex3d(x+vx, y+vy, z+vz)
    glEnd()
    glMaterialfv(GL_FRONT, GL_EMISSION, crno)

def normiraj(v):
    d = math.sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2])
    v[0] /= d; v[1] /= d; v[2] /= d
    return v

def vprodukt(v, a0, a1, a2, b0, b1, b2):
    v[0] = a1 * b2 - a2 * b1;
    v[1] = a2 * b0 - a0 * b2;
    v[2] = a0 * b1 - a1 * b0;
    return v

def stozac(a, b, h):
    t = [0.0, 0.0, 0.0]
    s = [0.0, 0.0, 0.0]
    v = [0.0, 0.0, 0.0]
    t1 = 0.0
    t2 = 0.0
    n = 16.0
    x1 = 0.0
    x2 = 0.0

    glBegin(GL_TRIANGLE_FAN)
    glNormal3d(0.0, 0.0, -1.0)
    glVertex3d(0.0, 0.0, 0.0)
    while x1<=n:
        glVertex3d(a * math.cos(t1), b * math.sin(t1), 0.0)
        t1 += 2*M_PI/n
        x1+=1
    glEnd()

    glBegin(GL_TRIANGLE_STRIP)
    t2 = 2.0 * M_PI
    while x2<=n:
        v = normiraj(vprodukt(v, a * math.cos(t2), b * math.sin(t2), -h, math.cos(t2 + M_PI / 2.0), math.sin(t2 + M_PI / 2.0), 0.0))
        glNormal3dv(v)
        glVertex3d(a * math.cos(t2), b * math.sin(t2), 0.0)
        t2 -= M_PI / n

        v = normiraj(vprodukt(v, a * math.cos(t2), b * math.sin(t2), -h, math.cos(t2 + M_PI / 2.0), math.sin(t2 + M_PI / 2.0), 0.0))
        glNormal3dv(v)
        glVertex3d(0.0, 0.0, h)
        t2 -= M_PI / n
        x2+=1
    glEnd()

def valjak(a, b, v):
    t1 = 0.0
    t2 = 0.0
    t3 = 0.0
    n = 16.0
    x1 = 0.0
    x2 = 0.0
    x3 = 0.0

    glBegin(GL_TRIANGLE_FAN)
    glNormal3d(0.0, 0.0, -1.0)
    glVertex3d(0.0, 0.0, 0.0)
    while x1<=n:
        glNormal3d(0.0, 0.0, -1.0)
        glVertex3d(a * math.cos(t1), b * math.sin(t1), 0.0)
        t1 += 2*M_PI/n
        x1+=1
    glEnd()

    glBegin(GL_TRIANGLE_FAN)
    glNormal3d(0.0, 0.0, 1.0)
    glVertex3d(0.0, 0.0, v)
    while x2<=n:
        glNormal3d(0.0, 0.0, 1.0)
        glVertex3d(a * math.cos(t2), b * math.sin(t2), v)
        t2 += 2*M_PI/n
        x2+=1
    glEnd()

    glBegin(GL_QUAD_STRIP)
    glVertex3d(0.0, 0.0, 0.0)
    glVertex3d(0.0, 0.0, v)
    while x3<=n:
        glNormal3d(math.cos(t3), math.sin(t3), 0.0)
        glVertex3d(a * math.cos(t3), b * math.sin(t3), 0.0)
        glNormal3d(math.cos(t3), math.sin(t3), 0.0)
        glVertex3d(a * math.cos(t3), b * math.sin(t3), v)
        t3 += 2*M_PI/n
        x3+=1
    glEnd()

def polukugla (a):
    phi = -90.0
    pomak = 20
    n = phi*(-2)/10
    theta = -180.0
    x = 0

    for phi in range (-90, -10, 12):
        glBegin (GL_QUAD_STRIP)
        for theta in range (-180, 181, pomak):
            param_theta = theta * M_PI / 180
            glNormal3d (math.sin(param_theta)*math.cos(phi*M_PI/180), math.cos(param_theta)*math.cos(phi*M_PI/180), math.sin(phi*M_PI/180))
            glVertex3d (a*math.sin(param_theta)*math.cos(phi*M_PI/180), a*math.cos(param_theta)*math.cos(phi*M_PI/180), a*math.sin(phi*M_PI/180))
            glNormal3d (math.sin(param_theta)*math.cos((phi+n)*M_PI/180), math.cos(param_theta)*math.cos((phi+n)*M_PI/180), math.sin((phi+n)*M_PI/ 180))
            glVertex3d (a*math.sin(param_theta)*math.cos((phi+n)*M_PI/180), a*math.cos(param_theta)*math.cos((phi+n)*M_PI/180), a*math.sin((phi+n)*M_PI/ 180))
            x += 1
        glEnd()

def kocka(a):
    glBegin(GL_QUADS);
    # donja ploha je crvena
    glColor3d(1.0, 0.0, 0.0)
    glVertex3d(0.0, 0.0, 0.0)
    glVertex3d(0.0, a, 0.0)
    glVertex3d(a, a, 0.0)
    glVertex3d(a, 0.0, 0.0)

    # gornja ploha je zelena
    glColor3d(0.0, 1.0, 0.0)
    glVertex3d(0.0, 0.0, a)
    glVertex3d(a, 0.0, a)
    glVertex3d(a, a, a)
    glVertex3d(0.0, a, a)
    glEnd()

    # bočne plohe
    glBegin(GL_QUAD_STRIP)
    # plava
    glColor3d(0.0, 0.0, 1.0)
    glVertex3d(0.0, 0.0, a)
    glVertex3d(0.0, 0.0, 0.0)
    glVertex3d(a, 0.0, a)
    glVertex3d(a, 0.0, 0.0)

    # žuta
    glColor3d(1.0, 1.0, 0.0)
    glVertex3d(a, a, a)
    glVertex3d(a, a, 0.0)

    # ljubičasta
    glColor3d(1.0, 0.0, 1.0)
    glVertex3d(0.0, a, a)
    glVertex3d(0.0, a, 0.0)

    # plavozelena (cijan)
    glColor3d(0.0, 1.0, 1.0)
    glVertex3d(0.0, 0.0, a)
    glVertex3d(0.0, 0.0, 0.0)
    glEnd()

def svjetlo0():
    pozicija = [0.0, 0.0, 0.0, 1.0]
    glLightfv(GL_LIGHT0, GL_DIFFUSE, bijelo)
    glLightfv(GL_LIGHT0, GL_SPECULAR, bijelo)
    glLightfv(GL_LIGHT0, GL_POSITION, pozicija)

def svjetlo1():
    pozicija = [0.0, 0.0, 0.0, 1.0]
    glLightfv(GL_LIGHT1, GL_DIFFUSE, crveno)
    glLightfv(GL_LIGHT1, GL_SPECULAR, crveno)
    glLightfv(GL_LIGHT1, GL_POSITION, pozicija)

# The main drawing function. 
def iscrtaj():
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
    glMatrixMode(GL_MODELVIEW)
    glLoadIdentity()

    # kamera
    gluLookAt(20.0, 0.0, 20.0, 0.0, 0.0, 4.0, 0.0, 0.0, 1.0)


    # svjetlo0
    glPushMatrix()
    glTranslated(0.0, 8.0, 5.0)
    svjetlo0()
    glMaterialfv(GL_FRONT, GL_EMISSION, bijelo)
    kocka(0.5)
    glMaterialfv(GL_FRONT, GL_EMISSION, crno)
    glPopMatrix()

    glMaterialfv(GL_FRONT, GL_DIFFUSE, smedje);
    glMaterialfv(GL_FRONT, GL_SPECULAR, bijelo);
    glMaterialf(GL_FRONT, GL_SHININESS, 20.0);

    #svjetlo1
    glPushMatrix()
    glTranslated(0.0, -8.0, 5.0)
    svjetlo1()
    glMaterialfv(GL_FRONT, GL_EMISSION, crveno)
    kocka(0.5)
    glMaterialfv(GL_FRONT, GL_EMISSION, crno)
    glPopMatrix()

    glMaterialfv(GL_FRONT, GL_DIFFUSE, smedje);
    glMaterialfv(GL_FRONT, GL_SPECULAR, bijelo);
    glMaterialf(GL_FRONT, GL_SHININESS, 20.0);


    #stozac
    stozac(2.0, 2.0, 7.0)

    #rotacija rakova
    glRotated(kut, 0.0, 0.0, 1.0)

    #valjak_baza
    glPushMatrix()
    glTranslated(0, 0, 5.5)
    valjak(0.5, 0.5, 0.7)
    glPopMatrix()

    #valjak_krak1
    glPushMatrix()
    glTranslated(0.0, -0.5, 5.75)
    glRotated(90, 1.0, 0.0, 0.0)
    valjak(0.3, 0.3, 3)
    glPopMatrix()

    #valjak_krak2
    glPushMatrix()
    glRotated(120, 0.0, 0.0, 1.0)
    glTranslated(0.0, -0.5, 5.75)
    glRotated(90, 1.0, 0.0, 0.0)
    valjak(0.3, 0.3, 3)
    glPopMatrix()
  
    #valjak_krak3
    glPushMatrix()
    glRotated(240, 0.0, 0.0, 1.0)
    glTranslated(0.0, -0.5, 5.75)
    glRotated(90, 1.0, 0.0, 0.0)
    valjak(0.3, 0.3, 3)
    glPopMatrix()

    #polukugla1
    glPushMatrix()
    glTranslated(0.0, -4.5, 5.75)
    glRotated(90, 0.0, 1.0, 0.0)
    polukugla(1)
    glPopMatrix()
 
    #polukugla2
    glPushMatrix()
    glRotated(120, 0.0, 0.0, 1.0)
    glTranslated(0.0, -4.5, 5.75)
    glRotated(90, 0.0, 1.0, 0.0)
    polukugla(1)
    glPopMatrix()

    #polukugla3
    glPushMatrix()
    glRotated(240, 0.0, 0.0, 1.0)
    glTranslated(0.0, -4.5, 5.75)
    glRotated(90, 0.0, 1.0, 0.0)
    polukugla(1)
    glPopMatrix()
    
    glutSwapBuffers()

def skaliraj(Width, Height):
    xrange = XMAX - XMIN
    yrange = Height * xrange / Width

    glViewport(0, 0, Width, Height)		
    glMatrixMode(GL_PROJECTION)
    glLoadIdentity()
    glFrustum(XMIN, XMAX, -yrange / 2.0, yrange / 2.0, 20.0, 50.0)

def tipka(*args):
    if args[0] == q_key:
        sys.exit()
    elif args[0] == s_key:
        glShadeModel(GL_SMOOTH)
    elif args[0] == f_key:
        glShadeModel(GL_FLAT)
    elif args[0] == B_key:
        glCullFace(GL_BACK)
    elif args[0] == b_key:
        glCullFace(GL_FRONT)
    elif args[0] == C_key:
        glEnable(GL_CULL_FACE)
    elif args[0] == c_key:
        glDisable(GL_CULL_FACE)
    elif args[0] == D_key:
        glEnable(GL_DEPTH_TEST)
    elif args[0] == d_key:
        glDisable(GL_DEPTH_TEST)
    elif args[0] == P_key:
        glEnable(GL_LIGHT0)
    elif args[0] == p_key:
        glDisable(GL_LIGHT0)
    elif args[0] == O_key:
        glEnable(GL_LIGHT1)
    elif args[0] == o_key:
        glDisable(GL_LIGHT1)
    

def rotiraj():
    global kut
    kut += -0.2
    glutPostRedisplay()

def main():
    glutInit(())
    glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGB)
    
    glutInitWindowSize(800, 600)
    glutInitWindowPosition(0, 0)
    
    glutCreateWindow("Zadatak2")
    
    glShadeModel(GL_FLAT)
    glEnable(GL_DEPTH_TEST)
    glClearColor(0.0, 0.0, 0.0, 0.0)

    glEnable(GL_LIGHTING)
    glEnable(GL_LIGHT0)
    glEnable(GL_LIGHT1)
  
    glutDisplayFunc(iscrtaj)
    glutReshapeFunc(skaliraj)
    glutKeyboardFunc(tipka)
    glutIdleFunc(rotiraj)
    glutMainLoop()

main()
    	
