07-controls-motion-detection.html


<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
	<title>The Five Planets</title>
	<meta http-equiv="content-type" content="text/html;charset=utf-8" />
	<style>
        body {
			width:100%;
			height:100%;
			padding:0;
            margin:0;
            overflow:hidden;
        }
    </style>
	<link rel="stylesheet" type="text/css" href="../css/screen.css"/>
	<link rel="stylesheet" type="text/css" href="../css/ui.css"/>
	
	<!-- LOAD JQUERY & REQUIERE -->
	<script src="../frameworks/require.min.js"></script>
    <script src="../frameworks/jquery-2.0.3.min.js"></script>
	<script src="../core/ui/ui_v01.js" defer></script>
	
	<!-- LOAD THREE.JS -->
    <script src="../frameworks/three.js" defer></script>
	<script src="../frameworks/renders/projector.js" defer></script>
    <script src="../frameworks/loaders/DDSLoader.js" defer></script>
	<script src="../frameworks/loaders/MTLLoader.js" defer></script>
	<script src="../frameworks/loaders/OBJLoader.js" defer></script>
	<script src="../frameworks/loaders/ColladaLoader.js" defer></script>
	<script src="../frameworks/loaders/collada/Animation.js" defer></script>
	<script src="../frameworks/loaders/collada/AnimationHandler.js" defer></script>
	<script src="../frameworks/loaders/collada/KeyFrameAnimation.js" defer></script>
	
	<!-- LOAD DAT.GUI & STATS-->
    <script src="../frameworks/dat.gui.min.js" defer></script>
	<script src="../frameworks/stats.js" defer></script>
	
	<!-- GAME FILES-->
	<script src="../core/controls/controls_webcam_v01.js" defer></script>
    <script src="../core/world/world_v01.js" defer></script>
	<script src="../core/world/ground_v01.js" defer></script>
	<script src="../core/world/sky_v01.js" defer></script>
	<script src="../core/world/nature_v01.js" defer></script>
	<script src="../core/entities/template3D_v01.js" defer></script>
	<script src="../core/entities/entity3D_v02.js" defer></script>
	<script src="../core/ai/ai_path_v01.js" defer></script>
	<script src="../core/ai/ai_random_v01.js" defer></script>

<script>

