text:
/**
 * @author alteredq / http://alteredqualia.com/
 */

THREE.SceneLoader = function () {

	this.onLoadStart = function () {};
	this.onLoadProgress = function() {};
	this.onLoadComplete = function () {};

	this.callbackSync = function () {};
	this.callbackProgress = function () {};

	this.geometryHandlers = {};
	this.hierarchyHandlers = {};

	this.addGeometryHandler( "ascii", THREE.JSONLoader );

	//added by mca
	this.loader = new THREE.XHRLoader( this.manager );
};

THREE.SceneLoader.prototype = {

	constructor: THREE.SceneLoader,

	load: function ( url, onLoad, onProgress, onError ) {

		var scope = this;

		// mca var loader = new THREE.XHRLoader( scope.manager );
		var loader = this.loader;
		loader.setCrossOrigin( this.crossOrigin );
		loader.load( url, function ( text ) {
			setTimeout(
				function(scope, text, onLoad, url){
					try{
						scope.parse( JSON.parse( text ), onLoad, url );
					}
					catch(e){
						console.log("SceneLoader_r63");
						console.log(e);
						console.log("ResponseText", text);
						onLoad({ //send empty result (fail silent)
								scene: new THREE.Scene(),
								geometries: {},
								face_materials: {},
								materials: {},
								textures: {},
								objects: {},
								cameras: {},
								lights: {},
								fogs: {},
								empties: {},
								groups: {}
								}
						);
					}

				}.bind(this), 1, scope, text, onLoad, url);

			// try{
				// scope.parse( JSON.parse( text ), onLoad, url );
			// }
			// catch(e){
				// console.log("SceneLoader_r63");
				// console.log(e);
				// console.log("ResponseText", text);
				// onLoad({ //send empty result (fail silent)
						// scene: new THREE.Scene(),
						// geometries: {},
						// face_materials: {},
						// materials: {},
						// textures: {},
						// objects: {},
						// cameras: {},
						// lights: {},
						// fogs: {},
						// empties: {},
						// groups: {}
						// }
				// );
			// }

		}, onProgress, onError );

	},

	setCrossOrigin: function ( value ) {

		this.crossOrigin = value;

	},

	addGeometryHandler: function ( typeID, loaderClass ) {

		this.geometryHandlers[ typeID ] = { "loaderClass": loaderClass };

	},

	addHierarchyHandler: function ( typeID, loaderClass ) {

		this.hierarchyHandlers[ typeID ] = { "loaderClass": loaderClass };

	},

	parse: function ( json, callbackFinished, url ) {

		var scope = this;

		var urlBase = THREE.Loader.prototype.extractUrlBase( url );

		var geometry, material, camera, fog,
			texture, images, color,
			light, hex, intensity,
			counter_models, counter_textures,
			total_models, total_textures,
			result;

		var target_array = [];

		var data = json;

		// async geometry loaders

		for ( var typeID in this.geometryHandlers ) {

			var loaderClass = this.geometryHandlers[ typeID ][ "loaderClass" ];
			this.geometryHandlers[ typeID ][ "loaderObject" ] = new loaderClass();

		}

		// async hierachy loaders

		for ( var typeID in this.hierarchyHandlers ) {

			var loaderClass = this.hierarchyHandlers[ typeID ][ "loaderClass" ];
			this.hierarchyHandlers[ typeID ][ "loaderObject" ] = new loaderClass();

		}

		counter_models = 0;
		counter_textures = 0;

		result = {

			scene: new THREE.Scene(),
			geometries: {},
			face_materials: {},
			materials: {},
			textures: {},
			objects: {},
			cameras: {},
			lights: {},
			fogs: {},
			empties: {},
			groups: {}

		};

		if ( data.transform ) {

			var position = data.transform.position,
				rotation = data.transform.rotation,
				scale = data.transform.scale;

			if ( position ) {

				result.scene.position.fromArray( position );

			}

			if ( rotation ) {

				result.scene.rotation.fromArray( rotation );

			}

			if ( scale ) {

				result.scene.scale.fromArray( scale );

			}

			if ( position || rotation || scale ) {

				result.scene.updateMatrix();
				result.scene.updateMatrixWorld();

			}

		}

		function get_url( source_url, url_type ) {

			if ( url_type == "relativeToHTML" ) {

				return source_url;

			} else {

				return urlBase + "/" + source_url;

			}

		};

		// toplevel loader function, delegates to handle_children

		function handle_objects() {

			handle_children( result.scene, data.objects );

		}

		// handle all the children from the loaded json and attach them to given parent

		function handle_children( parent, children ) {

			var mat, dst, pos, rot, scl, quat;

			for ( var objID in children ) {

				// check by id if child has already been handled,
				// if not, create new object

				var object = result.objects[ objID ];
				var objJSON = children[ objID ];

				if ( object === undefined ) {

					// meshes

					if ( objJSON.type && ( objJSON.type in scope.hierarchyHandlers ) ) {

						if ( objJSON.loading === undefined ) {

							var reservedTypes = {
								"type": 1, "url": 1, "material": 1,
								"position": 1, "rotation": 1, "scale" : 1,
								"visible": 1, "children": 1, "userData": 1,
								"skin": 1, "morph": 1, "mirroredLoop": 1, "duration": 1
							};

							var loaderParameters = {};

							for ( var parType in objJSON ) {

								if ( ! ( parType in reservedTypes ) ) {

									loaderParameters[ parType ] = objJSON[ parType ];

								}

							}

							material = result.materials[ objJSON.material ];

							objJSON.loading = true;

							var loader = scope.hierarchyHandlers[ objJSON.type ][ "loaderObject" ];

							// ColladaLoader

							if ( loader.options ) {

								loader.load( get_url( objJSON.url, data.urlBaseType ), create_callback_hierachy( objID, parent, material, objJSON ) );

							// UTF8Loader
							// OBJLoader

							} else {

								loader.load( get_url( objJSON.url, data.urlBaseType ), create_callback_hierachy( objID, parent, material, objJSON ), loaderParameters );

							}

						}

					} else if ( objJSON.geometry !== undefined ) {

						geometry = result.geometries[ objJSON.geometry ];

						// geometry already loaded

						if ( geometry ) {

							var needsTangents = false;

							material = result.materials[ objJSON.material ];
							needsTangents = material instanceof THREE.ShaderMaterial;

							pos = objJSON.position;
							rot = objJSON.rotation;
							scl = objJSON.scale;
							mat = objJSON.matrix;
							quat = objJSON.quaternion;

							// use materials from the model file
							// if there is no material specified in the object

							if ( ! objJSON.material ) {

								material = new THREE.MeshFaceMaterial( result.face_materials[ objJSON.geometry ] );

							}

							// use materials from the model file
							// if there is just empty face material
							// (must create new material as each model has its own face material)

							if ( ( material instanceof THREE.MeshFaceMaterial ) && material.materials.length === 0 ) {

								material = new THREE.MeshFaceMaterial( result.face_materials[ objJSON.geometry ] );

							}

							if ( material instanceof THREE.MeshFaceMaterial ) {

								for ( var i = 0; i < material.materials.length; i ++ ) {

									needsTangents = needsTangents || ( material.materials[ i ] instanceof THREE.ShaderMaterial );

								}

							}

							if ( needsTangents ) {

								geometry.computeTangents();

							}

							if ( objJSON.skin ) {

								object = new THREE.SkinnedMesh( geometry, material );

							} else if ( objJSON.morph ) {

								object = new THREE.MorphAnimMesh( geometry, material );

								if ( objJSON.duration !== undefined ) {

									object.duration = objJSON.duration;

								}

								if ( objJSON.time !== undefined ) {

									object.time = objJSON.time;

								}

								if ( objJSON.mirroredLoop !== undefined ) {

									object.mirroredLoop = objJSON.mirroredLoop;

								}

								if ( material.morphNormals ) {

									geometry.computeMorphNormals();

								}

							} else {

								object = new THREE.Mesh( geometry, material );

							}

							object.name = objID;

							if ( mat ) {

								object.matrixAutoUpdate = false;
								object.matrix.set(
									mat[0],  mat[1],  mat[2],  mat[3],
									mat[4],  mat[5],  mat[6],  mat[7],
									mat[8],  mat[9],  mat[10], mat[11],
									mat[12], mat[13], mat[14], mat[15]
								);

							} else {

								object.position.fromArray( pos );

								if ( quat ) {

									object.quaternion.fromArray( quat );

								} else {

									object.rotation.fromArray( rot );

								}

								object.scale.fromArray( scl );

							}

							object.visible = objJSON.visible;
							object.castShadow = objJSON.castShadow;
							object.receiveShadow = objJSON.receiveShadow;

							parent.add( object );

							result.objects[ objID ] = object;

						}

					// lights

					} else if ( objJSON.type === "AmbientLight" || objJSON.type === "PointLight" ||
						objJSON.type === "DirectionalLight" || objJSON.type === "SpotLight" ||
						objJSON.type === "HemisphereLight" || objJSON.type === "AreaLight" ) {

						var color = objJSON.color;
						var intensity = objJSON.intensity;
						var distance = objJSON.distance;
						var position = objJSON.position;
						var rotation = objJSON.rotation;

						switch ( objJSON.type ) {

							case 'AmbientLight':
								light = new THREE.AmbientLight( color );
								break;

							case 'PointLight':
								light = new THREE.PointLight( color, intensity, distance );
								light.position.fromArray( position );
								break;

							case 'DirectionalLight':
								light = new THREE.DirectionalLight( color, intensity );
								light.position.fromArray( objJSON.direction );
								break;

							case 'SpotLight':
								light = new THREE.SpotLight( color, intensity, distance, 1 );
								light.angle = objJSON.angle;
								light.position.fromArray( position );
								light.target.set( position[ 0 ], position[ 1 ] - distance, position[ 2 ] );
								light.target.applyEuler( new THREE.Euler( rotation[ 0 ], rotation[ 1 ], rotation[ 2 ], 'XYZ' ) );
								break;

							case 'HemisphereLight':
								light = new THREE.DirectionalLight( color, intensity, distance );
								light.target.set( position[ 0 ], position[ 1 ] - distance, position[ 2 ] );
								light.target.applyEuler( new THREE.Euler( rotation[ 0 ], rotation[ 1 ], rotation[ 2 ], 'XYZ' ) );
								break;

							case 'AreaLight':
								light = new THREE.AreaLight(color, intensity);
								light.position.fromArray( position );
								light.width = objJSON.size;
								light.height = objJSON.size_y;
								break;

						}

						parent.add( light );

						light.name = objID;
						result.lights[ objID ] = light;
						result.objects[ objID ] = light;

					// cameras

					} else if ( objJSON.type === "PerspectiveCamera" || objJSON.type === "OrthographicCamera" ) {

						pos = objJSON.position;
						rot = objJSON.rotation;
						quat = objJSON.quaternion;

						if ( objJSON.type === "PerspectiveCamera" ) {

							camera = new THREE.PerspectiveCamera( objJSON.fov, objJSON.aspect, objJSON.near, objJSON.far );

						} else if ( objJSON.type === "OrthographicCamera" ) {

							camera = new THREE.OrthographicCamera( objJSON.left, objJSON.right, objJSON.top, objJSON.bottom, objJSON.near, objJSON.far );

						}

						camera.name = objID;
						camera.position.fromArray( pos );

						if ( quat !== undefined ) {

							camera.quaternion.fromArray( quat );

						} else if ( rot !== undefined ) {

							camera.rotation.fromArray( rot );

						}

						parent.add( camera );

						result.cameras[ objID ] = camera;
						result.objects[ objID ] = camera;

					// pure Object3D

					} else {

						pos = objJSON.position;
						rot = objJSON.rotation;
						scl = objJSON.scale;
						quat = objJSON.quaternion;

						object = new THREE.Object3D();
						object.name = objID;
						object.position.fromArray( pos );

						if ( quat ) {

							object.quaternion.fromArray( quat );

						} else {

							object.rotation.fromArray( rot );

						}

						object.scale.fromArray( scl );
						object.visible = ( objJSON.visible !== undefined ) ? objJSON.visible : false;

						parent.add( object );

						result.objects[ objID ] = object;
						result.empties[ objID ] = object;

					}

					if ( object ) {

						if ( objJSON.userData !== undefined ) {

							for ( var key in objJSON.userData ) {

								var value = objJSON.userData[ key ];
								object.userData[ key ] = value;

							}

						}

						if ( objJSON.groups !== undefined ) {

							for ( var i = 0; i < objJSON.groups.length; i ++ ) {

								var groupID = objJSON.groups[ i ];

								if ( result.groups[ groupID ] === undefined ) {

									result.groups[ groupID ] = [];

								}

								result.groups[ groupID ].push( objID );

							}

						}

					}

				}

				if ( object !== undefined && objJSON.children !== undefined ) {

					handle_children( object, objJSON.children );

				}

			}

		};

		function handle_mesh( geo, mat, id ) {

			result.geometries[ id ] = geo;
			result.face_materials[ id ] = mat;
			handle_objects();

		};

		function handle_hierarchy( node, id, parent, material, obj ) {

			var p = obj.position;
			var r = obj.rotation;
			var q = obj.quaternion;
			var s = obj.scale;

			node.position.fromArray( p );

			if ( q ) {

				node.quaternion.fromArray( q );

			} else {

				node.rotation.fromArray( r );

			}

			node.scale.fromArray( s );

			// override children materials
			// if object material was specified in JSON explicitly

			if ( material ) {

				node.traverse( function ( child ) {

					child.material = material;

				} );

			}

			// override children visibility
			// with root node visibility as specified in JSON

			var visible = ( obj.visible !== undefined ) ? obj.visible : true;

			node.traverse( function ( child ) {

				child.visible = visible;

			} );

			parent.add( node );

			node.name = id;

			result.objects[ id ] = node;
			handle_objects();

		};

		function create_callback_geometry( id ) {

			return function ( geo, mat ) {

				geo.name = id;

				handle_mesh( geo, mat, id );

				counter_models -= 1;

				scope.onLoadComplete();

				async_callback_gate();

			};

		};

		function create_callback_hierachy( id, parent, material, obj ) {

			return function ( event ) {

				var result;

				// loaders which use EventDispatcher

				if ( event.content ) {

					result = event.content;

				// ColladaLoader

				} else if ( event.dae ) {

					result = event.scene;

				// UTF8Loader

				} else {

					result = event;

				}

				handle_hierarchy( result, id, parent, material, obj );

				counter_models -= 1;

				scope.onLoadComplete();

				async_callback_gate();

			};

		};

		function create_callback_embed( id ) {

			return function ( geo, mat ) {

				geo.name = id;

				result.geometries[ id ] = geo;
				result.face_materials[ id ] = mat;

			};

		};

		function async_callback_gate() {

			var progress = {

				totalModels : total_models,
				totalTextures : total_textures,
				loadedModels : total_models - counter_models,
				loadedTextures : total_textures - counter_textures

			};

			scope.callbackProgress( progress, result );

			scope.onLoadProgress();

			if ( counter_models === 0 && counter_textures === 0 ) {

				finalize();
				callbackFinished( result );

			}

		};

		function finalize() {

			// take care of targets which could be asynchronously loaded objects

			for ( var i = 0; i < target_array.length; i ++ ) {

				var ta = target_array[ i ];

				var target = result.objects[ ta.targetName ];

				if ( target ) {

					ta.object.target = target;

				} else {

					// if there was error and target of specified name doesn't exist in the scene file
					// create instead dummy target
					// (target must be added to scene explicitly as parent is already added)

					ta.object.target = new THREE.Object3D();
					result.scene.add( ta.object.target );

				}

				ta.object.target.userData.targetInverse = ta.object;

			}

		};

		var callbackTexture = function ( count ) {

			counter_textures -= count;
			async_callback_gate();

			scope.onLoadComplete();

		};

		// must use this instead of just directly calling callbackTexture
		// because of closure in the calling context loop

		var generateTextureCallback = function ( count ) {

			return function () {

				callbackTexture( count );

			};

		};

		function traverse_json_hierarchy( objJSON, callback ) {

			callback( objJSON );

			if ( objJSON.children !== undefined ) {

				for ( var objChildID in objJSON.children ) {

					traverse_json_hierarchy( objJSON.children[ objChildID ], callback );

				}

			}

		};

		// first go synchronous elements

		// fogs

		var fogID, fogJSON;

		for ( fogID in data.fogs ) {

			fogJSON = data.fogs[ fogID ];

			if ( fogJSON.type === "linear" ) {

				fog = new THREE.Fog( 0x000000, fogJSON.near, fogJSON.far );

			} else if ( fogJSON.type === "exp2" ) {

				fog = new THREE.FogExp2( 0x000000, fogJSON.density );

			}

			color = fogJSON.color;
			fog.color.setRGB( color[0], color[1], color[2] );

			result.fogs[ fogID ] = fog;

		}

		// now come potentially asynchronous elements

		// geometries

		// count how many geometries will be loaded asynchronously

		var geoID, geoJSON;

		for ( geoID in data.geometries ) {

			geoJSON = data.geometries[ geoID ];

			if ( geoJSON.type in this.geometryHandlers ) {

				counter_models += 1;

				scope.onLoadStart();

			}

		}

		// count how many hierarchies will be loaded asynchronously

		for ( var objID in data.objects ) {

			traverse_json_hierarchy( data.objects[ objID ], function ( objJSON ) {

				if ( objJSON.type && ( objJSON.type in scope.hierarchyHandlers ) ) {

					counter_models += 1;

					scope.onLoadStart();

				}

			});

		}

		total_models = counter_models;

		for ( geoID in data.geometries ) {

			geoJSON = data.geometries[ geoID ];

			if ( geoJSON.type === "cube" ) {

				geometry = new THREE.CubeGeometry( geoJSON.width, geoJSON.height, geoJSON.depth, geoJSON.widthSegments, geoJSON.heightSegments, geoJSON.depthSegments );
				geometry.name = geoID;
				result.geometries[ geoID ] = geometry;

			} else if ( geoJSON.type === "plane" ) {

				geometry = new THREE.PlaneGeometry( geoJSON.width, geoJSON.height, geoJSON.widthSegments, geoJSON.heightSegments );
				geometry.name = geoID;
				result.geometries[ geoID ] = geometry;

			} else if ( geoJSON.type === "sphere" ) {

				geometry = new THREE.SphereGeometry( geoJSON.radius, geoJSON.widthSegments, geoJSON.heightSegments );
				geometry.name = geoID;
				result.geometries[ geoID ] = geometry;

			} else if ( geoJSON.type === "cylinder" ) {

				geometry = new THREE.CylinderGeometry( geoJSON.topRad, geoJSON.botRad, geoJSON.height, geoJSON.radSegs, geoJSON.heightSegs );
				geometry.name = geoID;
				result.geometries[ geoID ] = geometry;

			} else if ( geoJSON.type === "torus" ) {

				geometry = new THREE.TorusGeometry( geoJSON.radius, geoJSON.tube, geoJSON.segmentsR, geoJSON.segmentsT );
				geometry.name = geoID;
				result.geometries[ geoID ] = geometry;

			} else if ( geoJSON.type === "icosahedron" ) {

				geometry = new THREE.IcosahedronGeometry( geoJSON.radius, geoJSON.subdivisions );
				geometry.name = geoID;
				result.geometries[ geoID ] = geometry;

			} else if ( geoJSON.type in this.geometryHandlers ) {

				var loaderParameters = {};

				for ( var parType in geoJSON ) {

					if ( parType !== "type" && parType !== "url" ) {

						loaderParameters[ parType ] = geoJSON[ parType ];

					}

				}

				var loader = this.geometryHandlers[ geoJSON.type ][ "loaderObject" ];
				loader.load( get_url( geoJSON.url, data.urlBaseType ), create_callback_geometry( geoID ), loaderParameters );

			} else if ( geoJSON.type === "embedded" ) {

				var modelJson = data.embeds[ geoJSON.id ],
					//mca texture_path = ""; //removed because textures won't be loaded with embedded facematerials
					texture_path = urlBase; //mca added

				// pass metadata along to jsonLoader so it knows the format version

				modelJson.metadata = data.metadata;

				if ( modelJson ) {

					var jsonLoader = this.geometryHandlers[ "ascii" ][ "loaderObject" ];
					var model = jsonLoader.parse( modelJson, texture_path );
					create_callback_embed( geoID )( model.geometry, model.materials );

				}

			}

		}

		// textures

		// count how many textures will be loaded asynchronously

		var textureID, textureJSON;

		for ( textureID in data.textures ) {

			textureJSON = data.textures[ textureID ];

			if ( textureJSON.url instanceof Array ) {

				counter_textures += textureJSON.url.length;

				for( var n = 0; n < textureJSON.url.length; n ++ ) {

					scope.onLoadStart();

				}

			} else {

				counter_textures += 1;

				scope.onLoadStart();

			}

		}

		total_textures = counter_textures;

		for ( textureID in data.textures ) {

			textureJSON = data.textures[ textureID ];

			if ( textureJSON.mapping !== undefined && THREE[ textureJSON.mapping ] !== undefined ) {

				textureJSON.mapping = new THREE[ textureJSON.mapping ]();

			}

			if ( textureJSON.url instanceof Array ) {

				var count = textureJSON.url.length;
				var url_array = [];

				for( var i = 0; i < count; i ++ ) {

					url_array[ i ] = get_url( textureJSON.url[ i ], data.urlBaseType );

				}

				var isCompressed = /\.dds$/i.test( url_array[ 0 ] );

				if ( isCompressed ) {

					texture = THREE.ImageUtils.loadCompressedTextureCube( url_array, textureJSON.mapping, generateTextureCallback( count ) );

				} else {

					texture = THREE.ImageUtils.loadTextureCube( url_array, textureJSON.mapping, generateTextureCallback( count ) );

				}

			} else {

				var isCompressed = /\.dds$/i.test( textureJSON.url );
				var fullUrl = get_url( textureJSON.url, data.urlBaseType );
				var textureCallback = generateTextureCallback( 1 );

				if ( isCompressed ) {

					texture = THREE.ImageUtils.loadCompressedTexture( fullUrl, textureJSON.mapping, textureCallback );

				} else {

					texture = THREE.ImageUtils.loadTexture( fullUrl, textureJSON.mapping, textureCallback );

				}

				if ( THREE[ textureJSON.minFilter ] !== undefined )
					texture.minFilter = THREE[ textureJSON.minFilter ];

				if ( THREE[ textureJSON.magFilter ] !== undefined )
					texture.magFilter = THREE[ textureJSON.magFilter ];

				if ( textureJSON.anisotropy ) texture.anisotropy = textureJSON.anisotropy;

				if ( textureJSON.repeat ) {

					texture.repeat.set( textureJSON.repeat[ 0 ], textureJSON.repeat[ 1 ] );

					if ( textureJSON.repeat[ 0 ] !== 1 ) texture.wrapS = THREE.RepeatWrapping;
					if ( textureJSON.repeat[ 1 ] !== 1 ) texture.wrapT = THREE.RepeatWrapping;

				}

				if ( textureJSON.offset ) {

					texture.offset.set( textureJSON.offset[ 0 ], textureJSON.offset[ 1 ] );

				}

				// handle wrap after repeat so that default repeat can be overriden

				if ( textureJSON.wrap ) {

					var wrapMap = {
						"repeat": THREE.RepeatWrapping,
						"mirror": THREE.MirroredRepeatWrapping
					};

					if ( wrapMap[ textureJSON.wrap[ 0 ] ] !== undefined ) texture.wrapS = wrapMap[ textureJSON.wrap[ 0 ] ];
					if ( wrapMap[ textureJSON.wrap[ 1 ] ] !== undefined ) texture.wrapT = wrapMap[ textureJSON.wrap[ 1 ] ];

				}

			}

			result.textures[ textureID ] = texture;

		}

		// materials

		var matID, matJSON;
		var parID;

		for ( matID in data.materials ) {

			matJSON = data.materials[ matID ];

			for ( parID in matJSON.parameters ) {

				if ( parID === "envMap" || parID === "map" || parID === "lightMap" || parID === "bumpMap" ) {

					matJSON.parameters[ parID ] = result.textures[ matJSON.parameters[ parID ] ];

				} else if ( parID === "shading" ) {

					matJSON.parameters[ parID ] = ( matJSON.parameters[ parID ] === "flat" ) ? THREE.FlatShading : THREE.SmoothShading;

				} else if ( parID === "side" ) {

					if ( matJSON.parameters[ parID ] == "double" ) {

						matJSON.parameters[ parID ] = THREE.DoubleSide;

					} else if ( matJSON.parameters[ parID ] == "back" ) {

						matJSON.parameters[ parID ] = THREE.BackSide;

					} else {

						matJSON.parameters[ parID ] = THREE.FrontSide;

					}

				} else if ( parID === "blending" ) {

					matJSON.parameters[ parID ] = matJSON.parameters[ parID ] in THREE ? THREE[ matJSON.parameters[ parID ] ] : THREE.NormalBlending;

				} else if ( parID === "combine" ) {

					matJSON.parameters[ parID ] = matJSON.parameters[ parID ] in THREE ? THREE[ matJSON.parameters[ parID ] ] : THREE.MultiplyOperation;

				} else if ( parID === "vertexColors" ) {

					if ( matJSON.parameters[ parID ] == "face" ) {

						matJSON.parameters[ parID ] = THREE.FaceColors;

					// default to vertex colors if "vertexColors" is anything else face colors or 0 / null / false

					} else if ( matJSON.parameters[ parID ] ) {

						matJSON.parameters[ parID ] = THREE.VertexColors;

					}

				} else if ( parID === "wrapRGB" ) {

					var v3 = matJSON.parameters[ parID ];
					matJSON.parameters[ parID ] = new THREE.Vector3( v3[ 0 ], v3[ 1 ], v3[ 2 ] );

				}

			}

			if ( matJSON.parameters.opacity !== undefined && matJSON.parameters.opacity < 1.0 ) {

				matJSON.parameters.transparent = true;

			}

			if ( matJSON.parameters.normalMap ) {

				var shader = THREE.ShaderLib[ "normalmap" ];
				var uniforms = THREE.UniformsUtils.clone( shader.uniforms );

				var diffuse = matJSON.parameters.color;
				var specular = matJSON.parameters.specular;
				var ambient = matJSON.parameters.ambient;
				var shininess = matJSON.parameters.shininess;

				uniforms[ "tNormal" ].value = result.textures[ matJSON.parameters.normalMap ];

				if ( matJSON.parameters.normalScale ) {

					uniforms[ "uNormalScale" ].value.set( matJSON.parameters.normalScale[ 0 ], matJSON.parameters.normalScale[ 1 ] );

				}

				if ( matJSON.parameters.map ) {

					uniforms[ "tDiffuse" ].value = matJSON.parameters.map;
					uniforms[ "enableDiffuse" ].value = true;

				}

				if ( matJSON.parameters.envMap ) {

					uniforms[ "tCube" ].value = matJSON.parameters.envMap;
					uniforms[ "enableReflection" ].value = true;
					uniforms[ "uReflectivity" ].value = matJSON.parameters.reflectivity;

				}

				if ( matJSON.parameters.lightMap ) {

					uniforms[ "tAO" ].value = matJSON.parameters.lightMap;
					uniforms[ "enableAO" ].value = true;

				}

				if ( matJSON.parameters.specularMap ) {

					uniforms[ "tSpecular" ].value = result.textures[ matJSON.parameters.specularMap ];
					uniforms[ "enableSpecular" ].value = true;

				}

				if ( matJSON.parameters.displacementMap ) {

					uniforms[ "tDisplacement" ].value = result.textures[ matJSON.parameters.displacementMap ];
					uniforms[ "enableDisplacement" ].value = true;

					uniforms[ "uDisplacementBias" ].value = matJSON.parameters.displacementBias;
					uniforms[ "uDisplacementScale" ].value = matJSON.parameters.displacementScale;

				}

				uniforms[ "uDiffuseColor" ].value.setHex( diffuse );
				uniforms[ "uSpecularColor" ].value.setHex( specular );
				uniforms[ "uAmbientColor" ].value.setHex( ambient );

				uniforms[ "uShininess" ].value = shininess;

				if ( matJSON.parameters.opacity ) {

					uniforms[ "uOpacity" ].value = matJSON.parameters.opacity;

				}

				var parameters = { fragmentShader: shader.fragmentShader, vertexShader: shader.vertexShader, uniforms: uniforms, lights: true, fog: true };

				material = new THREE.ShaderMaterial( parameters );

			} else {

				material = new THREE[ matJSON.type ]( matJSON.parameters );

			}

			material.name = matID;

			result.materials[ matID ] = material;

		}

		// second pass through all materials to initialize MeshFaceMaterials
		// that could be referring to other materials out of order

		for ( matID in data.materials ) {

			matJSON = data.materials[ matID ];

			if ( matJSON.parameters.materials ) {

				var materialArray = [];

				for ( var i = 0; i < matJSON.parameters.materials.length; i ++ ) {

					var label = matJSON.parameters.materials[ i ];
					materialArray.push( result.materials[ label ] );

				}

				result.materials[ matID ].materials = materialArray;

			}

		}

		// objects ( synchronous init of procedural primitives )

		handle_objects();

		// defaults

		if ( result.cameras && data.defaults.camera ) {

			result.currentCamera = result.cameras[ data.defaults.camera ];

		}

		if ( result.fogs && data.defaults.fog ) {

			result.scene.fog = result.fogs[ data.defaults.fog ];

		}

		// synchronous callback

		scope.callbackSync( result );

		// just in case there are no async elements

		async_callback_gate();

	}

};


