/***************************************************	abstract 3d engine for javascript		(c) 2009 severin klaus, switzerland		all rights reserved		sklaus@betabong.com				****************************************************/// **********// SCENE//// Creates 3d scene (Contains Points, Lines and Triangles)function Scene3D( perspective ) {	// DATA	this.groups = new Array();	// DYNAMIC CONSTANTS (sounds weird, eh?!)	perspective == null ? this.perspective = 300 : this.perspective = perspective;		this.alphaBackLimit = 100;	this.alphaFrontLimit = -100;		this.soundRadiusFactor = 5;		this.showPoints = true;	this.showObjects = true;	this.doZClipping = false;	}Scene3D.prototype.addGroup = function( group ) {		this.groups.push( group );}Scene3D.prototype.removeGroup = function( group ) {	// Finds the group in the groups array and replaces it with the	// last item in the array (or simply removes it if it's the last item)	for ( var i=0 ; i<this.groups.length ; i++ ) {		if ( this.groups[i] == group ) {			if ( i != (this.groups.length-1) ) {				this.groups[i] = this.groups.pop();				return true;			} else {				var temp = this.groups.pop();				delete temp;				return true;			}		}	}		return false; // Group could not be found and thous not be removed}			Scene3D.prototype.getScalar = function( point ) {		return ( 1 / ( point.z / this.perspective + 1) );}Scene3D.prototype.project = function() {		this.alphaScalar = ( this.alphaFrontLimit - this.alphaBackLimit ) / 100;		// Projecting Points	for ( var group=0 ; group<this.groups.length ; group++ ) {		var g = this.groups[ group ];				g.project();				for ( var point=0 ; point<g.points.length ; point++ ) {						g.points[ point ].project();					}			}	// Drawing Objects (dependent on points -> lines, shapes, ...)		for ( var group=0 ; group<this.groups.length ; group++ ) {		var g = this.groups[ group ];				for ( var i=0 ; i<g.objects.length ; i++ ) {						g.objects[ i ].project();					}	}	}// **********// GROUP//// Creates 3d scene (Contains Points, Lines and Triangles)function Group3D( scene , x , y , z ) {		// DATA	this.points = new Array();	this.objects = new Array();	x == 0 ? this.x = 0 : this.x = x;	y == 0 ? this.y = 0 : this.y = y;	z == 0 ? this.z = 0 : this.z = z;	this.centerPoint = new Vector3D( this.x , this.y , this.z );		this.xrot = 0;	this.yrot = 0;	this.zrot = 0;		this.xscale = 1;	this.yscale = 1;	this.zscale = 1;		this.axis = new Object();	this.axis.x = new Vector3D( 1 , 0 , 0 );	this.axis.y = new Vector3D( 0 , 1 , 0 );	this.axis.z = new Vector3D( 0 , 0 , 1 );	this.translation = null;	this.rotation = null;	this.scaling = null;		// ADD TO SCENE		scene.addGroup( this );	this.scene = scene;}Group3D.prototype.project = function() {	for ( var i=0 ; i<this.points.length ; i++ ) {		this.points[i].localToGlobal();	}}// (BUILD:) Add primary elements to groupGroup3D.prototype.addPoint = function( point ) {	this.points.push( point );	point.group = this;}// i keep this for backward compabilityGroup3D.prototype.addLine = function( line ) {	this.objects.push( line );}Group3D.prototype.addObject = function( obj ) {	this.objects.push( tri );}Group3D.prototype.addGroup = function( group ) {	// To be implemented}Group3D.prototype.remove = function() {	for ( var i in this.points ) this.points[i].movie.removeMovieClip();	for ( var i in this.objects ) this.objects[i].movie.removeMovieClip();		this.scene.removeGroup( this );}// (MODIFY:) Rotate, scale and move the groupGroup3D.prototype.setCenter = function( vector ) {	this.centerPoint = vector;}Group3D.prototype.getCenter = function() {	return this.centerPoint;}Group3D.prototype.translate = function( distx , disty , distz ) {		this.translation = new Translation3D ( distx , disty , distz );	this.translation.transform( this.centerPoint );	this.translation.transform( this );}Group3D.prototype.scale = function( xscale , yscale , zscale ) {	this.xscale *= xscale;	this.yscale *= yscale;	this.zscale *= zscale;		this.scaling = new Scaling3D( this.xscale , this.yscale , this.zscale );	// Scale the points (relative to the group's center point -> this doesn't	// actually scale any movie clip, just the points' coordinates		for ( var i in this.axis ) {		this.scaling.transform( this.axis[ i ] );	}}Group3D.prototype.rotate = function( theaxis , angle ) {	// Be aware that this.xrot etc. won't reflect the correct rotation	// anymore after use of this method. This is a thing to be implemented	// or dropped.	// Create new rotation object around the according relative axis		this.rotation = new Rotation3D( this.axis[ theaxis ] , angle );		// Rotate the axis (so they stay relative =-)		for ( var i in this.axis ) {		this.rotation.transform( this.axis[ i ] );	}}Group3D.prototype.rotateVector = function( unitVector , angle ) {	// create new rotation around vector with angle	this.rotation = new Rotation3D( unitVector , angle );		// Rotate the axis (so they stay relative =-)		for ( var i in this.axis ) {		this.rotation.transform( this.axis[ i ] );	}}		Group3D.prototype.transform = function( transformation ) {	for ( var i=0 ; i<this.points.length ; i++ ) {		this.points[i].translate( -this.centerPoint.x , -this.centerPoint.y , -this.centerPoint.z );		transformation.transform( this.points[i] );		this.points[i].translate( this.centerPoint.x , this.centerPoint.y , this.centerPoint.z );	}}		// **********// POINT 3D//// Creates 3d point at coordinates x,y,zfunction Point3D( x , y , z , group ) {		this.group = group;		this.local = new Vector3D( x , y , z );		this.x = x;	this.y = y;	this.z = z;	this.transformation = null;		this.xReal = null;	this.yReal = null;	this.alphaReal = null;	this.scaleReal = null;	}// calculate from local group coordinates to global scene coordinatesPoint3D.prototype.localToGlobal = function() {	// this little substitution makes it 10% faster!!!	var xs = this.group.xscale * this.local.x;	var ys = this.group.yscale * this.local.y;	var zs = this.group.zscale * this.local.z;	this.x = xs * this.group.axis.x.x + ys * this.group.axis.y.x + zs * this.group.axis.z.x + this.group.x;	this.y = xs * this.group.axis.x.y + ys * this.group.axis.y.y + zs * this.group.axis.z.y + this.group.y;	this.z = xs * this.group.axis.x.z + ys * this.group.axis.y.z + zs * this.group.axis.z.z + this.group.z;}		// Moves the point (world coordinates)Point3D.prototype.translate = function( distx , disty , distz ) {	this.x += distx;	this.y += disty;	this.z += distz;}// Projects the point onto the scene// (3d -> 2d)Point3D.prototype.project = function() {	thisScene = this.group.scene;		// project the virtual 3d point to 2d	var scalar = thisScene.getScalar( this );	this.xReal = this.x * scalar;	this.yReal = - this.y * scalar;	this.scaleReal = scalar * 0.76;	this.alphaReal = ( this.z - thisScene.alphaBackLimit ) / thisScene.alphaScalar;}Point3D.prototype.toString = function( precision ) {	if ( precision == null ) precision = 10;	var p = this.local;	return '' + [ Math.round(p.x * precision) / precision , Math.round(p.y * precision) / precision , Math.round(p.z * precision) / precision ].join(',');}			// **********// VECTOR//// Creates simple and stupid 3d vectorfunction Vector3D( dx , dy , dz ) {	this.x = dx;	this.y = dy;	this.z = dz;}Vector3D.prototype.toString = function( precision ) {	if ( precision == null ) precision = 10;	var p = this;	return '' + [ Math.round(p.x * precision) / precision , Math.round(p.y * precision) / precision , Math.round(p.z * precision) / precision ].join(',');}// ----------------------------------------------------------------// ROTATION AROUND VECTOR// ----------------------------------------------------------------// Creates transformation object for rotation around vector a,b,c (through 0,0,0) and angle function Rotation3D( vector , angle ) {	var a = vector.x;	var b = vector.y;	var c = vector.z;		// make vector a,b,c, a unit vector	var f = Math.sqrt( a*a + b*b + c*c );	if ( f != 0 ) {		a /= f;		b /= f;		c /= f;	} else {		// don't rotate, so take any unit vector and set angle to zero.		// this is just to prevent a division by zero error (btw)		a = 1;		b = 0;		c = 0;		angle = 0;	}			// store repeated calculations in variables (to make it faster)	var sin = Math.sin( angle );	var cos = Math.cos( angle );	var i = 1.0 - cos;	var a_sin = a * sin;	var b_sin = b * sin;	var c_sin = c * sin;		var a_i = a * i;	var b_i = b * i;	var c_i = c * i;			// create the rotation matrix	// i used an array before, but it's 1% faster using straight variables :-)		this.m_0_0 = a*a_i + cos;	this.m_0_1 = b*a_i - c_sin;	this.m_0_2 = c*a_i + b_sin;	this.m_1_0 = a*b_i + c_sin;	this.m_1_1 = b*b_i + cos;	this.m_1_2 = c*b_i - a_sin;	this.m_2_0 = a*c_i - b_sin;	this.m_2_1 = b*c_i + a_sin;	this.m_2_2 = c*c_i + cos;}Rotation3D.prototype.transform = function( point ) {	if ( point == null ) return;	var x = point.x * this.m_0_0 + point.y * this.m_0_1 + point.z * this.m_0_2;	var y = point.x * this.m_1_0 + point.y * this.m_1_1 + point.z * this.m_1_2;	var z = point.x * this.m_2_0 + point.y * this.m_2_1 + point.z * this.m_2_2;	point.x = x;	point.y = y;	point.z = z;}function Scaling3D( factor ) {	this.factor = factor;}Scaling3D.prototype.transform = function( point ) {	if ( point.scaleFactor == null ) {		point.scaleFactor = 1;	}		if ( point.scaleFactor != this.factor ) {		var f = this.factor / point.scaleFactor;		point.x *= f;		point.y *= f;		point.z *= f;		point.scaleFactor = this.factor;	}}function Translation3D( distx , disty , distz ) {	this.distx = distx;	this.disty = disty;	this.distz = distz;}Translation3D.prototype.transform = function( point ) {	point.x += this.distx;	point.y += this.disty;	point.z += this.distz;}function vorzeichen() {	if ( Math.random() > 0.5 ) 		return -1;	else		return 1;}