$(document).ready(function () {
	$UI.drawloading();
    $UI.loading.setValue(0);
    $UI.loading.show();
	$WORLD.distance = 130;
	$WORLD.init3D({}, function () {
		$UI.loading.setValue(0.05);//5%
		$RG.templates={
			"castle_wall_a": {"model" : "../data/models/castle/wall_a.obj"},
			"castle_wall_b": {"model" : "../data/models/castle/wall_b.obj"},
			"castle_wall_c": {"model" : "../data/models/castle/wall_c.obj"},
			"castle_gate_wall": {"model" : "../data/models/castle/gate_wall.obj"},
			"castle_metal_gate": {"model" : "../data/models/castle/metal_gate.obj"},
			"castle_tower1": {"model" : "../data/models/castle/tower1.obj"},
			"castle_tower2": {"model" : "../data/models/castle/tower2.obj"},
			"castle_tower3": {"model" : "../data/models/castle/tower3.obj"},
			"house1": {"model": "../data/models/houses01/house1-01.obj"},
			"house2": {"model": "../data/models/houses01/house1-02.obj"},
			"house3": {"model": "../data/models/houses01/house1-03.obj"},
			"house4": {"model": "../data/models/houses01/house1-04.obj"},
			"well1": {"model": "../data/models/houses01/well-01.obj"},
			"bench1": {"model": "../data/models/houses01/bench-01.obj"},
			"house17": {"model": "../data/models/houses05/house5-01.obj"},
			"house18": {"model": "../data/models/houses05/house5-02.obj"},
			"house19": {"model": "../data/models/houses05/house5-03.obj"},
			"house20": {"model": "../data/models/houses05/house5-04.obj"},
			"house21": {"model": "../data/models/houses05/house5-05.obj"},
			"house22": {"model": "../data/models/houses06/house6-01.obj"},
			"house23": {"model": "../data/models/houses06/house6-02.obj"},
			"house25": {"model": "../data/models/houses06/house6-03.obj"},
			
			"tree07": {"model": "../data/graphics/textures/vegetation/tree07.png","width":10.2,"height":14.53,"type":3},
			"villager01": {"model": "../data/models/people/aldeano01.dae", "type":1, "animation":true, "ai":"PathAI", "scale":{"x":1.5,"y":1.5,"z":1.5}, "rotate":{"x":-90,"y":0,"z":0}},
			"aliendog": {"model": "../data/models/monsters/aliendog.dae", "type":1, "animation":true, "ai":"RandomAI", "scale":{"x":0.05,"y":0.05,"z":0.05}, "rotate":{"x":-90,"y":0,"z":-90}}
		}
		$WORLD.map = {
		"x":256,
		"z":256,
		"startPosX":126,
		"startPosZ":145,
		"ground": {
			"type":"basic",
			"texture":"../data/graphics/textures/terrain/grass1.jpg",
			"resX":2,
			"resY":2
		},
		"sky": {
			"type":"skysphere",
			"colorAmbient" : "rgb(90, 90, 90)",
			"intensityAmbient" : 0.5,
			"sunlightcolor" : "rgb(255, 255, 255)",
			"sunlightposition": {"x":10, "y":20, "z":0},
			"sunlightintensity" : 1,
			"texture":"../data/graphics/textures/sky/skydome.jpg",
			"fogColor": "rgb(225, 225, 225)",
			"fogNear":70,
			"fogFar":130
		},
			
		"nature": {
				"type":"basic",
				"patterns": {
					"bushes":{
						"freqX":5,
						"freqZ":5,
						"elements":[
							{"object":"../data/graphics/textures/vegetation/grass.png","width":1.5,"height":1.5},
							{"object":"../data/graphics/textures/vegetation/struik.png","width":1.5,"height":1.5}
						]
					},
					"forest":{
						"freqX":10,
						"freqZ":10,
						"elements":[
							{"object":"../data/graphics/textures/vegetation/tree01.png","width":8.75,"height":8.91},
							{"object":"../data/graphics/textures/vegetation/tree02.png","width":10,"height":9.84},
							{"object":"../data/graphics/textures/vegetation/tree03.png","width":9.59,"height":8.65},
							{"object":"../data/graphics/textures/vegetation/tree04.png","width":6.1,"height":8.65},
							{"object":"../data/graphics/textures/vegetation/tree05.png","width":10,"height":7.66},
							{"object":"../data/graphics/textures/vegetation/tree06.png","width":8.94,"height":13.9},
							{"object":"../data/graphics/textures/vegetation/tree07.png","width":10.2,"height":14.53}
						]
					},
					"hightTrees":{
						"freqX":12,
						"freqZ":12,
						"elements":[
							{"object":"../data/graphics/textures/vegetation/tree06.png","width":10,"height":20.68},
							{"object":"../data/graphics/textures/vegetation/tree07.png","width":12,"height":22.43}
						]
					}
					
				},
				"zones": [
					{"pattern":"forest","minX":0,"minZ":50,"maxZ":260,"maxX":114},
					{"pattern":"bushes","minX":20,"minZ":50,"maxZ":260,"maxX":117},
					
					{"pattern":"hightTrees","minX":110,"minZ":40,"maxZ":110,"maxX":200},
					{"pattern":"bushes","minX":110,"minZ":80,"maxZ":113,"maxX":140},
					
					{"pattern":"hightTrees","minX":0,"minZ":217,"maxZ":280,"maxX":230}
				]
			
		 }, 
		
		 "map3D": [
			{ "template": "castle_wall_c", "x": 214, "z": 110, "rY": -90 , "coment":"Size X:120-230, z:110-215"},
			{ "template": "castle_tower2", "x": 210, "z": 110 },
			{ "template": "castle_wall_a", "x": 199, "z": 110, "rY": -90 },
			{ "template": "castle_tower1", "x": 188, "z": 110, "rY": -90  },
			{ "template": "castle_gate_wall", "x": 177, "z": 110, "rY": -90 },
			{ "template": "castle_metal_gate", "x": 177, "z": 110, "rY": -90 },
			{ "template": "castle_tower1", "x": 166, "z": 110, "rY": -90  },
			{ "template": "castle_wall_a", "x": 155, "z": 110, "rY": -90 },
			{ "template": "castle_tower2", "x": 143, "z": 110 },

			{ "template": "castle_wall_c", "x": 120, "z": 129},
			{ "template": "castle_tower1", "x": 120, "z": 134},
			{ "template": "castle_gate_wall", "x": 120, "z": 145},
			{ "template": "castle_metal_gate", "x": 120, "z": 145, "y":2.5},
			{ "template": "castle_tower1", "x": 120, "z": 156},
			{ "template": "castle_wall_b", "x": 120, "z": 173},
			{ "template": "castle_tower3", "x": 120, "z": 192},
			{ "template": "castle_wall_c", "x": 140, "z": 215, "rY": 90},

			{ "template": "castle_tower2", "x": 144, "z": 215},
			{ "template": "castle_wall_b", "x": 157, "z": 215, "rY": 90 },
			{ "template": "castle_tower2", "x": 176, "z": 215},
			{ "template": "castle_wall_b", "x": 190, "z": 215, "rY": 90 },
			{ "template": "castle_tower2", "x": 210, "z": 215},
			{ "template": "castle_wall_c", "x": 233, "z": 199, "rY": 180 },
	
			{ "template": "castle_tower2", "x": 233, "z": 132},
			{ "template": "castle_wall_b", "x": 233, "z": 150, "rY": 180 },
			{ "template": "castle_tower2", "x": 233, "z": 165},
			{ "template": "castle_wall_b", "x": 233, "z": 185, "rY": 180 },
			{ "template": "castle_tower2", "x": 233, "z": 199},

			{ "template": "house1", "x": 155, "z": 150, "rY": -25,  "comment" : "houses01" },
			{ "template": "well1", "x": 135, "z": 146, "rY": -45  },
			{ "template": "bench1", "x": 145, "z": 153, "rY": -25 },
			{ "template": "house22", "x": 134, "z": 130,"rY": 110 },
			{ "template": "house23", "x": 150, "z": 125,"rY": 45 },
			{ "template": "house4", "x": 170, "z": 132, "rY": -25},

			{ "template": "house17", "x": 135, "z": 162, "rY": -100,  "comment" : "houses05" },
			{ "template": "house18", "x": 154, "z": 172,"rY": -45},
			{ "template": "house19", "x": 170, "z": 170,"rY": -55 },
			{ "template": "house20", "x": 174, "z": 155,"rY": -35 },
			{ "template": "house21", "x": 178, "z": 142,"rY": 45 },

			{ "template": "house22", "x": 133, "z": 180,"rY": 200, "comment" : "houses06" },
			{ "template": "house3", "x": 148, "z": 190, "rY": -15 },
			{ "template": "house2", "x": 168, "z": 190, "rY": 20 },
			{ "template": "house25", "x": 185, "z": 190, "rY": -5 },
			
			{ "template": "tree07", "x": 145, "z": 141 },
			{ "template": "tree07", "x": 146, "z": 166 },
			
			{ "template": "villager01", "x": 139, "z": 144, "path":[[171,0,131],[164,0,130],[159,0,130],[156,0,134],[149,0,141],[145,0,145],[139,0,150],[129,0,149],[127,0,144]
			,[133,0,140],[169,0,131],[140,0,138],[144,0,135],[145,0,131],[146,0,129],[147,0,128],[149,0,126],[148,0,128],[144,0,130],[142,0,126],[141,0,121],[149,0,117]
			,[160,0,121],[136,0,129],[166,0,130],[169,0,131]]},
			{ "template": "villager01", "x": 140, "z": 145, "path":[[135,0,133],[136,0,136],[131,0,142],[132,0,152],[141,0,152],[145,0,163],[144,0,173],[142,0,184],[138,0,190]
			,[127,0,191.5],[120.5,0,191.5],[120.5,0,159],[121,0,156],[128,0,156],[133,0,150],[132,0,143],[137,0,138],[136,0,134]]},
			{ "template": "villager01", "x": 140, "z": 145, "path":[[135,0,179],[136,0,179],[140,0,177],[152,0,181],[156,0,185],[157,0,190],[160,0,194],[163,0,192],[167,0,190]
			,[172,0,189],[176,0,188],[179,0,190],[180,0,190],[183,0,190],[185,0,190]]},
			
			{ "template": "aliendog", "x": 70, "z": 120, "minX":60,"maxX":85,"minZ":117,"maxZ":140},
			{ "template": "aliendog", "x": 73, "z": 150, "minX":60,"maxX":85,"minZ":140,"maxZ":163},
			{ "template": "aliendog", "x": 80, "z": 170, "minX":60,"maxX":85,"minZ":163,"maxZ":186},
			{ "template": "aliendog", "x": 65, "z": 190, "minX":60,"maxX":85,"minZ":186,"maxZ":209},

			{ "template": "aliendog", "x": 90, "z": 140, "minX":85,"maxX":111,"minZ":117,"maxZ":140},
			{ "template": "aliendog", "x": 100, "z": 141, "minX":85,"maxX":111,"minZ":140,"maxZ":163},
			{ "template": "aliendog", "x": 95, "z": 149, "minX":85,"maxX":111,"minZ":163,"maxZ":186},
			{ "template": "aliendog", "x": 105, "z": 149, "minX":85,"maxX":111,"minZ":186,"maxZ":209},
			
			{ "template": "aliendog", "x": 105, "z": 149, "minX":90,"maxX":110,"minZ":132,"maxZ":150}
			
		]
	};
		
		$WORLD.showStats();		
		$WORLD.drawGround();
		$WORLD.drawSky();
		$WORLD.drawNature();
		
		$RG.loadTemplates( function() {

			var elements=$WORLD.map.map3D.length;
			for (var i=0;i<elements;i++){
			
				var props=$WORLD.map.map3D[i];
				var ent=new $RG.Entity3D(props);
				ent.addToWorld();
				$UI.loading.setValue( ((i/elements)*0.20) +0.80);
			}
			
			var path=new THREE.CatmullRomCurve3([
            new THREE.Vector3(0/2, 2, 100/2),
			new THREE.Vector3(10/2, 2, 80/2),
            new THREE.Vector3(30/2, 2, 110/2),
            new THREE.Vector3(50, 2, 0/2),
            new THREE.Vector3(60/2, 2, 0/2),
            new THREE.Vector3(70/2, 2, 100/2),
            new THREE.Vector3(85/2, 2, 55/2),
            new THREE.Vector3(100/2, 2, 65/2),
            new THREE.Vector3(0/2, 2, 100/2)])

			$WORLD.camera.position.set(126,2,145);
			$WORLD.controls = new $CONTROLS.FirstPersonControls ($WORLD.camera);
			$WORLD.controls.minX=60;
			$WORLD.controls.minZ=117;
			$WORLD.controls.maxX=226;
			$WORLD.controls.maxZ=209;
			$WORLD.controls.showPosition();
			$WORLD.addToListUpdate ($WORLD.controls);

			setTimeout(function() {
				$WORLD.startAnimation();
				$UI.loading.hide();
				},500
			)
		},function () {
			//error
		},function (template,i,elements) {
			//Calculo un 75% para la carga de las plantillas
			$UI.loading.setValue( ((i/elements)*0.75) +0.05);
		}
		);
	});
})
			
