var settings = {
    release: true,
    sync: true
};


var Sync = function() {
    this.BPM = 80,
    this.ROWS_PER_BEAT = 8,
    this.ROW_RATE = this.BPM / 60 * this.ROWS_PER_BEAT,
    this.musicReady = false,
    this.music = new Audio(),
    this.device = new JSRocket.SyncDevice(),
    this.row = 0,
    this.previousRow = 0,
    this.tracks = {
        _tracks: {},
        init: function(device) {        
            this._tracks.logo = {
                type: "logo",
                position : {
                    x: device.getTrack("logo.position.x"),
                    y: device.getTrack("logo.position.y"),
                    z: device.getTrack("logo.position.z")
                },
                scale : {
                    x: device.getTrack("logo.scale.x"),
                    y: device.getTrack("logo.scale.y"),
                    z: device.getTrack("logo.scale.z")
                },
                rotation : {
                    x: device.getTrack("logo.rotation.x"),
                    y: device.getTrack("logo.rotation.y"),
                    z: device.getTrack("logo.rotation.z")
                },
                color : {
                    r: device.getTrack("logo.color.r"),
                    g: device.getTrack("logo.color.g"),
                    b: device.getTrack("logo.color.b")
                },
                alpha: {
                    value: device.getTrack("logo.alpha")
                } ,
                enabled: {
                    value: device.getTrack("logo.enabled")
                }
            };
            this._tracks.floor = {
                type: "floor",
                position : {
                    x: device.getTrack("floor.position.x"),
                    y: device.getTrack("floor.position.y"),
                    z: device.getTrack("floor.position.z")
                },
                scale : {
                    x: device.getTrack("floor.scale.x"),
                    y: device.getTrack("floor.scale.y"),
                    z: device.getTrack("floor.scale.z")
                },
                rotation : {
                    x: device.getTrack("floor.rotation.x"),
                    y: device.getTrack("floor.rotation.y"),
                    z: device.getTrack("floor.rotation.z")
                },
                alpha: {
                    value: device.getTrack("floor.alpha")
                }
            };
            this._tracks.camera = {
                type: "camera",
                position : {
                    x: device.getTrack("camera.position.x"),
                    y: device.getTrack("camera.position.y"),
                    z: device.getTrack("camera.position.z")
                },
                scale : {
                    x: device.getTrack("camera.scale.x"),
                    y: device.getTrack("camera.scale.y"),
                    z: device.getTrack("camera.scale.z")
                },
                rotation : {
                    x: device.getTrack("camera.rotation.x"),
                    y: device.getTrack("camera.rotation.y"),
                    z: device.getTrack("camera.rotation.z")
                },
                look : {
                    x: device.getTrack("camera.look.x"),
                    y: device.getTrack("camera.look.y"),
                    z: device.getTrack("camera.look.z")
                }

            };
            this._tracks.march = {
                type: "march",
                position : {
                    x: device.getTrack("march.position.x"),
                    y: device.getTrack("march.position.y"),
                    z: device.getTrack("march.position.z")
                },
                rotation : {
                    x: device.getTrack("march.rotation.x"),
                    y: device.getTrack("march.rotation.y"),
                    z: device.getTrack("march.rotation.z")
                },
                color : {
                    r: device.getTrack("march.color.r"),
                    g: device.getTrack("march.color.g"),
                    b: device.getTrack("march.color.b")
                },
                fov : {
                    value: device.getTrack("march.fov")
                },
                alpha : {
                    value: device.getTrack("march.alpha")
                },
                dist : {
                    value: device.getTrack("march.dist")
                },
                darkness : {
                    value: device.getTrack("march.darkness")
                },
                modifier : {
                    value: device.getTrack("march.mod")
                },
                enabled : {
                    value: device.getTrack("march.enabled")
                }


            };
            this._tracks.onlycode = {
                type: "onlycode",
                position : {
                    x: device.getTrack("onlycode.position.x"),
                    y: device.getTrack("onlycode.position.y"),
                    z: device.getTrack("onlycode.position.z")
                },
                scale : {
                    x: device.getTrack("onlycode.scale.x"),
                    y: device.getTrack("onlycode.scale.y"),
                    z: device.getTrack("onlycode.scale.z")
                },
                rotation : {
                    x: device.getTrack("onlycode.rotation.x"),
                    y: device.getTrack("onlycode.rotation.y"),
                    z: device.getTrack("onlycode.rotation.z")
                },
                color : {
                    r: device.getTrack("onlycode.color.r"),
                    g: device.getTrack("onlycode.color.g"),
                    b: device.getTrack("onlycode.color.b")
                },
                alpha: {
                    value: device.getTrack("onlycode.alpha")
                } 
            };
            this._tracks.gods = {
                type: "gods",
                position : {
                    x: device.getTrack("gods.position.x"),
                    y: device.getTrack("gods.position.y"),
                    z: device.getTrack("gods.position.z")
                },
                scale : {
                    x: device.getTrack("gods.scale.x"),
                    y: device.getTrack("gods.scale.y"),
                    z: device.getTrack("gods.scale.z")
                },
                rotation : {
                    x: device.getTrack("gods.rotation.x"),
                    y: device.getTrack("gods.rotation.y"),
                    z: device.getTrack("gods.rotation.z")
                },
                color : {
                    r: device.getTrack("gods.color.r"),
                    g: device.getTrack("gods.color.g"),
                    b: device.getTrack("gods.color.b")
                },
                alpha: {
                    value: device.getTrack("gods.alpha")
                } 
            };
            this._tracks.darkness = {
                type: "darkness",
                position : {
                    x: device.getTrack("darkness.position.x"),
                    y: device.getTrack("darkness.position.y"),
                    z: device.getTrack("darkness.position.z")
                },
                scale : {
                    x: device.getTrack("darkness.scale.x"),
                    y: device.getTrack("darkness.scale.y"),
                    z: device.getTrack("darkness.scale.z")
                },
                rotation : {
                    x: device.getTrack("darkness.rotation.x"),
                    y: device.getTrack("darkness.rotation.y"),
                    z: device.getTrack("darkness.rotation.z")
                },
                color : {
                    r: device.getTrack("darkness.color.r"),
                    g: device.getTrack("darkness.color.g"),
                    b: device.getTrack("darkness.color.b")
                },
                alpha: {
                    value: device.getTrack("darkness.alpha")
                } 
            };
            this._tracks.synth = {
                type: "synth",
                position : {
                    x: device.getTrack("synth.position.x"),
                    y: device.getTrack("synth.position.y"),
                    z: device.getTrack("synth.position.z")
                },
                scale : {
                    x: device.getTrack("synth.scale.x"),
                    y: device.getTrack("synth.scale.y"),
                    z: device.getTrack("synth.scale.z")
                },
                rotation : {
                    x: device.getTrack("synth.rotation.x"),
                    y: device.getTrack("synth.rotation.y"),
                    z: device.getTrack("synth.rotation.z")
                },
                color : {
                    r: device.getTrack("synth.color.r"),
                    g: device.getTrack("synth.color.g"),
                    b: device.getTrack("synth.color.b")
                },
                alpha: {
                    value: device.getTrack("synth.alpha")
                } 
            };
            this._tracks.gfx = {
                type: "gfx",
                position : {
                    x: device.getTrack("gfx.position.x"),
                    y: device.getTrack("gfx.position.y"),
                    z: device.getTrack("gfx.position.z")
                },
                scale : {
                    x: device.getTrack("gfx.scale.x"),
                    y: device.getTrack("gfx.scale.y"),
                    z: device.getTrack("gfx.scale.z")
                },
                rotation : {
                    x: device.getTrack("gfx.rotation.x"),
                    y: device.getTrack("gfx.rotation.y"),
                    z: device.getTrack("gfx.rotation.z")
                },
                color : {
                    r: device.getTrack("gfx.color.r"),
                    g: device.getTrack("gfx.color.g"),
                    b: device.getTrack("gfx.color.b")
                },
                alpha: {
                    value: device.getTrack("gfx.alpha")
                } 
            };
            this._tracks.code = {
                type: "code",
                position : {
                    x: device.getTrack("code.position.x"),
                    y: device.getTrack("code.position.y"),
                    z: device.getTrack("code.position.z")
                },
                scale : {
                    x: device.getTrack("code.scale.x"),
                    y: device.getTrack("code.scale.y"),
                    z: device.getTrack("code.scale.z")
                },
                rotation : {
                    x: device.getTrack("code.rotation.x"),
                    y: device.getTrack("code.rotation.y"),
                    z: device.getTrack("code.rotation.z")
                },
                color : {
                    r: device.getTrack("code.color.r"),
                    g: device.getTrack("code.color.g"),
                    b: device.getTrack("code.color.b")
                },
                alpha: {
                    value: device.getTrack("code.alpha")
                } 
            };
            this._tracks.music = {
                type: "music",
                position : {
                    x: device.getTrack("music.position.x"),
                    y: device.getTrack("music.position.y"),
                    z: device.getTrack("music.position.z")
                },
                scale : {
                    x: device.getTrack("music.scale.x"),
                    y: device.getTrack("music.scale.y"),
                    z: device.getTrack("music.scale.z")
                },
                rotation : {
                    x: device.getTrack("music.rotation.x"),
                    y: device.getTrack("music.rotation.y"),
                    z: device.getTrack("music.rotation.z")
                },
                color : {
                    r: device.getTrack("music.color.r"),
                    g: device.getTrack("music.color.g"),
                    b: device.getTrack("music.color.b")
                },
                alpha: {
                    value: device.getTrack("music.alpha")
                } 
            };
            this._tracks.common = {
                type: "common",
                time : {
                    value: device.getTrack("common.time"),

                }
            };
                
        },
        get: function(name, row) {
            var track = this._tracks[name];
            if(track.type == "logo") {
                return {
                    position: {
                        x: track.position.x.getValue(row) || 0,
                        y: track.position.y.getValue(row) || 0,
                        z: track.position.z.getValue(row) || 0
                    },
                    scale: {
                        x: track.scale.x.getValue(row) || 0,
                        y: track.scale.y.getValue(row) || 0,
                        z: track.scale.z.getValue(row) || 0
                    },
                    rotation: {
                        x: track.rotation.x.getValue(row) || 0,
                        y: track.rotation.y.getValue(row) || 0,
                        z: track.rotation.z.getValue(row) || 0
                    },
                    color: {
                        r: track.color.r.getValue(row) || 0,
                        g: track.color.g.getValue(row) || 0,
                        b: track.color.b.getValue(row) || 0
                    },
                    alpha: {
                        value: track.alpha.value.getValue(row) || 0
                    },
                    enabled: {
                        value: track.enabled.value.getValue(row) || 0
                    }
                }
            }
            else if(track.type == "floor") {
                return {
                    position: {
                        x: track.position.x.getValue(row) || 0,
                        y: track.position.y.getValue(row) || 0,
                        z: track.position.z.getValue(row) || 0
                    },
                    scale: {
                        x: track.scale.x.getValue(row) || 0,
                        y: track.scale.y.getValue(row) || 0,
                        z: track.scale.z.getValue(row) || 0
                    },
                    rotation: {
                        x: track.rotation.x.getValue(row) || 0,
                        y: track.rotation.y.getValue(row) || 0,
                        z: track.rotation.z.getValue(row) || 0
                    },
                    alpha: {
                        value: track.alpha.value.getValue(row) || 0
                    } 
                }
            }
            else if(track.type == "camera") {
                return {
                    position: {
                        x: track.position.x.getValue(row) || 0,
                        y: track.position.y.getValue(row) || 0,
                        z: track.position.z.getValue(row) || 0
                    },
                    scale: {
                        x: track.scale.x.getValue(row) || 0,
                        y: track.scale.y.getValue(row) || 0,
                        z: track.scale.z.getValue(row) || 0
                    },
                    rotation: {
                        x: track.rotation.x.getValue(row) || 0,
                        y: track.rotation.y.getValue(row) || 0,
                        z: track.rotation.z.getValue(row) || 0
                    },
                    look: {
                        x: track.look.x.getValue(row) || 0,
                        y: track.look.y.getValue(row) || 0,
                        z: track.look.z.getValue(row) || 0
                    },
                }
            }
            else if(track.type == "march") {
                return {
                    position: {
                        x: track.position.x.getValue(row) || 0,
                        y: track.position.y.getValue(row) || 0,
                        z: track.position.z.getValue(row) || 0
                    },
                    rotation: {
                        x: track.rotation.x.getValue(row) || 0,
                        y: track.rotation.y.getValue(row) || 0,
                        z: track.rotation.z.getValue(row) || 0
                    },
                    color: {
                        r: track.color.r.getValue(row) || 0,
                        g: track.color.g.getValue(row) || 0,
                        b: track.color.b.getValue(row) || 0
                    },
                    fov: {
                        value: track.fov.value.getValue(row) || 0
                    },
                    alpha: {
                        value: track.alpha.value.getValue(row) || 0
                    },
                    dist: {
                        value: track.dist.value.getValue(row) || 0
                    },
                    darkness: {
                        value: track.darkness.value.getValue(row) || 0
                    },
                    modifier: {
                        value: track.modifier.value.getValue(row) || 0
                    },
                    enabled: {
                        value: track.enabled.value.getValue(row) || 0
                    }
                }
            }
            else if(track.type == "onlycode") {
                return {
                    position: {
                        x: track.position.x.getValue(row) || 0,
                        y: track.position.y.getValue(row) || 0,
                        z: track.position.z.getValue(row) || 0
                    },
                    scale: {
                        x: track.scale.x.getValue(row) || 0,
                        y: track.scale.y.getValue(row) || 0,
                        z: track.scale.z.getValue(row) || 0
                    },
                    rotation: {
                        x: track.rotation.x.getValue(row) || 0,
                        y: track.rotation.y.getValue(row) || 0,
                        z: track.rotation.z.getValue(row) || 0
                    },
                    color: {
                        r: track.color.r.getValue(row) || 0,
                        g: track.color.g.getValue(row) || 0,
                        b: track.color.b.getValue(row) || 0
                    },
                    alpha: {
                        value: track.alpha.value.getValue(row) || 0
                    } 
                }
            }
            else if(track.type == "gods") {
                return {
                    position: {
                        x: track.position.x.getValue(row) || 0,
                        y: track.position.y.getValue(row) || 0,
                        z: track.position.z.getValue(row) || 0
                    },
                    scale: {
                        x: track.scale.x.getValue(row) || 0,
                        y: track.scale.y.getValue(row) || 0,
                        z: track.scale.z.getValue(row) || 0
                    },
                    rotation: {
                        x: track.rotation.x.getValue(row) || 0,
                        y: track.rotation.y.getValue(row) || 0,
                        z: track.rotation.z.getValue(row) || 0
                    },
                    color: {
                        r: track.color.r.getValue(row) || 0,
                        g: track.color.g.getValue(row) || 0,
                        b: track.color.b.getValue(row) || 0
                    },
                    alpha: {
                        value: track.alpha.value.getValue(row) || 0
                    } 
                }
            }
            else if(track.type == "synth") {
                return {
                    position: {
                        x: track.position.x.getValue(row) || 0,
                        y: track.position.y.getValue(row) || 0,
                        z: track.position.z.getValue(row) || 0
                    },
                    scale: {
                        x: track.scale.x.getValue(row) || 0,
                        y: track.scale.y.getValue(row) || 0,
                        z: track.scale.z.getValue(row) || 0
                    },
                    rotation: {
                        x: track.rotation.x.getValue(row) || 0,
                        y: track.rotation.y.getValue(row) || 0,
                        z: track.rotation.z.getValue(row) || 0
                    },
                    color: {
                        r: track.color.r.getValue(row) || 0,
                        g: track.color.g.getValue(row) || 0,
                        b: track.color.b.getValue(row) || 0
                    },
                    alpha: {
                        value: track.alpha.value.getValue(row) || 0
                    } 
                }
            }
            else if(track.type == "darkness") {
                return {
                    position: {
                        x: track.position.x.getValue(row) || 0,
                        y: track.position.y.getValue(row) || 0,
                        z: track.position.z.getValue(row) || 0
                    },
                    scale: {
                        x: track.scale.x.getValue(row) || 0,
                        y: track.scale.y.getValue(row) || 0,
                        z: track.scale.z.getValue(row) || 0
                    },
                    rotation: {
                        x: track.rotation.x.getValue(row) || 0,
                        y: track.rotation.y.getValue(row) || 0,
                        z: track.rotation.z.getValue(row) || 0
                    },
                    color: {
                        r: track.color.r.getValue(row) || 0,
                        g: track.color.g.getValue(row) || 0,
                        b: track.color.b.getValue(row) || 0
                    },
                    alpha: {
                        value: track.alpha.value.getValue(row) || 0
                    } 
                }
            }
            else if(track.type == "gfx") {
                return {
                    position: {
                        x: track.position.x.getValue(row) || 0,
                        y: track.position.y.getValue(row) || 0,
                        z: track.position.z.getValue(row) || 0
                    },
                    scale: {
                        x: track.scale.x.getValue(row) || 0,
                        y: track.scale.y.getValue(row) || 0,
                        z: track.scale.z.getValue(row) || 0
                    },
                    rotation: {
                        x: track.rotation.x.getValue(row) || 0,
                        y: track.rotation.y.getValue(row) || 0,
                        z: track.rotation.z.getValue(row) || 0
                    },
                    color: {
                        r: track.color.r.getValue(row) || 0,
                        g: track.color.g.getValue(row) || 0,
                        b: track.color.b.getValue(row) || 0
                    },
                    alpha: {
                        value: track.alpha.value.getValue(row) || 0
                    } 
                }
            }
            else if(track.type == "code") {
                return {
                    position: {
                        x: track.position.x.getValue(row) || 0,
                        y: track.position.y.getValue(row) || 0,
                        z: track.position.z.getValue(row) || 0
                    },
                    scale: {
                        x: track.scale.x.getValue(row) || 0,
                        y: track.scale.y.getValue(row) || 0,
                        z: track.scale.z.getValue(row) || 0
                    },
                    rotation: {
                        x: track.rotation.x.getValue(row) || 0,
                        y: track.rotation.y.getValue(row) || 0,
                        z: track.rotation.z.getValue(row) || 0
                    },
                    color: {
                        r: track.color.r.getValue(row) || 0,
                        g: track.color.g.getValue(row) || 0,
                        b: track.color.b.getValue(row) || 0
                    },
                    alpha: {
                        value: track.alpha.value.getValue(row) || 0
                    } 
                }
            }
            else if(track.type == "music") {
                return {
                    position: {
                        x: track.position.x.getValue(row) || 0,
                        y: track.position.y.getValue(row) || 0,
                        z: track.position.z.getValue(row) || 0
                    },
                    scale: {
                        x: track.scale.x.getValue(row) || 0,
                        y: track.scale.y.getValue(row) || 0,
                        z: track.scale.z.getValue(row) || 0
                    },
                    rotation: {
                        x: track.rotation.x.getValue(row) || 0,
                        y: track.rotation.y.getValue(row) || 0,
                        z: track.rotation.z.getValue(row) || 0
                    },
                    color: {
                        r: track.color.r.getValue(row) || 0,
                        g: track.color.g.getValue(row) || 0,
                        b: track.color.b.getValue(row) || 0
                    },
                    alpha: {
                        value: track.alpha.value.getValue(row) || 0
                    } 
                }
            }
            else if(track.type == "common") {
                return {
                    time: {
                        value: track.time.value.getValue(row) || 0
                    }
                }
            }
    
        }
    },

    this.prepare = function() {
        if(settings.release) {
            this.device.setConfig({
                rocketXML: "assets/music/simulaatio8.rocket"
            });
            this.device.init("demo");
        }
        else {
            this.device.setConfig({
                socketURL:'ws://localhost:1339'
            });
            this.device.init();
        }
   
        this.device.on("ready", this.ready.bind(this));
        this.device.on("update", this.update.bind(this));
        this.device.on("play", this.play.bind(this));
        this.device.on("pause", this.pause.bind(this));
    },

    this.loadMusic = function() {
        this.music.src = "assets/music/simulaatio8fadeout.ogg",
        this.music.load();
        this.music.preload = true;
        this.music.addEventListener("canplay", this.canPlay.bind(this));
    },

    this.canPlay = function() {
        if(this.musicReady) {
            return;
        }  
        if(settings.release) { 
            render();
            this.music.play();
        } else {
            this.music.pause();
            this.music.currentTime = sync.row / sync.ROW_RATE;
        }
        this.musicReady = true;
       
    },
    this.ready = function() {
        this.tracks.init(this.device);
        //this.loadMusic();
    },
    this.update = function(row) {
        if (!isNaN(row)) {
            this.row = row;
            this.music.currentTime = this.row / this.ROW_RATE;
        }
        render();
    },
    this.play = function() {
        this.music.currentTime = this.row / this.ROW_RATE;
        this.music.play();
        render();
    },
    this.pause = function() {
        this.row = this.music.currentTime * this.ROW_RATE;
        window.cancelAnimationFrame(render, document);
        this.music.pause();
    }
};

