# -*- coding: utf-8 -*-
# Teststadt für Rundgang
# 2010-03-08

from visual import *
from visual.text import *
from random import *

import Image
name = "faust.tga"

width = 400
height = 640

im = Image.open(name)
materials.saveTGA(name,im)      # Speichern des Bildes intern
data = materials.loadTGA(name)
tex = materials.texture(data=im, mapping="sign")

geschossen = -1
getroffen = 0

def kreuzprodukt(v1, v2):
	return (v1[1]*v2[2] - v1[2]*v2[1], v1[2]*v2[0] - v1[0]*v2[2], v1[0]*v2[1] - v1[1]*v2[0])
	

	
def vektorAddition(v1, v2):
	x = v1[0] + v2[0]
	y = v1[1] + v2[1]
	z = v1[2] + v2[2]
	return (x, y, z)
	
def vektorSubtraktion(v1, v2):
	x = v1[0] - v2[0]
	y = v1[1] - v2[1]
	z = v1[2] - v2[2]
	return (x, y, z)


	
#b = buch
def relevantePunkteGebenQuader2(b):
	axis = vektorBetragAnpassen(b.objects[0].axis, b.objects[0].length / 2)
	up = vektorBetragAnpassen(b.objects[0].up, b.objects[0].height / 2)       
	senkrecht = vektorBetragAnpassen(kreuzprodukt(axis, up), b.objects[0].width / 2)
	
	liste = [vektorAddition(b.pos, axis), vektorSubtraktion(b.pos, axis)] #Mittelpunkte der Flächen die durch height und width aufgespannt werden
	
	#Mittelpunkte der Flächen die durch length und width aufgespannt werden
	liste.append(vektorAddition(b.pos, up))
	liste.append(vektorSubtraktion(b.pos, up))
	
	#Mittelpunkte der Flächen die durch height und length aufgespannt werden
	liste.append(vektorAddition(b.pos, senkrecht))
	liste.append(vektorSubtraktion(b.pos, senkrecht))
	
	#kantenmittelpunkte
	liste.append(vektorAddition(vektorAddition(b.pos, axis), up))
	liste.append(vektorSubtraktion(vektorAddition(b.pos, axis), up))
	
	liste.append(vektorAddition(vektorSubtraktion(b.pos, axis), up))
	liste.append(vektorSubtraktion(vektorSubtraktion(b.pos, axis), up))
	
	liste.append(vektorAddition(vektorAddition(b.pos, axis), senkrecht))
	liste.append(vektorSubtraktion(vektorAddition(b.pos, axis), senkrecht))
	
	liste.append(vektorAddition(vektorSubtraktion(b.pos, axis), senkrecht))
	liste.append(vektorSubtraktion(vektorSubtraktion(b.pos, axis), senkrecht))
	
	liste.append(vektorAddition(vektorAddition(b.pos, up), senkrecht))
	liste.append(vektorSubtraktion(vektorAddition(b.pos, up), senkrecht))
	
	liste.append(vektorAddition(vektorSubtraktion(b.pos, up), senkrecht))
	liste.append(vektorSubtraktion(vektorSubtraktion(b.pos, up), senkrecht))
	
	#eckpunkte
	liste.append(vektorAddition(vektorAddition(vektorAddition(b.pos, axis), up), senkrecht))
	liste.append(vektorAddition(vektorAddition(vektorSubtraktion(b.pos, axis), up), senkrecht))
	
	liste.append(vektorAddition(vektorSubtraktion(vektorAddition(b.pos, axis), up), senkrecht))
	liste.append(vektorAddition(vektorSubtraktion(vektorSubtraktion(b.pos, axis), up), senkrecht))
	
	liste.append(vektorSubtraktion(vektorAddition(vektorAddition(b.pos, axis), up), senkrecht))
	liste.append(vektorSubtraktion(vektorAddition(vektorSubtraktion(b.pos, axis), up), senkrecht))
	
	liste.append(vektorSubtraktion(vektorSubtraktion(vektorAddition(b.pos, axis), up), senkrecht))
	liste.append(vektorSubtraktion(vektorSubtraktion(vektorSubtraktion(b.pos, axis), up), senkrecht))
	
	
	return liste


#a = auge, p = punkt, true, bei kollision, false ohne kollision
def kollisionPunktKugel(a, p):
	mp = vektorSubtraktion(a.pos, p)
	betrag = vektorBetrag(mp)
	
	return (betrag <= a.objects[0].radius)
	