</script>
</head>
<body>
<!-- butons -->
<div id="sample-info">
</div>
<div id="sample-buttons" class="sample-btn">
</div>
<div id="lyr_loading">
	<div id="lyr_loading_background"></div>
	<div id="lyr_loading_logo" class="ui_logo"></div>
</div>
</body>
</html>

core/controls/controls_webcan_v01.js


var $CONTROLS = $CONTROLS || {};

$CONTROLS.WebcamControls = function ( object, domElement ) {

	var temp = document.createElement('div');
	temp.innerHTML='<video id="monitor" autoplay style="display: none; width: 320px; height: 240px;"></video>'+
	'<div id="canvasLayers" width="320" height="240" style="position: absolute; right: 0px; top: 0px; width: 320px; height: 240px; overflow:hidden;">'+
	'<canvas id="videoCanvas" width="320" height="240" style="z-index: 1; position: absolute; left:0px; top:0px;width: 320px; height: 240px; overflow:hidden;"></canvas>'+
	'<canvas id="buttonsLayer" width="320" height="240" style="z-index: 2; position: absolute; left:0px; top:0px; opacity:0.5;width: 320px; height: 240px; overflow:hidden;"></canvas>'+
	'</div>'+
	'<canvas id="blendCanvas"  width="320" height="240" style="display: none; position: absolute; right: 320px; top: 0px; width: 320px; height: 240px;"></canvas>';
	document.body.appendChild(temp);
	var camvideo = document.getElementById('monitor');
	var video = document.getElementById( 'monitor' );
	var videoCanvas = document.getElementById( 'videoCanvas' );
	var videoContext = videoCanvas.getContext( '2d' );

	var buttonsLayerCanvas = document.getElementById( 'buttonsLayer' );
	var buttonsLayerContext = buttonsLayerCanvas.getContext( '2d' );

	var blendCanvas  = document.getElementById( "blendCanvas" );
	var blendContext = blendCanvas.getContext('2d');

	videoContext.translate(320, 0);
	videoContext.scale(-1, 1);
		
	videoContext.fillStyle = '#005337';
	videoContext.fillRect( 0, 0, videoCanvas.width, videoCanvas.height );				

	var buttons = [];

	var button1 = new Image();
	button1.src ="../data/graphics/ui/ico/wait-icon.png";
	var buttonData1 = { name:"wait", image:button1, x:64 + 10, y:10, w:32, h:32, pressed:false  };
	buttons.push( buttonData1 );

	var button2 = new Image();
	button2.src ="../data/graphics/ui/ico/walking-icon.png";
	var buttonData2 = { name:"walking", image:button2, x: 32 + 10, y:10, w:32, h:32, pressed:false };
	buttons.push( buttonData2 );

	var button3 = new Image();
	button3.src ="../data/graphics/ui/ico/running-icon.png";
	var buttonData3 = { name:"runing", image:button3, x:10, y:10, w:32, h:32, pressed:false };
	buttons.push( buttonData3 );

	var button4 = new Image();
	button4.src ="../data/graphics/ui/ico/left-icon.png";
	var buttonData4 = { name:"left", image:button4, x:320 - 96 - 10, y:10, w:32, h:32, pressed:false  };
	buttons.push( buttonData4 );

	var button5 = new Image();
	button5.src ="../data/graphics/ui/ico/up-icon.png";
	var buttonData5 = { name:"forward", image:button5, x: 320 - 64 -10 , y:10, w:32, h:32, pressed:false };
	buttons.push( buttonData5 );

	var button6 = new Image();
	button6.src ="../data/graphics/ui/ico/right-icon.png";
	var buttonData6 = { name:"right", image:button6, x:320 - 32 - 10, y:10, w:32, h:32, pressed:false };
	buttons.push( buttonData6 );
	
	
	navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia;
	window.URL = window.URL || window.webkitURL;

	if (!navigator.getUserMedia) 
	{
		//document.getElementById('messageError').innerHTML = 'Sorry. <code>navigator.getUserMedia()</code> no esta disponible.';
	}
	navigator.getUserMedia({video: true}, gotStream, noStream);

	function gotStream(stream) 
	{
		if (window.URL) 
		{   camvideo.src = window.URL.createObjectURL(stream);   } 
		else // Opera
		{   camvideo.src = stream;   }

		camvideo.onerror = function(e) 
		{   stream.stop();   };
		stream.onended = noStream;
	}

	function noStream(e) 
	{
		var msg = 'No hay camara disponible.';
		if (e.code == 1) 
		{   msg = 'El usuario ha denegado el acceso a la cámara.';   }
	//document.getElementById('errorMessage').textContent = msg;
	}
	
	
	function render() 
	{	
		if ( video.readyState === video.HAVE_ENOUGH_DATA ) 
		{

		videoContext.drawImage( video, 0, 0, videoCanvas.width, videoCanvas.height );
		for ( var i = 0; i < buttons.length; i++ )
				buttonsLayerContext.drawImage( buttons[i].image, buttons[i].x, buttons[i].y, buttons[i].w, buttons[i].h );		
		}
	}

	var lastImageData;

	function blend() 
	{
		var width  = videoCanvas.width;
		var height = videoCanvas.height;
		var sourceData = videoContext.getImageData(0, 0, width, height);
		if (!lastImageData) lastImageData = videoContext.getImageData(0, 0, width, height);
		var blendedData = videoContext.createImageData(width, height);
		differenceAccuracy(blendedData.data, sourceData.data, lastImageData.data);
		blendContext.putImageData(blendedData, 0, 0);
		lastImageData = sourceData;
	}
	function differenceAccuracy(target, data1, data2) 
	{
	if (data1.length != data2.length) return null;
	var i = 0;
	while (i < (data1.length * 0.25)) 
	{
		var average1 = (data1[4*i] + data1[4*i+1] + data1[4*i+2]) / 3;
		var average2 = (data2[4*i] + data2[4*i+1] + data2[4*i+2]) / 3;
		var diff = threshold(fastAbs(average1 - average2));
		target[4*i]   = diff;
		target[4*i+1] = diff;
		target[4*i+2] = diff;
		target[4*i+3] = 0xFF;
		++i;
	}
	}
	function fastAbs(value) 
	{
		return (value ^ (value >> 31)) - (value >> 31);
	}
	function threshold(value) 
	{
		return (value > 0x15) ? 0xFF : 0;
	}

	function checkAreas() 
	{
	for (var b = 0; b < buttons.length; b++)
	{
		var blendedData = blendContext.getImageData( buttons[b].x, buttons[b].y, buttons[b].w, buttons[b].h );
		var i = 0;
		var sum = 0;
		var countPixels = blendedData.data.length * 0.25;
		while (i < countPixels) 
		{
			sum += (blendedData.data[i*4] + blendedData.data[i*4+1] + blendedData.data[i*4+2]);
			++i;
		}
		var average = Math.round(sum / (3 * countPixels));
		if (average > 50)
		{
			buttons[b].pressed=true;
		} else {
			buttons[b].pressed=false;
		}
	}
	}

	this.object = object;
	this.target = new THREE.Vector3( 0, 0, 0 );

	this.domElement = ( domElement !== undefined ) ? domElement : document;

	this.enabled = true;

	this.eyeY=2;
	this.movementSpeed = 3.5;
	this.movementSpeedRun = 6.0;
	this.lookSpeed = 0.02;

	this.mouseX = 0;
	this.mouseY = 0;

	this.lon = 0;
	this.theta = 0;

	this.moveForward = false;
	this.moveBackward = false;
	this.moveLeft = false;
	this.moveRight = false;
	this.run = false;
	this.jump = false;
	this.showPosition=false;
	
	this.minX=0;
	this.maxX=256;
	this.minZ=0;
	this.maxZ=256;

	this.viewHalfX = 0;

	if ( this.domElement !== document ) {
		this.domElement.setAttribute( 'tabindex', - 1 );
	}



	this.handleResize = function () {

		if ( this.domElement === document ) {
			this.viewHalfX = window.innerWidth / 2;
		} else {
			this.viewHalfX = this.domElement.offsetWidth / 2;
		}

	};

	this.getPosition = function ( ) {
		return this.object.position;
	}
	
	this.showPosition = function () {
		var o=document.createElement('div');
		o.id="panelInfoControls";
		document.body.appendChild(o);
		this.panelInfo=o;
		this.showPosition=true;
	}

	this.onMouseMove = function ( event ) {

		if ( this.domElement === document ) {

			this.mouseX = event.pageX - this.viewHalfX;


		} else {

			this.mouseX = event.pageX - this.domElement.offsetLeft - this.viewHalfX;

		}

	};

	this.onKeyDown = function ( event ) {

		switch ( event.keyCode ) {

			case 38: /*up*/
			case 87: /*W*/ this.moveForward = true; break;

			case 37: /*left*/
			case 65: /*A*/ this.moveLeft = true; break;

			case 40: /*down*/
			case 83: /*S*/ this.moveBackward = true; break;

			case 39: /*right*/
			case 68: /*D*/ this.moveRight = true; break;
			
			case 16: /*shift*/ this.run = true; break;

		}

	};

	this.onKeyUp = function ( event ) {

		switch ( event.keyCode ) {

			case 38: /*up*/
			case 87: /*W*/ this.moveForward = false; break;

			case 37: /*left*/
			case 65: /*A*/ this.moveLeft = false; break;

			case 40: /*down*/
			case 83: /*S*/ this.moveBackward = false; break;

			case 39: /*right*/
			case 68: /*D*/ this.moveRight = false; break;

			case 16: /*shift*/ this.run = false; break;

		}

	};

	this.update = function( delta ) {

		if ( this.enabled === false ) return;
		
	render();	
	blend();	
	checkAreas();


	if (buttonData3.pressed) {
		action="corriendo";
		this.run=true;
		this.moveForward = true;
	} else if (buttonData2.pressed) {
		this.run=false;
		this.moveForward = true;
		action="andando";
	} else if (buttonData1.pressed) {
		this.run=false;
		this.moveForward = false;
		action="parados";
	};
	
	if (buttonData6.pressed) {
		this.mouseX = this.viewHalfX;
		action2="la derecha";
	} else if (buttonData4.pressed) {
		action2="la izquierda";
		this.mouseX = -1 * this.viewHalfX;
	} else if (buttonData5.pressed) {
		action2="adelante";
		this.mouseX = 0;
	};


		var actualMoveSpeed = delta * (this.run?this.movementSpeedRun:this.movementSpeed);

		if ( this.moveForward) this.object.translateZ( - (actualMoveSpeed) );
		if ( this.moveBackward) this.object.translateZ( actualMoveSpeed );

		if ( this.moveLeft) this.object.translateX( - actualMoveSpeed );
		if ( this.moveRight) this.object.translateX( actualMoveSpeed );

		this.object.position.y=this.eyeY;
		if (this.minX>this.object.position.x) {
			this.object.position.x=this.minX;
		} else if (this.maxX<this.object.position.x) {
			this.object.position.x=this.maxX;
		}
		if (this.minZ>this.object.position.z) {
			this.object.position.z=this.minZ;
		} else if (this.maxZ<this.object.position.z) {
			this.object.position.z=this.maxZ;
		}
		if (this.showPosition) {
			this.panelInfo.innerHTML=" x: "+Math.round(this.object.position.x,0.1)+" z: "+Math.round(this.object.position.z,0.1)+" ";
		}
		var actualLookSpeed = delta * this.lookSpeed;

		this.lon += this.mouseX * actualLookSpeed;
		this.theta = THREE.Math.degToRad( this.lon );

		var targetPosition = this.target,
		position = this.object.position;

		targetPosition.x = position.x + 100 * Math.cos( this.theta );
		targetPosition.z = position.z + 100 * Math.sin( this.theta );

		this.object.lookAt( targetPosition );

	};

	this.dispose = function() {
		this.domElement.removeEventListener( 'mousemove', _onMouseMove, false );
		window.removeEventListener( 'keydown', _onKeyDown, false );
		window.removeEventListener( 'keyup', _onKeyUp, false );
	}

	var _onMouseMove = bind( this, this.onMouseMove );
	var _onKeyDown = bind( this, this.onKeyDown );
	var _onKeyUp = bind( this, this.onKeyUp );

	this.domElement.addEventListener( 'mousemove', _onMouseMove, false );
	window.addEventListener( 'keydown', _onKeyDown, false );
	window.addEventListener( 'keyup', _onKeyUp, false );

	function bind( scope, fn ) {
		return function () {
			fn.apply( scope, arguments );
		};
	}

	this.handleResize();

};