var Universe = function() {
    this.screen = {
        width: window.innerWidth,
        height: window.innerHeight,
        renderer: null,
    },
    this.observer = {
        camera: null,
        target: null,
    },
    this.time = {
        delta: 0,
        time: 0,
        frameStart: 0,
        update: function() {
            var c = new Date().getTime();
            if(this.frameStart > 0)
                this.delta = c - this.frameStart;
            this.time += this.delta;

            this.frameStart = c;
        }
    },
    this.world = {
        scene: null
    }
    this.render = function() {
        this.screen.renderer.render(this.world.scene, this.observer.camera);
    },
    this.update = function() {

    }
};

var sync = new Sync();
var universe = new Universe();
var controls = null;

var logoUniforms = null;
var mixer = null;
var cameraLight = null;
var directionalLight = null;


var floor = {
    uniforms: null,
    material: null,
    geometry: null,
    mesh: null,  
};

var ceiling = {
    uniforms: null,
    material: null,
    geometry: null,
    mesh: null,  
};

var logo = {
    uniforms: null,
    material: null,
    geometry: null,
    mesh: null,
    texture: null
};

var march = {
    uniforms: null,
    material: null,
    geometry: null,
    mesh: null
};

var shaders = {
    
};
shaders["simple-vertex"] = {
    url: "assets/shaders/simple-vertex.glsl",
    content: ""
};
shaders["marching"] = {
    url: "assets/shaders/marching.glsl",
    content: ""
};
shaders["image"] = {
    url: "assets/shaders/image.glsl",
    content: ""
};
shaders["wormy"] = {
    url: "assets/shaders/wormy.glsl",
    content: ""
};
shaders["text"] = {
    url: "assets/shaders/text.glsl",
    content: ""
};