#false ohne Kollision, true bei Kollision	
def kollisionQuaderKugel(auge, buch):
	liste = relevantePunkteGebenQuader2(buch)
	
	for i in liste:
		if kollisionPunktKugel(auge, i):
			return True
	
	return False


def buchgeben():
    buch = frame()
    buchinhalt = box(pos=(0,0,0),length=1.5, height=2, width=0.5, material=materials.emissive, frame=buch)
    deckel1 = box(pos=(0.04,0,0.26), height=2.1, width=1.6, axis =(0,0,.02), color=(.5,0,0), frame=buch, material= tex)  
    deckel2 = box(pos=(0.04,0,-0.26), length=1.6, height=2.1, width=0.02, color=(.5,0,0), frame=buch)
    deckel3 = box(pos=(-0.77,0,0), length =0.02, height= 2.1, width= 0.54, color=(.5,0,0), frame=buch)
    buch.pos=(scene.center)
    return buch

def vektorBetrag(v):
	return ((float)(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]))**(0.5) #** ist Hochrechnen

def vektorBetragAnpassen(v, l):
	vektorbetrag = vektorBetrag(v)
	x = (v[0] / vektorbetrag) * l
	y = (v[1] / vektorbetrag) * l
	z = (v[2] / vektorbetrag) * l
	return (x, y, z)



scene.title = "WEIMAR" # Fenstertitel
scene.x = 0	                    # Fensterpos v. links
scene.y = 0	                    # Fensterpos v. oben
scene.height = 600              # Fensterhöhe
scene.width = 1000              # Fensterbreite
scene.range = (1,1,1)           # Abstand
scene.center = (0,5,50)         # Festlegung Blickziel
scene.userspin = False          # Blickwechsel abgeschaltet
scene.userzoom = False          # Benutzerzoom abgeschaltet
scene.fov = 2                   # Kamerawinkel
scene.background = (0.8,0.85,1) # Farbe Hintergrund
scene.stereodepth = 2           # Stereotiefe
scene.show_rendertime = True    # Anzeige der Berechnungszeiten
scene.fullscreen = False        # Vollbildmodus
haus_anzahl = 80                # Konstante: Anzahl der Häuser
auge_anzahl = 1
# graue Bodenplatte
floor = box(pos=(0,0,0), width=240, height=1, length=240, color=(0.4,0.4,0.4), material=materials.wood)
# wände
w1 = box(pos = (-120,15,0),width=240, height= 30, axis = (-1,0,0), material = materials.marble)
w2 = box(pos = (120,15,0),width=240, height= 30, axis = (1,0,0),material = materials.marble)
w3 = box(pos = (0,15,-120),length=240,width = 1, height= 30, material = materials.marble)
w4 = box(pos = (0,15,120),length=240, width = 1, height= 30, material = materials.marble)

for i in range(haus_anzahl): # Häuser durch Zufall generieren
    zufall = random()
    box(pos=(random()*200-100, (10+zufall*5)/2,random()*200-100),\
        width=5+random()*5, height=10+zufall*5, length=7+random()*3, \
        color=color.hsv_to_rgb(((float(i)/haus_anzahl),.8,.4)), material = materials.rough)
text(pos=(0, 20, -120), string="WEIMAR", color=(.9,.9,0), depth=1, height=5, justify="center") #Schriftzug


#auge color=(0,0.5,6)

aliste = []

def augenmachen():
    for i in range(auge_anzahl): # Auge durch Zufall generieren
        zufall = random()
        auge = frame()
        kugel = sphere(pos=(0,0,0), radius=3, material=materials.plastic, frame=auge)
        iris = sphere(pos=(0,0,.72), radius=2.4, material=materials.wood, color=(0,0.5,6), frame=auge)
        pupille = sphere(pos=(0,0,1.045), radius = 2.1, material=materials.plastic,color=(0,0,0), frame=auge)
        auge.pos = (random()*200-100, (10+zufall*5)/2,random()*200-100)
        auge.axis = (random(), random(), random())
        auge.scale=(.01,.01,.01)
        aliste.append(auge)
        
augenmachen()
scene.range = 5

    
#-Zweitfenster für topview---
zweitfenster = display(width=500,height=500, title="TOP-VIEW",\
                       center=(0,100,0), forward=(0,-5,0), x=1000, y=0,\
                       background=(0.8,0.85,1))