core/ai/ai_random_v01.js


var $AIS = $AIS || {};

$AIS.RandomAI = function (object, prop) {
	this._object=object;
	this.velocity=3; //unidades por segundo
	if (prop.velocity){
		this.velocity=prop.velocity;
	}
	this.minX=prop.minX;
	this.maxX=prop.maxX;
	this.minZ=prop.minZ;
	this.maxZ=prop.maxZ;
	this.directionWalk = new THREE.Vector3(0.5, 0, 0.5);
	this.changeDirection();
};

$AIS.RandomAI.prototype.changeDirection = function () {
	this._lastRandomX = Math.random();
    this._lastRandomZ = 1 - this._lastRandomX;
    if (Math.random() < 0.5) {
		this._lastRandomX = this._lastRandomX * -1;
    }
    if (Math.random() < 0.5) {
		this._lastRandomZ = this._lastRandomZ * -1;
    }
    this.directionWalk.x = this._lastRandomX;
	this.directionWalk.z = this._lastRandomZ;
	var pos = this.directionWalk.clone();
    pos.add(this._object.position);
	this._object.lookAt(pos);
}

$AIS.RandomAI.prototype.update = function ( delta ) {
	var p=this._object.position;
	var x=p.x+ this.directionWalk.x * this.velocity * delta;
	var z=p.z+ this.directionWalk.z * this.velocity * delta;
	var bChange=false;
	if (x<this.minX) {
		x=this.minX;bChange=true;
	} else if (x>this.maxX) {
		x=this.maxX;bChange=true;
	};
	if (z<this.minZ) {
		z=this.minZ;bChange=true;
	} else if (z>this.maxZ) {
		z=this.maxZ;bChange=true;
	};
	if (bChange) {
		this.changeDirection();
	};
	p.set(x, p.y, z)
}