James Jean will release this stunning new art print next week. "Horse IV" is a 20″ x 21″ giclee with screenprinted accents for $175. It will be sold for 24 hours as a timed edition starting Tuesday, March 31st at 8am Pacific Time. Visit JamesJean.com.
Just wondering on the off chance, do you have any of this James Jean 1V horse poster. Thanks LIsa.


text:
by: Clifford Mitchell
Artists showcase their talents in a gallery to sell their product. A seedstock producer's display case is the sale ring where potential customers appraise his offering. For the artist, a curator facilitates activity and helps appraise the product. The seedstock producer relies on a professional sale manager to provide a game plan and pay attention to detail.
Only after years of experience can an artist gain enough momentum to have a private exhibition of this magnitude. Purebred breeders have to build the same reputation to market cattle in an arena of this magnitude, providing quality in volume.
There are many factors that dictate if a seedstock operation is ready for this type of showcase. Purebred breeders consult sales professionals to help determine the most profitable time to set their date and have their sale.
"It is our place to tell a man if he's not ready for a sale. We help establish his date and market his cattle at the most opportune time," says Eddie Sims, National Cattle Services, Elgin, Oklahoma. Sims is in his 36th year of marketing purebred seedstock.
To set the stage for a sale, certain questions have to be answered. To market cattle effectively the sales professional has to have an idea what the goal is for the operation.
"I want to know what market we're trying to attack. We have to be goal setters first. It is hard to attain that goal if we don't know where a producer wants to go," says Ken Holloway, American Cattle Services, Chattanooga, Okla. Holloway began marketing purebred livestock in 1971.
The list of details the sale manager must cover is long, but the ability to accomplish these goals is what separates these professionals in their field. Working to position the seedstock firm for success is always the number one goal.
"There is a lot of what I call dry-labbing. What needs to be done, do we have current information etc., it is a detailed process," Holloway says. "The most challenging question I am often asked is how do I mate cattle to get ready for the sale. I have to visit with breeders ahead of time to make sure there is a product for every customer."
"We have to help make breeding decisions and get cattle properly prepared, which is a big challenge in this business," Sims says. "I encourage my customers to get involved in their local cattlemen's association, buy ads in breeder directories and put up farm signs. There is so much available, there is no reason not to take advantage of an opportunity."
Creating an advertising budget and placing advertisements is critical to the success of the sale. Budgets are often created with a projected sale gross in mind, and then administrated to effectively cover the designated market area.
"We develop a budget for every sale. It usually runs hand-in-hand with the quality of cattle we are selling. We try to reach an audience that fits the sale bill and type of cattle we're selling," Sims says. "I am a firm believer in the publication people and getting the sales staff we want."
"Every sale is a little different. First we have to identify what we need to spend, then what area we need to cover. If it is it local, regional or national, we have to adjust the advertising for the offering to keep a strong customer base," Holloway says. "Identify the product that is available, then identify the publications where we get the most bang for our buck and what service the publication will provide the auction."
Seedstock producers look to the sale manager's experience to help with design and placement of timely advertising to help market their product. This will help create an environment that is conducive to selling cattle.
"I look to the sale manager to develop an ad budget, design and place ads and hire ring service. He's a professional and does it all year long, where I do it once every year," says Jerry Wulf, Wulf Limousin, Morris, Minn.
"The sale manager designs the ads and creates an ad budget that covers all the bases to use the advertising dollars most effectively," says Billy Hall, Ratcliff Angus Ranch, Vinita, Okla.
In order to properly conduct the sale it is a building process that works right up until sale day. Display areas and facilities are very important to showcase the product.
"It is really important to have the facilities set right to display the cattle attractively and to move cattle with ease," Holloway says. "We want an auction with action and good facilities are critical."
"People who have never had a sale do not have the concept of what is about to take place," Sims says. "Once you've had a sale, you have a deeper appreciation for the guys sorting and penning the cattle."
Displaying the product to the sale manager is just like the motif the art curator has to establish to adequately promote a piece of artwork. The live animal presents certain challenges, but to get the most dollars, experience will usually help display cattle where they will get the attention of the buying public. A proper display also takes into account the manner in which the cattle will be sold.
"The sort you put on the cattle and how they are displayed will affect the results at the end of the day," Sims says. "You need good cattle in each pen. This is vital to get the most out of what you're selling that day."
"The more display pens that are available, the easier it is to make a uniform presentation of the offering," Holloway says. "More uniformity in each pen allows potential customers to move from pen to pen and find the good ones."
"The sale manager can look at the cattle from a marketing standpoint and appraise each individual," Hall says. "This will help us sort cattle and present them in the best way possible."
Once the cattle are sorted, the most difficult challenge every sale manager faces is creating a sale order that will help build the needed momentum for a successful sale. Many indicators factor into the sale manager's decision when it is time to build a sale order that will effectively merchandise the product. It is not an exact science, but this is another place where experience plays a huge role in determining the final order.
"The sale order is based on a lot of things. We get a feel for the sale order by response, not only with us, but what the ranch staff knows. All the facts we have available on the cattle that day," Holloway says. "Sometimes if you watch the people around the display pens you can get a feel for what's creating interest by their body language."
"No two sales are the same, that is the challenge with making a sale order," Sims says. "At some sales you can make a sale order, but if you have a good set of cattle all the way through it doesn't matter."
The sale order can easily be compared to a game plan developed by a coach to put his team in a position to win. Executing every stage of the plan to a degree of preciseness usually leads to success.
"You have to strategically make the best game plan. I am a firm believer in publishing a sale order. If a man takes his time to be at a sale he has the right to know when cattle are selling," Sims says. "I'll be the first to admit some days the crowd fools us, public auctions keep you on your toes. Sometimes we have to make adjustments to appease the buying public."
"It is important cattle are displayed in sale order fashion so the top cattle with sell first and you don't leave a good one down in the order. The most popular cattle set the stage and build momentum for the sale," Holloway says. "Each animal has an ERV (estimated ring value) based on their worth that day."
Keeping the momentum is a key element in having a successful production sale. It takes more than just good cattle to keep bidders active at ringside.
"You have to have a supplement sheet with the most current information available to the crowd because they will buy with more enthusiasm. It is also important you have this information available to the auctioneer so all he has in mind is selling cattle for the most money," Holloway says. "We want an auction with action, so it is important to have a good crew that has an animal waiting when we're ready for it."
Handling order money for sight unseen purchases falls under the sale manager's job description. Each marketing agent takes this part of the business very seriously because breeders unable to attend the sale are relying on their knowledge to spend their money wisely.
"We have more order money today than we've seen in the past with phone bids and Internet capabilities," Sims says. "It is a delicate situation, we have to handle the bids with a high degree of privacy and integrity. At the same time, we may have to call another client back to give him an opportunity to buy cattle. With cell phones it is a lot easier to have people on the phone during the actual auction and let them make their own bidding decision."
"Each individual usually has a specific goal in mind and I have to find the cattle that meet their needs," Holloway says. "It doesn't bother me to tell a potential customer I can't send him that animal. I don't intend to lose a friend over a cow. Tell it like it is. Be accurate and honest with potential customers. It may not help that day, but it will pay off down the road."
At the end of the day, sales are called a success based on different things. Averages can be deceiving depending on the range in sales price. The bottom line is the gross dollars produced by that offering.
"It is the gross at the end of the day, not what the top ten lots brought, not even the average, that measures success," Sims says. "I grade a sale by its gross because that is what I have based my expenses on. Sadly, in the purebred business success is still judged by the sale average."
With the nature of the seedstock business, there is a certain amount of change that goes on all the time. The veteran sale managers feel the buying public may be in a better position today to improve their program.
"The tools of selection have become much more sophisticated today," Holloway says. "Customers can buy and sell with a much higher degree of certainty thanks to science and technology."
"The technology and information demanded today has changed the business. We have a better balance, with more information available on profitability," Sims says. "The genetics have really changed due to embryo transfer. Whether you have five cows or 500, you can have the same genetics."
Maybe the most important phase in the whole process is the evaluation of the sale. This is a time the owners and sales team can critique the events of the day and start making plans for next year.
"Often times we'll sit down that evening and review the day's events because this is the best time to do it when it's fresh on our mind. We look at what we can do better," Holloway says. "To evaluate the sale, we have to break it down and analyze where cattle went and why they went there."
"If you are going to make changes to the breeding program it has to start then because it takes that long to make the product," Wulf says. "Things like red to black ratio, are we on the right date and what added management we have to do to have the product available that is in demand."
"It is extremely important, to succeed it has to be done. It helps better everything from genetic selection, to display of the cattle and where we need to advertise," Hall says. "By critiquing what you've done it helps you get better. It takes a whole year to prepare for one sale. Sale day should be the easiest because all the homework we do together is what counts to make the sale successful."
Most professional cattlemen who employ a sale manager realize it takes a team effort to get the job done. Just because you have a sale manager does not automatically lead to a successful sale. Each party has to hold up their end of the bargain to be successful.
"The sale manager can't take mediocrity and make a great sale, but he can usually take anything and make it somewhat better," Wulf says. "It is my job to produce a marketable product and his job to market it to its fullest potential. We have to work together to accomplish the same goal."
"We have to exchange ideas and be on the same page to market our product," Hall says. "We rely on his experience and the professional manner he conducts business before, during and after the sale."
Repeat business and building a clientele is the best reward a sale manager can accomplish. Professional is the best word that describes these marketers who wear many different hats throughout the year. Whether it is an art curator preparing for the big exhibition or the sale manager working to market seedstock, people still make the difference.
"The greatest joy I have is the people I have worked with for many years," Sims says. "Repeat business is very important because it shows people have confidence in us year after year."
"We have to be courteous, informative and enthusiastic and help the firm put its best foot forward," Holloway says. "We operate with a high degree of integrity. This comes easy when you enjoy what you're doing. I have been fortunate to work with lots of people that bring professionalism to the job every day."
Send mail to webmaster@cattletoday.com with questions or comments about this web site.
Copyright © 1998-2004 CATTLE TODAY, INC.

redpajama_set_name: RedPajamaCommonCrawl


Bring the sunshine inside with the range of stunning yellow paint from Homebase.
Available in tin sizes of 1L, you'll be able to create a bright feature wall that really packs in the wow factor. Yellow is a colour that instantly livens up a space and our collection of yellow emulsion is ideal for your home. Pair chalky yellow eggshell paint with deep navy furnishings and dark wood for your dining room, or choose a soft pastel shade paired with white furniture and plenty of cuddly toys for a nursery with.
From bright shades to more subdued hues, explore the choice of yellow paint available and create that feeling of summer in your home.