var texts = {
    onlycode: {
        uniforms: null,
        material: null,
        geometry: null,
        mesh: null,
        texture: null
    },
    gods: {
        uniforms: null,
        material: null,
        geometry: null,
        mesh: null,
        texture: null
    },
    darkness: {
        uniforms: null,
        material: null,
        geometry: null,
        mesh: null,
        texture: null
    },
    synth: {
        uniforms: null,
        material: null,
        geometry: null,
        mesh: null,
        texture: null
    },
    gfx: {
        uniforms: null,
        material: null,
        geometry: null,
        mesh: null,
        texture: null
    },
    code: {
        uniforms: null,
        material: null,
        geometry: null,
        mesh: null,
        texture: null
    },
    music: {
        uniforms: null,
        material: null,
        geometry: null,
        mesh: null,
        texture: null
    },
}
function initialize() {
    
    for(var name in shaders) {
        var shader = shaders[name];
        (function(s) {
            $.ajax({
                url: s.url,
                type: "get",
                async: false,
                success: function(data) {
                    s.content = data;
                }
            });
           
        }(shader));
        
    }
    universe.screen.renderer = new THREE.WebGLRenderer();
    universe.screen.renderer.autoClear = false;
    universe.screen.width = window.innerWidth;
    universe.screen.height = window.innerHeight;
    universe.screen.renderer.setSize(universe.screen.width, universe.screen.height);
    document.body.appendChild(universe.screen.renderer.domElement);
    
    universe.world.scene = new THREE.Scene();
    universe.world.scene.fog = new THREE.FogExp2( 0xefd1b5, 0.0025 );
    universe.observer.camera = new THREE.PerspectiveCamera(75, universe.screen.width / universe.screen.height, 0.01, 1000 );   

    universe.world.scene.add(universe.observer.camera);
    controls = new THREE.OrbitControls(universe.observer.camera);


    sync.prepare();
    sync.loadMusic();

    logo.texture = new THREE.TextureLoader().load("assets/graphics/Tahtituho_v4_kirjaimet.png");
    logo.texture.wrapS = logo.texture.wrapT = THREE.RepeatWrapping;

    logo.uniforms = THREE.UniformsUtils.merge([
        THREE.UniformsLib["common"],
        THREE.UniformsLib["lights"]
    ]);


    logo.uniforms["resolution"] = {
        value: new THREE.Vector2(universe.screen.width, universe.screen.height)
    };
    logo.uniforms["hPos"] = {
        value: 0.0
    };
    logo.uniforms["width"] = {
        value: 0.0
    };
    logo.uniforms["color"] = {
        value: new THREE.Vector3(1.0, 1.0, 1.0)
    };
    logo.uniforms["alpha"] = {
        value: 1.0
    };
    logo.uniforms["enabled"] = {
        value: 0.0
    };
    logo.uniforms["texture"] = {
        value: logo.texture
    };
    logo.uniforms["time"] = {
        value: 0.0
    };
    
    logo.material = new THREE.ShaderMaterial({
        uniforms:       logo.uniforms,
        vertexShader:   shaders["simple-vertex"].content,
        fragmentShader: shaders["image"].content,
        depthTest:      true,
        transparent:    true,
        wireframe:      false,
        lights:         false,

    });

    logo.geometry = new THREE.PlaneGeometry(5.0, 5.0, 320, 320);
    logo.mesh = new THREE.Mesh(logo.geometry, logo.material);
  

    universe.world.scene.add(logo.mesh);

    texts.onlycode.texture = new THREE.TextureLoader().load("assets/graphics/onlycode.png");
    texts.onlycode.texture.wrapS = texts.onlycode.texture.wrapT = THREE.RepeatWrapping;

    texts.onlycode.uniforms = THREE.UniformsUtils.merge([
        THREE.UniformsLib["common"]
    ]);

    texts.onlycode.uniforms["color"] = {
        value: new THREE.Vector3(1.0, 1.0, 1.0)
    };
    texts.onlycode.uniforms["alpha"] = {
        value: 1.0
    };
    texts.onlycode.uniforms["texture"] = {
        value: texts.onlycode.texture
    };
    texts.onlycode.uniforms["time"] = {
        value: 0.0
    };

    texts.onlycode.material = new THREE.ShaderMaterial({
        uniforms:       texts.onlycode.uniforms,
        vertexShader:   shaders["simple-vertex"].content,
        fragmentShader: shaders["text"].content,
        depthTest:      true,
        transparent:    true,
        wireframe:      false,
        lights:         false,

    });

    texts.onlycode.geometry = new THREE.PlaneGeometry(2.0, 2.0, 32, 32);
    texts.onlycode.mesh = new THREE.Mesh(texts.onlycode.geometry, texts.onlycode.material);

    universe.world.scene.add(texts.onlycode.mesh);

    texts.gods.texture = new THREE.TextureLoader().load("assets/graphics/gods.png");
    texts.gods.texture.wrapS = texts.gods.texture.wrapT = THREE.RepeatWrapping;

    texts.gods.uniforms = THREE.UniformsUtils.merge([
        THREE.UniformsLib["common"]
    ]);

    texts.gods.uniforms["color"] = {
        value: new THREE.Vector3(1.0, 1.0, 1.0)
    };
    texts.gods.uniforms["alpha"] = {
        value: 1.0
    };
    texts.gods.uniforms["texture"] = {
        value: texts.gods.texture
    };
    texts.gods.uniforms["time"] = {
        value: 0.0
    };

    texts.gods.material = new THREE.ShaderMaterial({
        uniforms:       texts.gods.uniforms,
        vertexShader:   shaders["simple-vertex"].content,
        fragmentShader: shaders["text"].content,
        depthTest:      true,
        transparent:    true,
        wireframe:      false,
        lights:         false,

    });

    texts.gods.geometry = new THREE.PlaneGeometry(2.0, 2.0, 32, 32);
    texts.gods.mesh = new THREE.Mesh(texts.gods.geometry, texts.gods.material);

    universe.world.scene.add(texts.gods.mesh);

    texts.synth.texture = new THREE.TextureLoader().load("assets/graphics/synth.png");
    texts.synth.texture.wrapS = texts.synth.texture.wrapT = THREE.RepeatWrapping;

    texts.synth.uniforms = THREE.UniformsUtils.merge([
        THREE.UniformsLib["common"]
    ]);

    texts.synth.uniforms["color"] = {
        value: new THREE.Vector3(1.0, 1.0, 1.0)
    };
    texts.synth.uniforms["alpha"] = {
        value: 1.0
    };
    texts.synth.uniforms["texture"] = {
        value: texts.synth.texture
    };
    texts.synth.uniforms["time"] = {
        value: 0.0
    };

    texts.synth.material = new THREE.ShaderMaterial({
        uniforms:       texts.synth.uniforms,
        vertexShader:   shaders["simple-vertex"].content,
        fragmentShader: shaders["text"].content,
        depthTest:      true,
        transparent:    true,
        wireframe:      false,
        lights:         false,

    });

    texts.synth.geometry = new THREE.PlaneGeometry(2.0, 2.0, 32, 32);
    texts.synth.mesh = new THREE.Mesh(texts.synth.geometry, texts.synth.material);

    universe.world.scene.add(texts.synth.mesh);

    texts.darkness.texture = new THREE.TextureLoader().load("assets/graphics/darkness.png");
    texts.darkness.texture.wrapS = texts.darkness.texture.wrapT = THREE.RepeatWrapping;

    texts.darkness.uniforms = THREE.UniformsUtils.merge([
        THREE.UniformsLib["common"]
    ]);

    texts.darkness.uniforms["color"] = {
        value: new THREE.Vector3(1.0, 1.0, 1.0)
    };
    texts.darkness.uniforms["alpha"] = {
        value: 1.0
    };
    texts.darkness.uniforms["texture"] = {
        value: texts.darkness.texture
    };
    texts.darkness.uniforms["time"] = {
        value: 0.0
    };

    texts.darkness.material = new THREE.ShaderMaterial({
        uniforms:       texts.darkness.uniforms,
        vertexShader:   shaders["simple-vertex"].content,
        fragmentShader: shaders["text"].content,
        depthTest:      true,
        transparent:    true,
        wireframe:      false,
        lights:         false,

    });

    texts.darkness.geometry = new THREE.PlaneGeometry(2.0, 2.0, 32, 32);
    texts.darkness.mesh = new THREE.Mesh(texts.darkness.geometry, texts.darkness.material);

    universe.world.scene.add(texts.darkness.mesh)

    texts.gfx.texture = new THREE.TextureLoader().load("assets/graphics/gfx.png");
    texts.gfx.texture.wrapS = texts.gfx.texture.wrapT = THREE.RepeatWrapping;

    texts.gfx.uniforms = THREE.UniformsUtils.merge([
        THREE.UniformsLib["common"]
    ]);

    texts.gfx.uniforms["color"] = {
        value: new THREE.Vector3(1.0, 1.0, 1.0)
    };
    texts.gfx.uniforms["alpha"] = {
        value: 1.0
    };
    texts.gfx.uniforms["texture"] = {
        value: texts.gfx.texture
    };

    texts.gfx.material = new THREE.ShaderMaterial({
        uniforms:       texts.gfx.uniforms,
        vertexShader:   shaders["simple-vertex"].content,
        fragmentShader: shaders["text"].content,
        depthTest:      true,
        transparent:    true,
        wireframe:      false,
        lights:         false,

    });

    texts.gfx.geometry = new THREE.PlaneGeometry(2.0, 2.0, 32, 32);
    texts.gfx.mesh = new THREE.Mesh(texts.gfx.geometry, texts.gfx.material);

    universe.world.scene.add(texts.gfx.mesh);

    texts.code.texture = new THREE.TextureLoader().load("assets/graphics/code.png");
    texts.code.texture.wrapS = texts.code.texture.wrapT = THREE.RepeatWrapping;

    texts.code.uniforms = THREE.UniformsUtils.merge([
        THREE.UniformsLib["common"]
    ]);

    texts.code.uniforms["color"] = {
        value: new THREE.Vector3(1.0, 1.0, 1.0)
    };
    texts.code.uniforms["alpha"] = {
        value: 1.0
    };
    texts.code.uniforms["texture"] = {
        value: texts.code.texture
    };

    texts.code.material = new THREE.ShaderMaterial({
        uniforms:       texts.code.uniforms,
        vertexShader:   shaders["simple-vertex"].content,
        fragmentShader: shaders["text"].content,
        depthTest:      true,
        transparent:    true,
        wireframe:      false,
        lights:         false,

    });

    texts.code.geometry = new THREE.PlaneGeometry(2.0, 2.0, 32, 32);
    texts.code.mesh = new THREE.Mesh(texts.code.geometry, texts.code.material);

    universe.world.scene.add(texts.code.mesh);

    texts.music.texture = new THREE.TextureLoader().load("assets/graphics/music.png");
    texts.music.texture.wrapS = texts.music.texture.wrapT = THREE.RepeatWrapping;

    texts.music.uniforms = THREE.UniformsUtils.merge([
        THREE.UniformsLib["common"]
    ]);

    texts.music.uniforms["color"] = {
        value: new THREE.Vector3(1.0, 1.0, 1.0)
    };
    texts.music.uniforms["alpha"] = {
        value: 1.0
    };
    texts.music.uniforms["texture"] = {
        value: texts.music.texture
    };

    texts.music.material = new THREE.ShaderMaterial({
        uniforms:       texts.music.uniforms,
        vertexShader:   shaders["simple-vertex"].content,
        fragmentShader: shaders["text"].content,
        depthTest:      true,
        transparent:    true,
        wireframe:      false,
        lights:         false,

    });

    texts.music.geometry = new THREE.PlaneGeometry(2.0, 2.0, 32, 32);
    texts.music.mesh = new THREE.Mesh(texts.music.geometry, texts.music.material);

    universe.world.scene.add(texts.music.mesh);

    floor.uniforms = THREE.UniformsUtils.merge([
        THREE.UniformsLib["common"],
    ]);

    floor.uniforms["time"] = {
        value: 0.0
    };

    floor.uniforms["scale"] = {
        value: 1.6
    };
    floor.uniforms["displacement"] = {
        value: 0.0
    };
    floor.uniforms["alpha"] = {
        value: 0.0
    };

    floor.geometry = new THREE.PlaneGeometry(1000.0, 1000.0, 200.0, 200.0);
    floor.material = new THREE.ShaderMaterial( {
		uniforms:       floor.uniforms,
		vertexShader:   shaders["simple-vertex"].content,
		fragmentShader: shaders["wormy"].content,
		depthTest:      true,
		transparent:    true,
        wireframe:      false

    });

    floor.mesh = new THREE.Mesh(floor.geometry, floor.material);
    universe.world.scene.add(floor.mesh);

    ceiling.uniforms = THREE.UniformsUtils.merge([
        THREE.UniformsLib["common"],
    ]);
    ceiling.uniforms["time"] = {
        value: 0.0
    };

    ceiling.uniforms["scale"] = {
        value: 1.6
    };

    ceiling.uniforms["displacement"] = {
        value: 0.0
    };
    ceiling.uniforms["alpha"] = {
        value: 0.0
    };

    ceiling.geometry = new THREE.PlaneGeometry(1000.0, 1000.0, 200.0, 200.0);
    ceiling.material = new THREE.ShaderMaterial( {
		uniforms:       ceiling.uniforms,
		vertexShader:   shaders["simple-vertex"].content,
		fragmentShader: shaders["wormy"].content,
		depthTest:      true,
		transparent:    true,
        wireframe:      false

    });

    ceiling.mesh = new THREE.Mesh(ceiling.geometry, ceiling.material);
    universe.world.scene.add(ceiling.mesh);

    march.geometry = new THREE.PlaneBufferGeometry(500, 500, 250, 250);

    march.uniforms = THREE.UniformsUtils.merge([
        THREE.UniformsLib["common"]
    ]);

    march.uniforms["resolution"] = {
        value: new THREE.Vector2(universe.screen.width, universe.screen.height)
    };
    march.uniforms["fov"] = {
        value: 1.0
    };
    march.uniforms["cPosition"] = {
        value: new THREE.Vector3(0.0, 0.0, 0.0)
    };
    march.uniforms["rotation"] = {
        value: new THREE.Vector3(0.0, 0.0, 0.0)
    };
    march.uniforms["color"] = {
        value: new THREE.Vector3(0.2, 0.4, 0.2)
    };
    march.uniforms["time"] = {
        value: 0.0
    };
    march.uniforms["alpha"] = {
        value: 1.0
    };
    march.uniforms["dist"] = {
        value: 1.0
    };
    march.uniforms["darkness"] = {
        value: 0.7
    };
    march.uniforms["modifier"] = {
        value: 0.7
    };
    march.uniforms["enabled"] = {
        value: 1.0
    };
    march.material = new THREE.ShaderMaterial( {
		uniforms:       march.uniforms,
		vertexShader:   shaders["simple-vertex"].content,
		fragmentShader: shaders["marching"].content,

		blending:       THREE.AdditiveBlending,
		depthTest:      true,
		transparent:    true,
        wireframe:      false,
        lights:         false,

    });
    
    march.mesh = new THREE.Mesh(march.geometry, march.material);

    march.mesh.position.z = -5.0;
    universe.world.scene.add(march.mesh);

}