$AIS.RandomAI.prototype.getPosition = function ( ) {
	return this._object.position;
}

core/ai/ai_path_v01.js



var $AIS = $AIS || {};

$AIS.PathAI = function (object, prop) {
	var vecs=[];
	for (var i=0;i 1) {this._pos = 0;};
	this._object.lookAt(this.path.getPointAt(this._pos));
}

$AIS.PathAI.prototype.showPath = function ( ) {
	var geometry = new THREE.Geometry();
	var points = this.path.getPoints(50);

	var material = new THREE.LineBasicMaterial({
		color: 0xff00f0
	});

	geometry.vertices = points;
	var line = new THREE.Line(geometry, material);
	line.position.set(0,0.25,0)
	$WORLD.scene.add(line);
}

$AIS.PathAI.prototype.getPosition = function ( ) {
	return this._object.position;
}

core/world/template3D_v01.js


var $RG = $RG || {};
$RG.templates=[];

$RG.Types = $RG.Types || {};
$RG.Types.type3D = { "OBJ": 0, "DAE":1, "JSON":2, "SPRITE":3 };

$RG.loadTemplates = function(fSuc, fFail, fProgress) {
	var i=0;
	var list=Object.keys($RG.templates);
	var _load = function () {
		if (list.length==i) {
			fSuc();
			return;
		}
		var ent=$RG.templates[list[i]].template3D=new $RG.Template3D(list[i]);
		if (fProgress) {fProgress(list[i],i+1,list.length);}
		i++;
		ent.load({},_load, fFail);
	}
	_load();
};