zweitfenster.range = 75
zweitfenster.select()
for obj in scene.objects:
    try:
        obj.__copy__(display=zweitfenster).opacity=0.5
    except:
        pass
walker = sphere(radius=1.5, color=color.white, pos=scene.center, material=materials.emissive)
walker.trail = curve(color=color.yellow)
pick = None # no object picked out of the scene yet
schuss = label(pos=(0,0,-40),height=10, text='Buecherkonsumption: 0',font='sans')
treffer = label(pos=(0,0,40), height=10, text='Faust aufs Auge!',font='sans')


#display = scene
scene.select()
buch = buchgeben()
zitate = ['Er nennt´s Vernunft und braucht´s allein, nur tierischer als jedes Tier zu sein.' ,'Es irrt der Mensch, solang er strebt.' , \
'Ein guter Mensch in seinem dunklen Drange ist sich des rechten Weges wohl bewusst.' , 'Dass ich erkenne, was die Welt im Innersten zusammenhält.', 'Die Botschaft hör ich wohl, allein mir fehlt der Glaube.']
fliegt = False
vektor = None
bliste = []
vliste = []
zaehler = 0
while True:
    rate(50)
    
    if scene.mouse.events: 
        m1 = scene.mouse.getevent() # get event
        if m1.press:
            vliste.append(vektorBetragAnpassen(scene.forward, 1))
            bliste.append(buch)
            scene.select()
            buch = buchgeben()
            geschossen += 1
            schuss.text="Buecherkonsumption: "+str(geschossen)
        if m1.drag and m1.pick == buch: # if touched buch
            drag_pos = m1.pickpos # where on the buch
            pick = m1.pick # pick now true (not None) 
        elif m1.drop: # released at end of drag
            pick = None # end dragging (None is false)
          
        
    if pick:
        # project onto xy plane, even if scene rotated:
        new_pos = scene.mouse.project(normal=(0,0,1)) 
        if new_pos != drag_pos: # if mouse has moved
            # offset for where the ball was clicked:
            pick.pos += new_pos - drag_pos 
            drag_pos = new_pos # update drag position
    
    

    buch.pos = scene.mouse.pos
     
    for j in aliste:
        #j.axis = (random(), random(), random())
        j.rotate(angle=radians(0.5), axis=(0,1,0))
    
      
    z = len(bliste) - 1
    while z >= 0:
        bliste[z].pos = vektorAddition(bliste[z].pos, vliste[z])
        
        i = len(aliste) - 1
        while i >= 0:
            if kollisionQuaderKugel(aliste[i], bliste[z]):
                aliste[i].visible = False
                
                a = aliste.pop(i)
                
                for j in a.objects:
                    j.visible = False
                    del(j)
                del(a)
                getroffen += 1
                treffer.text = "Treffer: "+str(getroffen)+'/'+str(auge_anzahl)
                
            i = i - 1
        
        
            
        if vektorBetrag(bliste[z].pos) > 200:
            
            b = bliste.pop(z)
            b.visible = False
            del(b)
            v = vliste.pop(z)
            del(v)
            
        z = z - 1
        
        
    


    
    zweitfenster.select()
    walker.pos = scene.center
    walker.trail.append(pos=walker.pos, retain=5000)
    
    

    # Falls Tastatur gedrückt...
    if scene.kb.keys:
        s = scene.kb.getkey()
        print s
        
        if   s == 'up':     # vorwärts
            scene.center = scene.center+scene.forward*.6*mag(scene.center-scene.mouse.camera)
        elif s == 'down':   # rückwärts
            scene.center = scene.center-scene.forward*.6*mag(scene.center-scene.mouse.camera)
        
        elif s == 'left':   # links drehen
            newforward = rotate(scene.forward, axis=scene.up, angle=radians(4))
            scene.center = scene.mouse.camera+newforward*mag(scene.center-scene.mouse.camera)
            scene.forward = newforward
            #scene.center = scene.center+scene.forward*ray.y/2.
        elif s == 'right':  # rechts drehen
            newforward = rotate(scene.forward, axis=scene.up, angle=radians(-4))
            scene.center = scene.mouse.camera+newforward*mag(scene.center-scene.mouse.camera)
            scene.forward = newforward
    
    
    if getroffen == auge_anzahl:
        scene.select()
        #schrift = label(pos = (0,15,-120),height = 5, text = zitate[int(round(random()*5))], font='sans')
        augenmachen()
        getroffen = 0       
    