function render() {
    universe.time.update();
    var time = universe.time.time / 500.0;
    if(sync.music.paused === false) {
        //only update the row in Rocket when the demo is playing
        sync.row = sync.music.currentTime * sync.ROW_RATE;
        sync.device.update(sync.row);
    }
    


    if(settings.release === true  ||  settings.sync === true) {  
        
        var cameraSync = sync.tracks.get("camera", sync.row);
        universe.observer.camera.position.x = cameraSync.position.x;
        universe.observer.camera.position.y = cameraSync.position.y;
        universe.observer.camera.position.z = cameraSync.position.z;

        universe.observer.camera.rotation.x = THREE.Math.degToRad(cameraSync.rotation.x);
        universe.observer.camera.rotation.y = THREE.Math.degToRad(cameraSync.rotation.y);
        universe.observer.camera.rotation.z = THREE.Math.degToRad(cameraSync.rotation.z);
        
    }
    else {
        controls.update();
    }
    controls.update();
    if(settings.sync || settings.release) {
        var commonSync = sync.tracks.get("common", sync.row);
        time = commonSync.time.value;

        var floorSync = sync.tracks.get("floor", sync.row);
        floor.mesh.position.x = floorSync.position.x;
        floor.mesh.position.y = floorSync.position.y;
        floor.mesh.position.z = floorSync.position.z;
    
        floor.mesh.scale.x = floorSync.scale.x;
        floor.mesh.scale.y = floorSync.scale.y;
        floor.mesh.scale.z = floorSync.scale.z;
    
        floor.mesh.rotation.x = THREE.Math.degToRad(floorSync.rotation.x);
        floor.mesh.rotation.y = THREE.Math.degToRad(floorSync.rotation.y);
        floor.mesh.rotation.z = THREE.Math.degToRad(floorSync.rotation.z);

        floor.uniforms["alpha"].value = floorSync.alpha.value;

        ceiling.mesh.position.x = floorSync.position.x;
        ceiling.mesh.position.y = -floorSync.position.y;
        ceiling.mesh.position.z = floorSync.position.z;
    
        ceiling.mesh.scale.x = floorSync.scale.x;
        ceiling.mesh.scale.y = floorSync.scale.y;
        ceiling.mesh.scale.z = floorSync.scale.z;
    
        ceiling.mesh.rotation.x = THREE.Math.degToRad(-floorSync.rotation.x);
        ceiling.mesh.rotation.y = THREE.Math.degToRad(-floorSync.rotation.y);
        ceiling.mesh.rotation.z = THREE.Math.degToRad(-floorSync.rotation.z);

        ceiling.uniforms["alpha"].value = floorSync.alpha.value;

        var logoSync = sync.tracks.get("logo", sync.row);
        logo.mesh.position.x = logoSync.position.x;
        logo.mesh.position.y = logoSync.position.y;
        logo.mesh.position.z = logoSync.position.z;
    
        logo.mesh.scale.x = logoSync.scale.x;
        logo.mesh.scale.y = logoSync.scale.y;
        logo.mesh.scale.z = logoSync.scale.z;
    
        logo.mesh.rotation.x = THREE.Math.degToRad(logoSync.rotation.x);
        logo.mesh.rotation.y = THREE.Math.degToRad(logoSync.rotation.y);
        logo.mesh.rotation.z = THREE.Math.degToRad(logoSync.rotation.z);

        logo.uniforms["alpha"].value = logoSync.alpha.value;
        logo.uniforms["color"].value = new THREE.Vector3(logoSync.color.r, logoSync.color.g, logoSync.color.b);
        logo.uniforms["enabled"].value = logoSync.enabled.value;

        var marchSync = sync.tracks.get("march", sync.row);
        march.uniforms["cPosition"].value = new THREE.Vector3(marchSync.position.x, marchSync.position.y, marchSync.position.z);
        march.uniforms["rotation"].value = new THREE.Vector3(marchSync.rotation.x, marchSync.rotation.y, marchSync.rotation.z);
        march.uniforms["fov"].value = marchSync.fov.value;
        march.uniforms["color"].value = new THREE.Vector3(marchSync.color.r, marchSync.color.g, marchSync.color.b);
        march.uniforms["alpha"].value = marchSync.alpha.value;
        march.uniforms["dist"].value = marchSync.dist.value;
        march.uniforms["darkness"].value = marchSync.darkness.value;
        march.uniforms["modifier"].value = marchSync.modifier.value;
        march.uniforms["enabled"].value = marchSync.enabled.value;

        var onlycodeSync = sync.tracks.get("onlycode", sync.row);
        texts.onlycode.mesh.position.x = onlycodeSync.position.x;
        texts.onlycode.mesh.position.y = onlycodeSync.position.y;
        texts.onlycode.mesh.position.z = onlycodeSync.position.z;
    
        texts.onlycode.mesh.scale.x = onlycodeSync.scale.x;
        texts.onlycode.mesh.scale.y = onlycodeSync.scale.y;
        texts.onlycode.mesh.scale.z = onlycodeSync.scale.z;
    
        texts.onlycode.mesh.rotation.x = THREE.Math.degToRad(onlycodeSync.rotation.x);
        texts.onlycode.mesh.rotation.y = THREE.Math.degToRad(onlycodeSync.rotation.y);
        texts.onlycode.mesh.rotation.z = THREE.Math.degToRad(onlycodeSync.rotation.z);

        texts.onlycode.uniforms["alpha"].value = onlycodeSync.alpha.value;
        texts.onlycode.uniforms["color"].value = new THREE.Vector3(onlycodeSync.color.r, onlycodeSync.color.g, onlycodeSync.color.b);
    
        var godsSync = sync.tracks.get("gods", sync.row);
        texts.gods.mesh.position.x = godsSync.position.x;
        texts.gods.mesh.position.y = godsSync.position.y;
        texts.gods.mesh.position.z = godsSync.position.z;
    
        texts.gods.mesh.scale.x = godsSync.scale.x;
        texts.gods.mesh.scale.y = godsSync.scale.y;
        texts.gods.mesh.scale.z = godsSync.scale.z;
    
        texts.gods.mesh.rotation.x = THREE.Math.degToRad(godsSync.rotation.x);
        texts.gods.mesh.rotation.y = THREE.Math.degToRad(godsSync.rotation.y);
        texts.gods.mesh.rotation.z = THREE.Math.degToRad(godsSync.rotation.z);

        texts.gods.uniforms["alpha"].value = godsSync.alpha.value;
        texts.gods.uniforms["color"].value = new THREE.Vector3(godsSync.color.r, godsSync.color.g, godsSync.color.b);

        var darknessSync = sync.tracks.get("darkness", sync.row);
        texts.darkness.mesh.position.x = darknessSync.position.x;
        texts.darkness.mesh.position.y = darknessSync.position.y;
        texts.darkness.mesh.position.z = darknessSync.position.z;
    
        texts.darkness.mesh.scale.x = darknessSync.scale.x;
        texts.darkness.mesh.scale.y = darknessSync.scale.y;
        texts.darkness.mesh.scale.z = darknessSync.scale.z;
    
        texts.darkness.mesh.rotation.x = THREE.Math.degToRad(darknessSync.rotation.x);
        texts.darkness.mesh.rotation.y = THREE.Math.degToRad(darknessSync.rotation.y);
        texts.darkness.mesh.rotation.z = THREE.Math.degToRad(darknessSync.rotation.z);

        texts.darkness.uniforms["alpha"].value = darknessSync.alpha.value;
        texts.darkness.uniforms["color"].value = new THREE.Vector3(darknessSync.color.r, darknessSync.color.g, darknessSync.color.b);

        var synthSync = sync.tracks.get("synth", sync.row);
        texts.synth.mesh.position.x = synthSync.position.x;
        texts.synth.mesh.position.y = synthSync.position.y;
        texts.synth.mesh.position.z = synthSync.position.z;
    
        texts.synth.mesh.scale.x = synthSync.scale.x;
        texts.synth.mesh.scale.y = synthSync.scale.y;
        texts.synth.mesh.scale.z = synthSync.scale.z;
    
        texts.synth.mesh.rotation.x = THREE.Math.degToRad(synthSync.rotation.x);
        texts.synth.mesh.rotation.y = THREE.Math.degToRad(synthSync.rotation.y);
        texts.synth.mesh.rotation.z = THREE.Math.degToRad(synthSync.rotation.z);

        texts.synth.uniforms["alpha"].value = synthSync.alpha.value;
        texts.synth.uniforms["color"].value = new THREE.Vector3(synthSync.color.r, synthSync.color.g, synthSync.color.b);

        var codeSync = sync.tracks.get("code", sync.row);
        texts.code.mesh.position.x = codeSync.position.x;
        texts.code.mesh.position.y = codeSync.position.y;
        texts.code.mesh.position.z = codeSync.position.z;
    
        texts.code.mesh.scale.x = codeSync.scale.x;
        texts.code.mesh.scale.y = codeSync.scale.y;
        texts.code.mesh.scale.z = codeSync.scale.z;
    
        texts.code.mesh.rotation.x = THREE.Math.degToRad(codeSync.rotation.x);
        texts.code.mesh.rotation.y = THREE.Math.degToRad(codeSync.rotation.y);
        texts.code.mesh.rotation.z = THREE.Math.degToRad(codeSync.rotation.z);

        texts.code.uniforms["alpha"].value = codeSync.alpha.value;
        texts.code.uniforms["color"].value = new THREE.Vector3(codeSync.color.r, codeSync.color.g, codeSync.color.b);

        var musicSync = sync.tracks.get("music", sync.row);
        texts.music.mesh.position.x = musicSync.position.x;
        texts.music.mesh.position.y = musicSync.position.y;
        texts.music.mesh.position.z = musicSync.position.z;
    
        texts.music.mesh.scale.x = musicSync.scale.x;
        texts.music.mesh.scale.y = musicSync.scale.y;
        texts.music.mesh.scale.z = musicSync.scale.z;
    
        texts.music.mesh.rotation.x = THREE.Math.degToRad(musicSync.rotation.x);
        texts.music.mesh.rotation.y = THREE.Math.degToRad(musicSync.rotation.y);
        texts.music.mesh.rotation.z = THREE.Math.degToRad(musicSync.rotation.z);

        texts.music.uniforms["alpha"].value = musicSync.alpha.value;
        texts.music.uniforms["color"].value = new THREE.Vector3(musicSync.color.r, musicSync.color.g, musicSync.color.b);

        var gfxSync = sync.tracks.get("gfx", sync.row);
        texts.gfx.mesh.position.x = gfxSync.position.x;
        texts.gfx.mesh.position.y = gfxSync.position.y;
        texts.gfx.mesh.position.z = gfxSync.position.z;
    
        texts.gfx.mesh.scale.x = gfxSync.scale.x;
        texts.gfx.mesh.scale.y = gfxSync.scale.y;
        texts.gfx.mesh.scale.z = gfxSync.scale.z;
    
        texts.gfx.mesh.rotation.x = THREE.Math.degToRad(gfxSync.rotation.x);
        texts.gfx.mesh.rotation.y = THREE.Math.degToRad(gfxSync.rotation.y);
        texts.gfx.mesh.rotation.z = THREE.Math.degToRad(gfxSync.rotation.z);

        texts.gfx.uniforms["alpha"].value = gfxSync.alpha.value;
        texts.gfx.uniforms["color"].value = new THREE.Vector3(gfxSync.color.r, gfxSync.color.g, gfxSync.color.b);
    }

    floor.uniforms["time"].value = time;
    ceiling.uniforms["time"].value = time + 200.0;
    logo.uniforms["time"].value = time;
    march.uniforms["time"].value = time;
    texts.gods.uniforms["time"].value = time;
    texts.darkness.uniforms["time"].value = time;
    texts.onlycode.uniforms["time"].value = time;
    texts.synth.uniforms["time"].value = time;
    //floor.material.opacity = floorSync.material.alpha;

    universe.update();
    universe.render();


    if((settings.release === true)  || (sync.music.paused === false || settings.sync === false)) {
        window.requestAnimationFrame(render);
    }
    else {
        window.cancelAnimationFrame(render);
    }
}