//CLASSE: Template3D    
$RG.Template3D = function (id) {
        this.id = id;
		this._template=$RG.templates[id];
        this.isReady = false;
        this.mesh = null; 
};

$RG.Template3D.prototype.load = function (oPars, fSuc, fFail) {
	var temp=this._template;
	if (!("type" in temp)) temp.type = $RG.Types.type3D.OBJ;
	if (temp.type == $RG.Types.type3D.OBJ) {
		this._loadOBJ(oPars,fSuc,fFail);
	} else if (temp.type == $RG.Types.type3D.DAE) {
		this._loadDAE(oPars,fSuc,fFail);
	} else if (temp.type == $RG.Types.type3D.SPRITE) {
		this._loadSPRITE(oPars,fSuc,fFail);
	} else {
		fFail();
	}
}

$RG.Template3D.prototype._loadOBJ = function (oPars, fSuc, fFail) {
        var $O = this;
        var onProgress = function (xhr) {    };
        var onError = function (xhr) { if (fFail) { fFail($O); } };
        var mtlLoader = new THREE.MTLLoader();
        var pathArray = $O._template.model.split('/');
        var mP = '';
        for (var i = 0; i < pathArray.length-1; i++) {
            mP += pathArray[i];
            mP += "/";
        }
        var model = pathArray[pathArray.length - 1];
        mtlLoader.setPath(mP);
		model=model.substr(0,model.length - 4)
        mtlLoader.load(model + '.mtl', function (materials) {
            materials.preload();
            var objLoader = new THREE.OBJLoader();
            objLoader.setMaterials(materials);
            objLoader.setPath(mP);
            objLoader.load(model + '.obj', function (object) {
                object.traverse(function (child) {
                    if (child instanceof THREE.Mesh) {
                        child.castShadow = true;
                    }
                });
                $O.mesh = object;
				$O.mesh.castShadow = true;
                $O.isReady = true;
                if (fSuc) { fSuc($O); }

            }, onProgress, onError);

        }, onProgress, onError);
};

$RG.Template3D.prototype._loadDAE = function (oPars, fSuc, fFail) {
	var $O = this;
	var temp=$O._template;
    var loader = new THREE.ColladaLoader();
	var onProgress = function (xhr) {    };
    var onError = function (xhr) { if (fFail) { fFail($O); } };
    loader.load(temp.model, function (collada) {
		var object = collada.scene;
		var mesh=null;
		object.traverse(function (child) {
			if (child instanceof THREE.Mesh) {
				child.castShadow = true;
				mesh=child;
               }
		});

		if (temp.scale) {
			mesh.scale.x = temp.scale.x;
			mesh.scale.y = temp.scale.y;
			mesh.scale.z = temp.scale.z; //Corregir escala
		}
		if (temp.rotate) {
			if (temp.rotate.x) {
				mesh.rotateX (temp.rotate.x * Math.PI / 180);
			};
			if (temp.rotate.y) {
				mesh.rotateY (temp.rotate.y * Math.PI / 180);
			};
			if (temp.rotate.z) {
				mesh.rotateZ (temp.rotate.z * Math.PI / 180);
			}//Corregir rotación
		}
		$O.mesh = object;
		$O.isReady = true;
		fSuc(mesh);
    }, onProgress, onError);
};

$RG.Template3D.prototype._loadSPRITE = function (oPars, fSuc, fFail) {
	var $O = this;
	var onProgress = function (xhr) {    };
    var onError = function (xhr) { if (fFail) { fFail($O); } };
    $WORLD.textureLoader.load($O._template.model, function (texture) {
		var mat = new THREE.SpriteMaterial( { map: texture, useScreenCoordinates: false, transparent: true,fog:true} );
		var object =new THREE.Sprite(mat);
		object.scale.y=$O._template.height;
		object.scale.x=$O._template.width;
		$O.mesh = object;
		$O.isReady = true;
		fSuc($O.mesh);
    }, onProgress, onError);
};

core/world/entity3D_v02.js


var $RG = $RG || {};
$RG.entities=[];

$RG.Entity3D = function (properties) {
	this.template=properties.template
	this.prop=properties;
	this.mesh=null;
	$RG.entities.push(this)
}

$RG.Entity3D.prototype.addToWorld = function () {
	var prop=this.prop;
	var templ=$RG.templates[prop.template];

	//Clonar la figura 3D, posicionar y rotar
	var mesh=templ.template3D.mesh.clone();
	var y=0
	mesh.position.set(prop.x, ((prop.y)?prop.y:0), prop.z);
	if (!(prop.rY)) prop.rY=0;
	if (templ.type=3) {
		mesh.translateY(templ.height/2-0.05);
	}
	mesh.rotateY(prop.rY * Math.PI / 180);
	this.mesh=mesh;
	
	//Animar el objeto si tienen una animación
	if (templ.animation) {
		mesh.traverse(function (child) {
			if (child instanceof THREE.SkinnedMesh) {
				var animation = new THREE.Animation(child, child.geometry.animation);
				animation.play();
			}
		})
	};
   
    //Aplicar la inteligencia artificial si hay definida
	if (templ.ai) {
	
		this.ai=new $AIS[templ.ai](this.mesh, this.prop);
		$WORLD.addToListUpdate (this.ai); 
	}
	$WORLD.scene.add(mesh);
	return mesh;
};

