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

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


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)
	
#q = quader
def relevantePunkteGebenQuader2(q):
	axis = vektorBetragAnpassen(q.axis, q.length / 2)
	up = vektorBetragAnpassen(q.up, q.height / 2)       
	senkrecht = vektorBetragAnpassen(kreuzprodukt(axis, up), q.width / 2)
	
	liste = [vektorAddition(q.pos, axis), vektorSubtraktion(q.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(q.pos, up))
	liste.append(vektorSubtraktion(q.pos, up))
	
	#Mittelpunkte der Flächen die durch height und length aufgespannt werden
	liste.append(vektorAddition(q.pos, senkrecht))
	liste.append(vektorSubtraktion(q.pos, senkrecht))
	
	#kantenmittelpunkte
	liste.append(vektorAddition(vektorAddition(q.pos, axis), up))
	liste.append(vektorSubtraktion(vektorAddition(q.pos, axis), up))
	
	liste.append(vektorAddition(vektorSubtraktion(q.pos, axis), up))
	liste.append(vektorSubtraktion(vektorSubtraktion(q.pos, axis), up))
	
	liste.append(vektorAddition(vektorAddition(q.pos, axis), senkrecht))
	liste.append(vektorSubtraktion(vektorAddition(q.pos, axis), senkrecht))
	
	liste.append(vektorAddition(vektorSubtraktion(q.pos, axis), senkrecht))
	liste.append(vektorSubtraktion(vektorSubtraktion(q.pos, axis), senkrecht))
	
	liste.append(vektorAddition(vektorAddition(q.pos, up), senkrecht))
	liste.append(vektorSubtraktion(vektorAddition(q.pos, up), senkrecht))
	
	liste.append(vektorAddition(vektorSubtraktion(q.pos, up), senkrecht))
	liste.append(vektorSubtraktion(vektorSubtraktion(q.pos, up), senkrecht))
	
	#eckpunkte
	liste.append(vektorAddition(vektorAddition(vektorAddition(q.pos, axis), up), senkrecht))
	liste.append(vektorAddition(vektorAddition(vektorSubtraktion(q.pos, axis), up), senkrecht))
	
	liste.append(vektorAddition(vektorSubtraktion(vektorAddition(q.pos, axis), up), senkrecht))
	liste.append(vektorAddition(vektorSubtraktion(vektorSubtraktion(q.pos, axis), up), senkrecht))
	
	liste.append(vektorSubtraktion(vektorAddition(vektorAddition(q.pos, axis), up), senkrecht))
	liste.append(vektorSubtraktion(vektorAddition(vektorSubtraktion(q.pos, axis), up), senkrecht))
	
	liste.append(vektorSubtraktion(vektorSubtraktion(vektorAddition(q.pos, axis), up), senkrecht))
	liste.append(vektorSubtraktion(vektorSubtraktion(vektorSubtraktion(q.pos, axis), up), senkrecht))
	
	
	return liste


#k = kugel, p = punkt, true, bei kollision, false ohne kollision
def kollisionPunktKugel(k, p):
	mp = vektorSubtraktion(k.pos, p)
	betrag = vektorBetrag(mp)
	
	return (betrag <= k.radius)
	


#false ohne Kollision, true bei Kollision	
def kollisionQuaderKugel(kugel, quader):
	liste = relevantePunkteGebenQuader2(quader)
	
	for i in liste:
		if kollisionPunktKugel(kugel, 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), length=1.6, height=2.1, width=0.02, color=(.5,0,0), frame=buch) 
    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 = 20                # Konstante: Anzahl der Häuser
auge_anzahl = 5
# graue Bodenplatte
floor = box(pos=(0,0,0), width=120, height=1, length=120, color=(0.4,0.4,0.4), material=materials.wood)
# wände
w1 = box(pos = (-60,15,0),width=120, height= 30, axis = (-1,0,0))
w2 = box(pos = (60,15,0),width=120, height= 30, axis = (1,0,0))
w3 = box(pos = (0,15,-60),length=120,width = 1, height= 30)
w4 = box(pos = (0,15,60),length=120, width = 1, height= 30)

for i in range(haus_anzahl): # Häuser durch Zufall generieren
    zufall = random()
    box(pos=(random()*100-50, (10+zufall*5)/2,random()*100-50),\
        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, -50), string="WEIMAR", color=(.9,.9,0), depth=1, height=5, justify="center") #Schriftzug


#auge color=(0,0.5,6)

aliste = []

for i in range(auge_anzahl): # Auge durch Zufall generieren
    zufall = random()
    auge = frame()
    kugel = sphere(pos=(1,2,1), radius=5, material=materials.plastic, frame=auge)
    iris = sphere(pos=(1,2,2.7), radius=3.5, material=materials.wood, color=(0,0.5,6), frame=auge)
    pupille = sphere(pos=(1,2,3.8), radius = 2.5, material=materials.plastic,color=(0,0,0), frame=auge)
    auge.pos = (random()*100-50, (10+zufall*5)/2,random()*100-50)
    auge.axis = (random(), random(), random())
    auge.scale=(.01,.01,.01)
    aliste.append(auge)
        

scene.range = 5

    
#-Zweitfenster für topview---
zweitfenster = display(width=400,height=430, title="TOP-VIEW",\
                       center=(0,5,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

#display = scene
scene.select()
buch = buchgeben()

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()
        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
     
      
    z = len(bliste) - 1
    while z >= 0:
        bliste[z].pos = vektorAddition(bliste[z].pos, vliste[z])
        
        for i in range(len(aliste)):
            if kollisionQuaderKugel(aliste[i].objects[0] , bliste[z].objects[0]):
                aliste[i].visibility = False
        
        if vektorBetrag(bliste[z].pos) > 200:
            
            b = bliste.pop(z)
            b.visibility = 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
            
    




	