core/world/nature_v01.js


//****************************
// CREA LA NATURALEZA
//****************************

$WORLD.drawNature = function () {

        var nat=$WORLD.map.nature;
        //CARGAR EN MEMORIA TODOS LOS SPRITES
        var list=Object.keys(nat.patterns);
        for (var i=0;i<list.length;i++) {
            var pat=nat.patterns[list[i]];
            for (var n=0;n<pat.elements.length;n++) {
                var el=pat.elements[n];
                var mat = new THREE.SpriteMaterial( { map: $WORLD.textureLoader.load(el.object), useScreenCoordinates: false, transparent: true,fog:true} );
                var obj =new THREE.Sprite(mat);
                obj.scale.y=el.height;
                obj.scale.x=el.width;
                el._sprite = obj;
            }
        }
        //PARA CADA ZONA AÑADIR LOSaerboles
        for (var j=0;j<nat.zones.length;j++) {
            var zon=nat.zones[j];
            var pat=nat.patterns[zon.pattern];
            for (var x=zon.minX;x<zon.maxX-pat.freqX;x+=pat.freqX) {
                for (var z=zon.minZ;z<zon.maxZ-pat.freqZ;z+=pat.freqZ) {
                    var i=Math.round(Math.random()*(pat.elements.length-1));
                    var el=pat.elements[i];
                    var obj2=el._sprite.clone();z
                    obj2.position.set(x+(Math.random()*pat.freqX), el.height/2-0.05, z+(Math.random()*pat.freqZ));
                    $WORLD.scene.add(obj2);
                }
            }
        }
};

core/world/sky_v01.js


//****************************
// CREA EL CIELO, Y LAS LUCES
//****************************

$WORLD.sky= {
    update:function(delta){
        var p = $WORLD.controls.getPosition();
        $WORLD.sky.skyBox.position.set(p.x, 0, p.z);
    }    
};

$WORLD.drawSky = function () {
    var sky = $WORLD.map.sky;
    if (sky.type=="skybox"){
        $WORLD.drawSkybox(sky);
    } else if (sky.type=="skysphere" && sky.texture!="") {
        $WORLD.drawSkysphere(sky);
    } else {
        $WORLD.drawSkysphereNoImg(sky);
    }

    //CREAR LA LUZ DE AMBIENTE
    $WORLD.ambientLight.color = new THREE.Color(sky.colorAmbient);
    $WORLD.ambientLight.intensity = sky.intensityAmbient;

    //CREAR LA LUZ DEL SOL
    var light = new THREE.DirectionalLight(sky.sunlightcolor, sky.sunlightintensity);
    light.castShadow = true;
    light.shadow.mapSize.width = 2 * 512; 
    light.shadow.mapSize.height = 2 * 512;
    light.shadow.camera.near = 0;
    light.shadow.camera.far = 50; //ALTURA DEL CUBO

    //DES DEL PUNTO CENTRAL INDICAN EL CUADRADO.
    light.shadow.camera.top = 25; //X
    light.shadow.camera.right = 25;
    light.shadow.camera.left = -25;
    light.shadow.camera.bottom = -25;

    light.shadow.camera.visible = true;
    $WORLD.sky.skyBox.add(light);
    
    light.position.set(sky.sunlightposition.x, sky.sunlightposition.y, sky.sunlightposition.z); 
    light.target = $WORLD.sky.skyBox;
    
    $WORLD.scene.fog.near = sky.fogNear;
    if (sky.fogFar > 0 && ($WORLD.distance - $WORLD.distance / 4) > sky.fogFar) {
        $WORLD.scene.fog.far = sky.fogFar;
    }
    $WORLD.scene.fog.color = new THREE.Color(sky.fogColor);
    $WORLD.renderer.setClearColor($WORLD.scene.fog.color, 1);
    
    $WORLD.addToListUpdate ($WORLD.sky);
};

$WORLD.drawSkybox=function (sky){
    var cubemap = new THREE.CubeTextureLoader().load( sky.texture );
    cubemap.format = THREE.RGBFormat;
        
    var shader = THREE.ShaderLib['cube']; 
    shader.uniforms['tCube'].value = cubemap; 

    var skyBoxMaterial = new THREE.ShaderMaterial( {
    fragmentShader: shader.fragmentShader,
    vertexShader: shader.vertexShader,
    uniforms: shader.uniforms,
    depthWrite: false,
    side: THREE.BackSide
    });
    
    var distance=($WORLD.distance*2-20);
    var c = Math.pow ((distance*distance)/2,0.5);
    var skyBox = new THREE.Mesh(  new THREE.BoxGeometry(c, c, c),  skyBoxMaterial);
    $WORLD.scene.add(skyBox);
    $WORLD.sky.skyBox = skyBox;

};

$WORLD.drawSkysphere=function (sky){
    var skyTexture = $WORLD.textureLoader.load(sky.texture);
    var geometry = new THREE.SphereGeometry($WORLD.distance - 10, 30, 20);

    var uniforms = {
        texture: { type: 't', value: skyTexture }
    };
    var material = new THREE.ShaderMaterial({
        uniforms: uniforms,
        vertexShader: "varying vec2 vUV;" +
        "\n" +
        "void main() {  " +
        "    vUV = uv;" +
        "    vec4 pos = vec4(position, 1.0);" +
        "    gl_Position = projectionMatrix * modelViewMatrix * pos;" +
        "}",
        fragmentShader: "uniform sampler2D texture;" +
        "varying vec2 vUV;" +
        "" +
        "    void main() {" +
        "        vec4 sample = texture2D(texture, vUV);" +
        "        gl_FragColor = vec4(sample.xyz, sample.w);" +
        "    }"
    });

    var skyBox = new THREE.Mesh(geometry, material);
    skyBox.scale.set(-1, 1, 1);
    skyBox.rotation.order = 'XZY';
    skyBox.renderDepth = $WORLD.distance;
    $WORLD.scene.add(skyBox);
    $WORLD.sky.skyBox = skyBox;
};

$WORLD.drawSkysphereNoImg=function (sky){

    var vertexShader ="varying vec3 vWorldPosition;"+
    " "+
    "void main() {"+
    "    vec4 worldPosition = modelMatrix * vec4( position, 1.0 );"+
    "    vWorldPosition = worldPosition.xyz;"+ //xyz
    " "+
    "    gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );"+
    "}";

    var fragmentShader ="uniform vec3 topColor;"+
    "uniform vec3 bottomColor;"+
    "uniform float offset;"+
    "uniform float exponent;"+
    " "+
    "varying vec3 vWorldPosition;"+
    " "+
    "void main() {"+
    "    float h = normalize( vWorldPosition + offset ).y;"+
    "    gl_FragColor = vec4( mix( bottomColor, topColor, max( pow( h, exponent ), 0.0 ) ), 1.0 );"+
    "}";

    var uniforms = {
            topColor: {type: "c", value: new THREE.Color(sky.topColor)}, bottomColor: {type: "c", value: new THREE.Color(sky.bottomColor)},
            offset: {type: "f", value: 0}, exponent: {type: "f", value: 0.5} 
    }
    var skyMaterial = new THREE.ShaderMaterial({vertexShader: vertexShader, fragmentShader: fragmentShader, uniforms: uniforms, side: THREE.BackSide, fog: false});
     
    var skyBox = new THREE.Mesh( new THREE.SphereGeometry($WORLD.distance - 10, 30, 20), skyMaterial);

    skyBox.rotation.order = 'XZY';
    skyBox.renderDepth = $WORLD.distance;
    
    $WORLD.scene.add(skyBox);
    $WORLD.sky.skyBox = skyBox;
}

core/world/ground_v01.js


//****************************
// CREA EL SUELO DEL MUNDO
//****************************

$WORLD.drawGround = function () {
    var map = $WORLD.map;
    var groundTexture = $WORLD.textureLoader.load(map.ground.texture);
    var x = $WORLD.distance * 2.25 + map.x
    var z = $WORLD.distance * 2.25 + map.z
    groundTexture.wrapS = groundTexture.wrapT = THREE.RepeatWrapping;
    groundTexture.repeat.set(x / 2, z / 2); 
    groundTexture.anisotropy = 16;
    var groundMaterial = new THREE.MeshLambertMaterial({ color: 0xffffff, map: groundTexture });
    var mesh = new THREE.Mesh(new THREE.PlaneBufferGeometry(x, z), groundMaterial);
    mesh.position.y = 0;
    mesh.position.x = map.x / 2;
    mesh.position.z = map.z / 2;
    mesh.rotation.x = - Math.PI / 2;
    mesh.receiveShadow = true;
    $WORLD.scene.add(mesh);
}

core/world/world_v01.js


//*******************************
//DEFINIR EL MUNDO
//*******************************
var $WORLD = $WORLD || {};
$WORLD.distance = 80;
$WORLD.renderer = null;
$WORLD.scene = null;
$WORLD.clock = null;
$WORLD.map=null;
$WORLD.controls=null;
$WORLD._objUpdate = [];

$WORLD.init3D=function(oPars, fSuc, fFail) {

    var renderer = new THREE.WebGLRenderer();
    renderer.shadowMap.enabled = true;
    renderer.shadowMap.type = THREE.PCFSoftShadowMap;
    renderer.setSize(window.innerWidth, window.innerHeight);
    document.body.appendChild(renderer.domElement);
    $WORLD.renderer = renderer;
    $WORLD.scene = new THREE.Scene();
    
    $WORLD.camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, $WORLD.distance);
    $WORLD.camera.position.set(0, 2, 0);
    $WORLD.camera.lookAt(new THREE.Vector3(0,2,0) );
    
    $WORLD.clock = new THREE.Clock();
    $WORLD.controls={
        getPosition: function(){
            return $WORLD.camera.position;
        }
    } 

    $WORLD.textureLoader = new THREE.TextureLoader();
    
    $WORLD.ambientLight = new THREE.AmbientLight(0xffffff,1);
    $WORLD.scene.add($WORLD.ambientLight);
 
    $WORLD.scene.fog = new THREE.Fog(0xffffff, 5, ($WORLD.distance - $WORLD.distance / 4)); //niebla
    $WORLD.renderer.setClearColor($WORLD.scene.fog.color, 1);
    
    window.addEventListener('resize', onWindowResize, false);
    THREE.Loader.Handlers.add(/\.dds$/i, new THREE.DDSLoader());
    fSuc();
}

$WORLD.showStats=function() {
    if (!($WORLD.stats)) {
        $WORLD.stats = new Stats();
        $WORLD.stats.setMode(0);
        document.body.appendChild($WORLD.stats.domElement);
        $WORLD.addToListUpdate($WORLD.stats);
    };

}

$WORLD.startAnimation = function () {
    $WORLD.animate();
}

$WORLD.pauseAnimation = function () {
    window.cancelAnimationFrame( $WORLD.idAnim );
}

$WORLD.addToListUpdate = function (obj) {
    $WORLD._objUpdate.push(obj);
}

$WORLD.animate = function () {
    $WORLD.idAnim = requestAnimationFrame($WORLD.animate);
    var delta = $WORLD.clock.getDelta();
    for (var i = 0; i < $WORLD._objUpdate.length; i++) {
        $WORLD._objUpdate[i].update(delta);
    };
    THREE.AnimationHandler.update(delta);
    $WORLD.renderer.render($WORLD.scene, $WORLD.camera);

};

function onWindowResize() {
    $WORLD.camera.aspect = window.innerWidth / window.innerHeight;
    $WORLD.camera.updateProjectionMatrix();
    $WORLD.renderer.setSize(window.innerWidth, window.innerHeight);
}