提交 cf37a8cc 编写于 作者: A alteredq

First integration step: something appeared on the screen ;)

Otherwise things are very much work in progress, expect everything to be broken.
上级 df513e04
此差异已折叠。
此差异已折叠。
此差异已折叠。
/**
* @author mikael emtinger / http://gomo.se/
*/
THREE.Animation = function( root, data ) {
this.root = root;
this.data = data;
this.hierarchy = [];
this.startTime = 0;
this.isPlaying = false;
this.loop = true;
// need to initialize data?
if( !this.data.initialized )
THREE.AnimationHandler.initData( this.data );
// setup hierarchy
if( root instanceof THREE.SkinnedMesh ) {
for( var b = 0; b < this.root.bones.length; b++ )
this.hierarchy.push( this.root.bones[ b ] );
}
else {
// parse hierarchy and match against animation (somehow)
}
}
/*
* Play
*/
THREE.Animation.prototype.play = function( loop ) {
if( !this.isPlaying ) {
this.isPlaying = true;
this.startTime = new Date().getTime() * 0.001;
// reset key cache
for( var h = 0; h < this.hierarchy.length; h++ ) {
this.hierarchy[ h ].useQuaternion = true;
this.hierarchy[ h ].autoUpdateMatrix = true;
if( this.hierarchy[ h ].prevKey === undefined ) {
this.hierarchy[ h ].prevKey = { pos: 0, rot: 0, scl: 0 };
this.hierarchy[ h ].nextKey = { pos: 0, rot: 0, scl: 0 };
}
this.hierarchy[ h ].prevKey.pos = this.data.hierarchy[ h ].keys[ 0 ];
this.hierarchy[ h ].prevKey.rot = this.data.hierarchy[ h ].keys[ 0 ];
this.hierarchy[ h ].prevKey.scl = this.data.hierarchy[ h ].keys[ 0 ];
this.hierarchy[ h ].nextKey.pos = this.getNextKeyWith( "pos", h, 1 );
this.hierarchy[ h ].nextKey.rot = this.getNextKeyWith( "rot", h, 1 );
this.hierarchy[ h ].nextKey.scl = this.getNextKeyWith( "scl", h, 1 );
}
this.update();
THREE.AnimationHandler.add( this );
}
};
/*
* Pause
*/
THREE.Animation.prototype.pause = function() {
THREE.AnimationHandler.remove( this );
// todo
}
/*
* Stop
*/
THREE.Animation.prototype.stop = function() {
this.isPlaying = false;
THREE.AnimationHandler.remove( this );
}
/*
* Update
*/
THREE.Animation.prototype.update = function( time ) {
// todo: add input time
// early out
if( !this.isPlaying ) return;
// vars
var types = [ "pos", "rot", "scl" ];
var scale;
var relative;
var vector;
var prevXYZ, nextXYZ;
var object;
var frame;
var JIThierarchy = this.data.JIT.hierarchy;
// update
var currentTime = new Date().getTime() * 0.001 - this.startTime;
var unloopedCurrentTime = currentTime;
// looped?
if( currentTime > this.data.length ) {
while( currentTime > this.data.length )
currentTime -= this.data.length;
this.startTime = new Date().getTime() * 0.001 - currentTime;
currentTime = new Date().getTime() * 0.001 - this.startTime;
}
frame = Math.min( parseInt( currentTime * this.data.fps ), parseInt( this.data.length * this.data.fps ));
// update
for( var h = 0, hl = this.hierarchy.length; h < hl; h++ )
{
object = this.hierarchy[ h ];
if( JIThierarchy[ h ][ frame ] !== undefined ) {
object.skinMatrix = JIThierarchy[ h ][ frame ];
object.autoUpdateMatrix = false;
object.matrixNeedsToUpdate = false;
this.root.boneMatrices[ h ] = object.skinMatrix.flatten32;
}
else {
for( var t = 0; t < 3; t++ ) {
// get keys
var type = types[ t ];
var prevKey = object.prevKey[ type ];
var nextKey = object.nextKey[ type ];
// switch keys?
if( nextKey.time < unloopedCurrentTime ) {
// did we loop?
if( currentTime < unloopedCurrentTime ) {
if( this.loop ) {
prevKey = this.data.hierarchy[ h ].keys[ 0 ];
nextKey = this.getNextKeyWith( type, h, 1 );
}
else {
this.stop();
return;
}
}
else {
do {
prevKey = nextKey;
nextKey = this.getNextKeyWith( type, h, nextKey.index + 1 );
}
while( nextKey.time < currentTime )
}
object.prevKey[ type ] = prevKey;
object.nextKey[ type ] = nextKey;
}
// interpolate rot (quaternion slerp)
object.autoUpdateMatrix = true;
object.matrixNeedsToUpdate = true;
scale = ( currentTime - prevKey.time ) / ( nextKey.time - prevKey.time );
prevXYZ = prevKey[ type ];
nextXYZ = nextKey[ type ];
if( type === "rot" ) {
if( scale < 0 || scale > 1 )
console.log( "Scale out of bounds:" + scale );
THREE.Quaternion.slerp( prevXYZ, nextXYZ, object.quaternion, scale );
}
// lerp pos/scl
else {
vector = type === "pos" ? object.position : object.scale;
vector.x = prevXYZ[ 0 ] + ( nextXYZ[ 0 ] - prevXYZ[ 0 ] ) * scale;
vector.y = prevXYZ[ 1 ] + ( nextXYZ[ 1 ] - prevXYZ[ 1 ] ) * scale;
vector.z = prevXYZ[ 2 ] + ( nextXYZ[ 2 ] - prevXYZ[ 2 ] ) * scale;
}
}
}
}
// update JIT?
if( JIThierarchy[ 0 ][ frame ] === undefined ) {
console.log(this.hierarchy);
this.hierarchy[ 0 ].update( undefined, true );
for( var h = 0; h < this.hierarchy.length; h++ )
JIThierarchy[ h ][ frame ] = this.hierarchy[ h ].skinMatrix.clone();
}
};
/*
* Update Object
*/
THREE.Animation.prototype.updateObject = function( h, currentTime, unloopedCurrentTime ) {
}
THREE.Animation.prototype.getNextKeyWith = function( type, h, key ) {
var keys = this.data.hierarchy[ h ].keys;
for( ; key < keys.length; key++ ) {
if( keys[ key ][ type ] !== undefined )
return keys[ key ];
}
return this.data.hierarchy[ h ].keys[ 0 ];
}
/**
* @author mikael emtinger / http://gomo.se/
*/
THREE.AnimationHandler = (function() {
var playing = [];
var that = {};
//--- update ---
that.update = function( time ) {
for( var i = 0; i < playing.length; i++ )
playing[ i ].update( time );
};
//--- add ---
that.add = function( animation ) {
if( playing.indexOf( animation ) === -1 )
playing.push( animation );
};
//--- remove ---
that.remove = function( animation ) {
var index = playing.indexOf( animation );
if( index !== -1 )
playing.splice( childIndex, 1 );
};
//--- init data ---
that.initData = function( data ) {
if( data.initialized === true )
return;
// loop through all keys
for( var h = 0; h < data.hierarchy.length; h++ ) {
for( var k = 0; k < data.hierarchy[ h ].keys.length; k++ ) {
// remove minus times
if( data.hierarchy[ h ].keys[ k ].time < 0 )
data.hierarchy[ h ].keys[ k ].time = 0;
// set index
data.hierarchy[ h ].keys[ k ].index = k;
// create quaternions
if( data.hierarchy[ h ].keys[ k ].rot !== undefined &&
!(data.hierarchy[ h ].keys[ k ].rot instanceof THREE.Quaternion )) {
var quat = data.hierarchy[ h ].keys[ k ].rot;
data.hierarchy[ h ].keys[ k ].rot = new THREE.Quaternion( quat[0], quat[1], quat[2], quat[3] );
}
}
}
// JIT
var lengthInFrames = parseInt( data.length * data.fps, 10 );
data.JIT = {};
data.JIT.hierarchy = [];
for( var h = 0; h < data.hierarchy.length; h++ )
data.JIT.hierarchy.push( new Array( lengthInFrames ));
// done
data.initialized = true;
};
return that;
}());
/**
* @author mr.doob / http://mrdoob.com/
* @author mikael emtinger / http://gomo.se/
*/
THREE.Camera = function ( fov, aspect, near, far ) {
THREE.Camera = function( FOV, aspect, zNear, zFar, renderer, target ) {
// call super
THREE.Object3D.call( this );
// set arguments
this.FOV = FOV || 50;
this.aspect = aspect || 1.0;
this.zNear = zNear || 0.1;
this.zFar = zFar || 2000;
this.screenCenterX = 0;
this.screenCenterY = 0;
this.target = target || new THREE.Object3D();
this.useTarget = true;
this.up = new THREE.Vector3( 0, 1, 0 );
// init
this.inverseMatrix = new THREE.Matrix4();
this.projectionMatrix = null;
this.fov = fov;
this.aspect = aspect;
this.near = near;
this.far = far;
this.updateProjectionMatrix();
}
this.position = new THREE.Vector3();
this.target = { position: new THREE.Vector3() };
THREE.Camera.prototype = new THREE.Object3D();
THREE.Camera.prototype.constructor = THREE.Camera;
THREE.Camera.prototype.supr = THREE.Object3D.prototype;
this.autoUpdateMatrix = true;
/*
* Update projection matrix
*
* TODO: make it work also for ortho camera
*/
this.projectionMatrix = null;
this.matrix = new THREE.Matrix4();
THREE.Camera.prototype.updateProjectionMatrix = function() {
this.projectionMatrix = THREE.Matrix4.makePerspective( this.FOV, this.aspect, this.zNear, this.zFar );
this.up = new THREE.Vector3( 0, 1, 0 );
}
this.tmpVec = new THREE.Vector3();
this.translateX = function ( amount ) {
/*
* Update
*/
this.tmpVec.sub( this.target.position, this.position ).normalize().multiplyScalar( amount );
this.tmpVec.crossSelf( this.up );
THREE.Camera.prototype.update = function( parentGlobalMatrix, forceUpdate, scene, camera ) {
if( this.useTarget ) {
// local
this.localMatrix.lookAt( this.position, this.target.position, this.up );
// global
if( parentGlobalMatrix )
this.globalMatrix.multiply( parentGlobalMatrix, this.localMatrix );
else
this.globalMatrix.copy( this.localMatrix );
THREE.Matrix4.makeInvert( this.globalMatrix, this.inverseMatrix );
forceUpdate = true;
} else {
if( this.autoUpdateMatrix )
forceUpdate |= this.updateMatrix();
if( forceUpdate || this.matrixNeedsToUpdate ) {
if( parentGlobalMatrix )
this.globalMatrix.multiply( parentGlobalMatrix, this.localMatrix );
else
this.globalMatrix.copy( this.localMatrix );
this.matrixNeedsToUpdate = false;
forceUpdate = true;
THREE.Matrix4.makeInvert( this.globalMatrix, this.inverseMatrix );
}
this.position.addSelf( this.tmpVec );
this.target.position.addSelf( this.tmpVec );
}
// update children
};
for( var i = 0; i < this.children.length; i++ )
this.children[ i ].update( this.globalMatrix, forceUpdate, camera, renderer );
/* TODO
this.translateY = function ( amount ) {
}
};
*/
this.translateZ = function ( amount ) {
/*
* FrustumContains
* Checks object against projected image (as opposed to ordinary frustum check)
*
* TODO: make it work also for ortho camera
*/
this.tmpVec.sub( this.target.position, this.position ).normalize().multiplyScalar( amount );
THREE.Camera.prototype.frustumContains = function( object3D ) {
this.position.subSelf( this.tmpVec );
this.target.position.subSelf( this.tmpVec );
// object pos
};
var vx0 = object3D.globalMatrix.n14,
vy0 = object3D.globalMatrix.n24,
vz0 = object3D.globalMatrix.n34;
// check z
this.updateMatrix = function () {
var inverse = this.inverseMatrix;
var radius = object3D.boundRadius * object3D.boundRadiusScale;
var vz1 = ( inverse.n31 * vx0 + inverse.n32 * vy0 + inverse.n33 * vz0 + inverse.n34 );
this.matrix.lookAt( this.position, this.target.position, this.up );
if( vz1 - radius > -this.zNear )
return false;
if( vz1 + radius < -this.zFar )
return false;
};
// check x
this.updateProjectionMatrix = function () {
vz1 -= radius;
this.projectionMatrix = THREE.Matrix4.makePerspective( this.fov, this.aspect, this.near, this.far );
var perspective = this.projectionMatrix;
var ooZ = 1 / ( perspective.n43 * vz1 );
var ooZscreenCenterX = ooZ * this.screenCenterX;
var vx1 = ( inverse.n11 * vx0 + inverse.n12 * vy0 + inverse.n13 * vz0 + inverse.n14 ) * perspective.n11 * ooZscreenCenterX;
radius = perspective.n11 * radius * ooZscreenCenterX;
};
if( vx1 + radius < -this.screenCenterX )
return false;
this.updateProjectionMatrix();
if( vx1 - radius > this.screenCenterX )
return false;
};
THREE.Camera.prototype = {
// check y
toString: function () {
var vy1 = ( inverse.n21 * vx0 + inverse.n22 * vy0 + inverse.n23 * vz0 + inverse.n24 ) * perspective.n22 * ooZ * this.screenCenterY;
if( vy1 + radius < -this.screenCenterY )
return false;
if( vy1 - radius > this.screenCenterY )
return false;
return 'THREE.Camera ( ' + this.position + ', ' + this.target.position + ' )';
}
// inside
object3D.screenPosition.set( vx1, vy1, vz1, radius );
return true;
};
}
......@@ -2,15 +2,21 @@
* @author mr.doob / http://mrdoob.com/
* @author kile / http://kile.stravaganza.org/
* @author alteredq / http://alteredqualia.com/
* @author mikael emtinger / http://gomo.se/
*/
THREE.Geometry = function () {
this.id = "Geometry" + THREE.GeometryIdCounter++;
this.vertices = [];
this.faces = [];
this.uvs = [];
this.uvs2 = [];
this.colors = [];
this.skinWeights = [];
this.skinIndices = [];
this.boundingBox = null;
this.boundingSphere = null;
......@@ -467,3 +473,5 @@ THREE.Geometry.prototype = {
}
};
THREE.GeometryIdCounter = 0;
......@@ -4,6 +4,8 @@
* @author philogb / http://blog.thejit.org/
* @author jordi_ros / http://plattsoft.com
* @author D1plo1d / http://github.com/D1plo1d
* @author alteredq / http://alteredqualia.com/
* @author mikael emtinger / http://gomo.se/
*/
THREE.Matrix4 = function ( n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44 ) {
......@@ -83,6 +85,15 @@ THREE.Matrix4.prototype = {
},
multiplyVector3OnlyZ: function( v ) {
var vx = v.x, vy = v.y, vz = v.z,
d = 1 / ( this.n41 * vx + this.n42 * vy + this.n43 * vz + this.n44 );
return ( this.n31 * vx + this.n32 * vy + this.n33 * vz + this.n34 ) * d;
},
multiplyVector4: function ( v ) {
var vx = v.x, vy = v.y, vz = v.z, vw = v.w;
......@@ -458,6 +469,92 @@ THREE.Matrix4.prototype = {
},
setPosition: function( vec3 ) {
this.n14 = vec3.x;
this.n24 = vec3.y;
this.n34 = vec3.z;
return this;
},
setRotationFromEuler: function( vec3 ) {
//var c = Math.PI / 180;
var x = vec3.x,// * c;
y = vec3.y,// * c;
z = vec3.z,// * c;
ch = Math.cos( y ),
sh = Math.sin( y ),
ca = Math.cos( -z ),
sa = Math.sin( -z ),
cb = Math.cos( x ),
sb = Math.sin( x ),
chsa = ch * sa,
shsa = sh * sa;
this.n11 = ch * ca;
this.n12 = sh * sb - chsa * cb;
this.n13 = chsa * sb + sh * cb;
this.n21 = sa;
this.n22 = ca * cb;
this.n23 = - ca * sb;
this.n31 = - sh * ca;
this.n32 = shsa * cb + ch * sb;
this.n33 = - shsa * sb + ch * cb;
},
setRotationFromQuaternion: function( quat ) {
var x = quat.x, y = quat.y, z = quat.z, w = quat.w,
x2 = x + x,
y2 = y + y,
z2 = z + z,
xx = x * x2,
xy = x * y2,
xz = x * z2,
yy = y * y2,
yz = y * z2,
zz = z * z2,
wx = w * x2,
wy = w * y2,
wz = w * z2;
this.n11 = 1 - ( yy + zz );
this.n12 = xy - wz;
this.n13 = xz + wy;
this.n21 = xy + wz;
this.n22 = 1 - ( xx + zz );
this.n23 = yz - wx;
this.n31 = xz - wy;
this.n32 = yz + wx;
this.n33 = 1 - ( xx + yy );
},
scale: function( vec3 ) {
var x = vec3.x;
var y = vec3.y;
var z = vec3.z;
this.n11 *= x; this.n12 *= x; this.n13 *= x;
this.n21 *= y; this.n22 *= y; this.n23 *= y;
this.n31 *= z; this.n32 *= z; this.n33 *= z;
return this;
},
toString: function() {
return "| " + this.n11 + " " + this.n12 + " " + this.n13 + " " + this.n14 + " |\n" +
......
/*
* @author mikael emtinger / http://gomo.se/
*/
THREE.Quaternion = function( _x, _y, _z, _w ) {
this.x = _x || 0;
this.y = _y || 0;
this.z = _z || 0;
this.w = _w !== undefined ? _w : 1;
this.api = {
isDirty: false,
that: this,
get x() { return this.that.x; },
get y() { return this.that.y; },
get z() { return this.that.z; },
get w() { return this.that.w; },
set x( value ) { this.that.x = value; this.isDirty = true; },
set y( value ) { this.that.y = value; this.isDirty = true; },
set z( value ) { this.that.z = value; this.isDirty = true; },
set w( value ) { this.that.w = value; this.isDirty = true; },
};
this.api.__proto__ = THREE.Quaternion.prototype;
return this.api;
};
THREE.Quaternion.prototype.set = function( x, y, z, w ) {
var quat = this.that;
quat.x = x;
quat.y = y;
quat.z = z;
quat.w = w;
this.isDirty = true;
return this;
};
THREE.Quaternion.prototype.setFromEuler = function( vec3 ) {
var c = 0.5 * Math.PI / 360, // 0.5 is an optimization
x = vec3.x * c,
y = vec3.y * c,
z = vec3.z * c,
c1 = Math.cos( y ),
s1 = Math.sin( y ),
c2 = Math.cos( -z ),
s2 = Math.sin( -z ),
c3 = Math.cos( x ),
s3 = Math.sin( x ),
c1c2 = c1 * c2,
s1s2 = s1 * s2,
quat = this.that;
quat.w = c1c2 * c3 - s1s2 * s3;
quat.x = c1c2 * s3 + s1s2 * c3;
quat.y = s1 * c2 * c3 + c1 * s2 * s3;
quat.z = c1 * s2 * c3 - s1 * c2 * s3;
this.isDirty = true;
return this;
};
THREE.Quaternion.prototype.calculateW = function() {
var quat = this.that,
x = quat.x,
y = quat.y,
z = quat.z;
quat.w = -Math.sqrt( Math.abs( 1.0 - x*x - y*y - z*z ));
this.isDirty = true;
return this;
};
THREE.Quaternion.prototype.inverse = function() {
var quat = this.that;
quat.x *= -1;
quat.y *= -1;
quat.z *= -1;
this.isDirty = true;
return this;
};
THREE.Quaternion.prototype.length = function() {
var quat = this.that;
return Math.sqrt( quat.x * quat.x + quat.y * quat.y + quat.z * quat.z + quat.w * quat.w );
};
THREE.Quaternion.prototype.normalize = function() {
var quat = this.that,
x = quat.x,
y = quat.y,
z = quat.z,
w = quat.w;
var len = Math.sqrt( x*x + y*y + z*z + w*w );
if ( len == 0 ) {
quat.x = 0;
quat.y = 0;
quat.z = 0;
quat.w = 0;
this.isDirty = true;
return this;
}
len = 1 / len;
quat.x = x * len;
quat.y = y * len;
quat.z = z * len;
quat.w = w * len;
this.isDirty = true;
return this;
};
THREE.Quaternion.prototype.multiplySelf = function( quat2 ) {
var quat = this.that;
qax = quat.x, qay = quat.y, qaz = quat.z, qaw = quat.w,
qbx = quat2.x, qby = quat2.y, qbz = quat2.z, qbw = quat2.w;
quat.x = qax * qbw + qaw * qbx + qay * qbz - qaz * qby;
quat.y = qay * qbw + qaw * qby + qaz * qbx - qax * qbz;
quat.z = qaz * qbw + qaw * qbz + qax * qby - qay * qbx;
quat.w = qaw * qbw - qax * qbx - qay * qby - qaz * qbz;
this.isDirty = true;
return this;
};
THREE.Quaternion.prototype.multiplyVector3 = function( vec, dest ) {
if( !dest ) { dest = vec; }
var quat = this.that,
x = vec.x, y = vec.y, z = vec.z,
qx = quat.x, qy = quat.y, qz = quat.z, qw = quat.w;
// calculate quat * vec
var ix = qw * x + qy * z - qz * y,
iy = qw * y + qz * x - qx * z,
iz = qw * z + qx * y - qy * x,
iw = -qx * x - qy * y - qz * z;
// calculate result * inverse quat
dest.x = ix * qw + iw * -qx + iy * -qz - iz * -qy;
dest.y = iy * qw + iw * -qy + iz * -qx - ix * -qz;
dest.z = iz * qw + iw * -qz + ix * -qy - iy * -qx;
return dest;
};
THREE.Quaternion.prototype.toMatrix3 = function( matrix3 ) {
/* todo: create a proper Matrix3 first
var x = quat[0], y = quat[1], z = quat[2], w = quat[3];
var x2 = x + x;
var y2 = y + y;
var z2 = z + z;
var xx = x*x2;
var xy = x*y2;
var xz = x*z2;
var yy = y*y2;
var yz = y*z2;
var zz = z*z2;
var wx = w*x2;
var wy = w*y2;
var wz = w*z2;
dest[0] = 1 - (yy + zz);
dest[1] = xy - wz;
dest[2] = xz + wy;
dest[3] = xy + wz;
dest[4] = 1 - (xx + zz);
dest[5] = yz - wx;
dest[6] = xz - wy;
dest[7] = yz + wx;
dest[8] = 1 - (xx + yy);
return dest;*/
};
THREE.Quaternion.prototype.toMatrix4 = function( matrix4 ) {
/* todo: this is implemented in Matrix4.setFromQuaternion
var x = quat[0], y = quat[1], z = quat[2], w = quat[3];
var x2 = x + x;
var y2 = y + y;
var z2 = z + z;
var xx = x*x2;
var xy = x*y2;
var xz = x*z2;
var yy = y*y2;
var yz = y*z2;
var zz = z*z2;
var wx = w*x2;
var wy = w*y2;
var wz = w*z2;
dest[0] = 1 - (yy + zz);
dest[1] = xy - wz;
dest[2] = xz + wy;
dest[3] = 0;
dest[4] = xy + wz;
dest[5] = 1 - (xx + zz);
dest[6] = yz - wx;
dest[7] = 0;
dest[8] = xz - wy;
dest[9] = yz + wx;
dest[10] = 1 - (xx + yy);
dest[11] = 0;
dest[12] = 0;
dest[13] = 0;
dest[14] = 0;
dest[15] = 1;
*/
};
THREE.Quaternion.slerp = function( qa, qb, qm, t ) {
var cosHalfTheta = qa.w * qb.w + qa.x * qb.x + qa.y * qb.y + qa.z * qb.z;
if( Math.abs( cosHalfTheta ) >= 1.0) {
qm.w = qa.w; qm.x = qa.x; qm.y = qa.y; qm.z = qa.z;
return qm;
}
var halfTheta = Math.acos( cosHalfTheta ),
sinHalfTheta = Math.sqrt( 1.0 - cosHalfTheta * cosHalfTheta );
if( Math.abs( sinHalfTheta ) < 0.001 ) {
qm.w = 0.5 * ( qa.w + qb.w );
qm.x = 0.5 * ( qa.x + qb.x );
qm.y = 0.5 * ( qa.y + qb.y );
qm.z = 0.5 * ( qa.z + qb.z );
return qm;
}
var ratioA = Math.sin( (1 - t) * halfTheta ) / sinHalfTheta,
ratioB = Math.sin( t * halfTheta ) / sinHalfTheta;
qm.w = ( qa.w * ratioA + qb.w * ratioB );
qm.x = ( qa.x * ratioA + qb.x * ratioB );
qm.y = ( qa.y * ratioA + qb.y * ratioB );
qm.z = ( qa.z * ratioA + qb.z * ratioB );
return qm;
};
......@@ -2,208 +2,278 @@
* @author mr.doob / http://mrdoob.com/
* @author kile / http://kile.stravaganza.org/
* @author philogb / http://blog.thejit.org/
* @author mikael emtinger / http://gomo.se/
*/
THREE.Vector3 = function ( x, y, z ) {
THREE.Vector3 = function ( _x, _y, _z ) {
this.x = x || 0;
this.y = y || 0;
this.z = z || 0;
this.x = _x || 0;
this.y = _y || 0;
this.z = _z || 0;
this.api = {
isDirty: false,
that: this,
get x() { return this.that.x; },
get y() { return this.that.y; },
get z() { return this.that.z; },
set x( value ) { this.that.x = value; this.isDirty = true; },
set y( value ) { this.that.y = value; this.isDirty = true; },
set z( value ) { this.that.z = value; this.isDirty = true; },
};
this.api.__proto__ = THREE.Vector3.prototype;
return this.api;
};
THREE.Vector3.prototype = {
set: function ( x, y, z ) {
this.x = x;
this.y = y;
this.z = z;
var vec = this.that;
vec.x = x;
vec.y = y;
vec.z = z;
this.isDirty = true;
return this;
},
copy: function ( v ) {
this.x = v.x;
this.y = v.y;
this.z = v.z;
var vec = this.that;
vec.x = v.x;
vec.y = v.y;
vec.z = v.z;
this.isDirty = true;
return this;
},
add: function ( a, b ) {
this.x = a.x + b.x;
this.y = a.y + b.y;
this.z = a.z + b.z;
var vec = this.that;
vec.x = a.x + b.x;
vec.y = a.y + b.y;
vec.z = a.z + b.z;
this.isDirty = true;
return this;
},
addSelf: function ( v ) {
this.x += v.x;
this.y += v.y;
this.z += v.z;
var vec = this.that;
vec.x += v.x;
vec.y += v.y;
vec.z += v.z;
this.isDirty = true;
return this;
},
addScalar: function ( s ) {
this.x += s;
this.y += s;
this.z += s;
var vec = this.that;
vec.x += s;
vec.y += s;
vec.z += s;
this.isDirty = true;
return this;
},
sub: function( a, b ) {
this.x = a.x - b.x;
this.y = a.y - b.y;
this.z = a.z - b.z;
var vec = this.that;
vec.x = a.x - b.x;
vec.y = a.y - b.y;
vec.z = a.z - b.z;
this.isDirty = true;
return this;
},
subSelf: function ( v ) {
this.x -= v.x;
this.y -= v.y;
this.z -= v.z;
var vec = this.that;
vec.x -= v.x;
vec.y -= v.y;
vec.z -= v.z;
this.isDirty = true;
return this;
},
cross: function ( a, b ) {
this.x = a.y * b.z - a.z * b.y;
this.y = a.z * b.x - a.x * b.z;
this.z = a.x * b.y - a.y * b.x;
var vec = this.that;
vec.x = a.y * b.z - a.z * b.y;
vec.y = a.z * b.x - a.x * b.z;
vec.z = a.x * b.y - a.y * b.x;
this.isDirty = true;
return this;
},
crossSelf: function ( v ) {
var tx = this.x, ty = this.y, tz = this.z;
var vec = this.that;
var tx = vec.x, ty = vec.y, tz = vec.z;
this.x = ty * v.z - tz * v.y;
this.y = tz * v.x - tx * v.z;
this.z = tx * v.y - ty * v.x;
vec.x = ty * v.z - tz * v.y;
vec.y = tz * v.x - tx * v.z;
vec.z = tx * v.y - ty * v.x;
this.isDirty = true;
return this;
},
multiply: function ( a, b ) {
this.x = a.x * b.x;
this.y = a.y * b.y;
this.z = a.z * b.z;
var vec = this.that;
vec.x = a.x * b.x;
vec.y = a.y * b.y;
vec.z = a.z * b.z;
this.isDirty = true;
return this;
},
multiplySelf: function ( v ) {
this.x *= v.x;
this.y *= v.y;
this.z *= v.z;
var vec = this.that;
vec.x *= v.x;
vec.y *= v.y;
vec.z *= v.z;
this.isDirty = true;
return this;
},
multiplyScalar: function ( s ) {
this.x *= s;
this.y *= s;
this.z *= s;
var vec = this.that;
vec.x *= s;
vec.y *= s;
vec.z *= s;
this.isDirty = true;
return this;
},
divideSelf: function ( v ) {
this.x /= v.x;
this.y /= v.y;
this.z /= v.z;
var vec = this.that;
vec.x /= v.x;
vec.y /= v.y;
vec.z /= v.z;
this.isDirty = true;
return this;
},
divideScalar: function ( s ) {
this.x /= s;
this.y /= s;
this.z /= s;
var vec = this.that;
vec.x /= s;
vec.y /= s;
vec.z /= s;
this.isDirty = true;
return this;
},
dot: function ( v ) {
return this.x * v.x + this.y * v.y + this.z * v.z;
var vec = this.that;
return vec.x * v.x + vec.y * v.y + vec.z * v.z;
},
distanceTo: function ( v ) {
var dx = this.x - v.x, dy = this.y - v.y, dz = this.z - v.z;
var vec = this.that;
var dx = vec.x - v.x, dy = vec.y - v.y, dz = vec.z - v.z;
return Math.sqrt( dx * dx + dy * dy + dz * dz );
},
distanceToSquared: function ( v ) {
var dx = this.x - v.x, dy = this.y - v.y, dz = this.z - v.z;
var vec = this.that;
var dx = vec.x - v.x, dy = vec.y - v.y, dz = vec.z - v.z;
return dx * dx + dy * dy + dz * dz;
},
length: function () {
return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z );
var vec = this.that;
return Math.sqrt( vec.x * vec.x + vec.y * vec.y + vec.z * vec.z );
},
lengthSq: function () {
return this.x * this.x + this.y * this.y + this.z * this.z;
var vec = this.that;
return vec.x * vec.x + vec.y * vec.y + vec.z * vec.z;
},
lengthManhattan: function () {
var vec = this.that;
return vec.x + vec.y + vec.z;
},
negate: function () {
this.x = - this.x;
this.y = - this.y;
this.z = - this.z;
var vec = this.that;
vec.x = - this.x;
vec.y = - this.y;
vec.z = - this.z;
this.isDirty = true;
return this;
},
normalize: function () {
var length = Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z );
var vec = this.that;
var length = Math.sqrt( vec.x * vec.x + vec.y * vec.y + vec.z * vec.z );
length > 0 ? this.multiplyScalar( 1 / length ) : this.set( 0, 0, 0 );
this.isDirty = true;
return this;
},
......@@ -217,13 +287,16 @@ THREE.Vector3.prototype = {
isZero: function () {
var almostZero = 0.0001;
return ( Math.abs( this.x ) < almostZero ) && ( Math.abs( this.y ) < almostZero ) && ( Math.abs( this.z ) < almostZero );
var vec = this.that;
return ( Math.abs( vec.x ) < almostZero ) && ( Math.abs( vec.y ) < almostZero ) && ( Math.abs( vec.z ) < almostZero );
},
clone: function () {
return new THREE.Vector3( this.x, this.y, this.z );
var vec = this.that;
return new THREE.Vector3( vec.x, vec.y, vec.z );
},
......
/**
* @author supereggbert / http://www.paulbrunt.co.uk/
* @author philogb / http://blog.thejit.org/
* @author mikael emtinger / http://gomo.se/
*/
THREE.Vector4 = function ( x, y, z, w ) {
......@@ -8,7 +9,7 @@ THREE.Vector4 = function ( x, y, z, w ) {
this.x = x || 0;
this.y = y || 0;
this.z = z || 0;
this.w = w || 1;
this.w = w !== undefined ? w : 1;
};
......@@ -108,6 +109,7 @@ THREE.Vector4.prototype = {
this.y = this.y + (v.y - this.y) * alpha;
this.z = this.z + (v.z - this.z) * alpha;
this.w = this.w + (v.w - this.w) * alpha;
},
clone: function () {
......
......@@ -759,11 +759,51 @@ THREE.Loader.prototype = {
init_vertices();
init_faces();
init_skin();
this.computeCentroids();
this.computeFaceNormals();
this.sortFacesByMaterial();
function init_skin() {
var i, l, x, y, z, w, a, b, c, d;
if ( data.skinWeights ) {
for( i = 0, l = data.skinWeights.length; i < l; i += 2 ) {
x = data.skinWeights[ i ];
y = data.skinWeights[ i + 1 ];
z = 0;
w = 0;
THREE.Loader.prototype.sw( scope, x, y, z, w );
}
}
if ( data.skinIndices ) {
for( i = 0, l = data.skinIndices.length; i < l; i += 2 ) {
a = data.skinIndices[ i ];
b = data.skinIndices[ i + 1 ];
c = 0;
d = 0;
THREE.Loader.prototype.si( scope, a, b, c, d );
}
}
THREE.Loader.prototype.bones( scope, data.bones );
THREE.Loader.prototype.animation( scope, data.animation );
}
function init_vertices() {
var i, l, x, y, z, r, g, b;
......@@ -882,7 +922,7 @@ THREE.Loader.prototype = {
THREE.Loader.prototype.uv3( scope.uvs, u1, v1, u2, v2, u3, v3 );
if( data.uvs2 ) {
if( data.uvs2 && data.uvs2.length ) {
u1 = data.uvs2[ uva * 2 ];
v1 = data.uvs2[ uva * 2 + 1 ];
......@@ -1012,6 +1052,30 @@ THREE.Loader.prototype = {
},
bones: function( scope, bones ) {
scope.bones = bones;
},
animation: function( scope, animation ) {
scope.animation = animation;
},
si: function( scope, a, b, c, d ) {
scope.skinIndices.push( new THREE.Vector4( a, b, c, d ) );
},
sw: function( scope, x, y, z, w ) {
scope.skinWeights.push( new THREE.Vector4( x, y, z, w ) );
},
v: function( scope, x, y, z ) {
scope.vertices.push( new THREE.Vertex( new THREE.Vector3( x, y, z ) ) );
......
/**
* @author mr.doob / http://mrdoob.com/
* @author alteredq / http://alteredqualia.com/
*/
THREE.Light = function ( hex ) {
THREE.Object3D.call( this );
this.color = new THREE.Color( hex );
};
THREE.Light.prototype = new THREE.Object3D();
THREE.Light.prototype.constructor = THREE.Light;
THREE.Light.prototype.supr = THREE.Object3D.prototype;
/**
* @author mikael emtinger / http://gomo.se/
*/
THREE.Bone = function( belongsToSkin ) {
THREE.Object3D.call( this );
this.skin = belongsToSkin;
this.skinMatrix = new THREE.Matrix4();
this.hasNoneBoneChildren = false;
};
THREE.Bone.prototype = new THREE.Object3D();
THREE.Bone.prototype.constructor = THREE.Bone;
THREE.Bone.prototype.supr = THREE.Object3D.prototype;
/*
* Update
*/
THREE.Bone.prototype.update = function( parentSkinMatrix, forceUpdate, camera, renderer ) {
// update local
if( this.autoUpdateMatrix )
forceUpdate |= this.updateMatrix();
// update skin matrix
if( forceUpdate || this.matrixNeedsToUpdate ) {
if( parentSkinMatrix )
this.skinMatrix.multiply( parentSkinMatrix, this.localMatrix );
else
this.skinMatrix.copy( this.localMatrix );
this.matrixNeedsToUpdate = false;
forceUpdate = true;
}
// update children
if( this.hasNoneBoneChildren ) {
this.globalMatrix.multiply( this.skin.globalMatrix, this.skinMatrix );
for( var i = 0; i < this.children.length; i++ )
if( !( this.children[ i ] instanceof THREE.Bone ))
this.children[ i ].update( this.globalMatrix, true, camera, renderer );
else
this.children[ i ].update( this.skinMatrix, forceUpdate, camera, renderer );
} else {
for( var i = 0; i < this.children.length; i++ )
this.children[ i ].update( this.skinMatrix, forceUpdate, camera, renderer );
}
};
/*
* Add child
*/
THREE.Bone.prototype.addChild = function( child ) {
if( this.children.indexOf( child ) === -1 ) {
if( child.parent !== undefined )
child.parent.removeChild( child );
child.parent = this;
this.children.push( child );
if( !( child instanceof THREE.Bone ))
this.hasNoneBoneChildren = true;
}
};
/*
* Todo: Remove Children: see if any remaining are none-Bone
*/
\ No newline at end of file
/**
* @author mikael emtinger / http://gomo.se/
*/
THREE.LOD = function() {
THREE.Object3D.call( this );
this.LODs = [];
};
THREE.LOD.prototype = new THREE.Object3D();
THREE.LOD.prototype.constructor = THREE.LOD;
THREE.LOD.prototype.supr = THREE.Object3D.prototype;
/*
* Add
*/
THREE.LOD.prototype.add = function( object3D, visibleAtDistance ) {
if( visibleAtDistance === undefined ) visibleAtDistance = 0;
visibleAtDistance = Math.abs( visibleAtDistance );
for( var l = 0; l < this.LODs.length; l++ ) {
if( visibleAtDistance < this.LODs[ l ].visibleAtDistance )
break;
}
this.LODs.splice( l, 0, { visibleAtDistance: visibleAtDistance, object3D: object3D } );
this.addChild( object3D );
};
/*
* Update
*/
THREE.LOD.prototype.update = function( parentGlobalMatrix, forceUpdate, camera, renderer ) {
// update local
if( this.autoUpdateMatrix )
forceUpdate |= this.updateMatrix();
// update global
if( forceUpdate || this.matrixNeedsToUpdate ) {
if( parentGlobalMatrix )
this.globalMatrix.multiply( parentGlobalMatrix, this.localMatrix );
else
this.globalMatrix.copy( this.localMatrix );
this.matrixNeedsToUpdate = false;
forceUpdate = true;
}
// update lods
if( this.LODs.length > 1 ) {
var distance = -camera.inverseMatrix.mulitplyVector3OnlyZ( this.position );
this.LODs[ 0 ].object3D.visible = true;
for( var l = 1; l < this.LODs.length; l++ ) {
if( distance >= this.LODs[ l ].visibleAtDistance ) {
this.LODs[ l - 1 ].object3D.visible = false;
this.LODs[ l ].object3D.visible = true;
}
else
break;
}
for( ; l < this.LODs.length; l++ )
this.LODs[ l ].object3D.visible = false;
}
// update children
for( var c = 0; c < this.children.length; c++ )
this.children[ c ].update( this.globalMatrix, forceUpdate, camera, renderer );
};
/**
* @author mr.doob / http://mrdoob.com/
* @author alteredq / http://alteredqualia.com/
* @author mikael emtinger / http://gomo.se/
*/
THREE.Mesh = function ( geometry, materials ) {
THREE.Mesh = function( geometry, materials ) {
THREE.Object3D.call( this );
this.geometry = geometry;
this.materials = materials instanceof Array ? materials : [ materials ];
this.geometry = geometry;
this.materials = materials && materials.length ? materials : [ materials ];
this.normalMatrix = THREE.Matrix4.makeInvert3x3( this.globalMatrix ).transpose();
this.flipSided = false;
this.doubleSided = false;
this.overdraw = false; // TODO: Move to material?
// calc bound radius
if( this.geometry ) {
if( !this.geometry.boundingSphere )
this.geometry.computeBoundingSphere();
this.boundRadius = geometry.boundingSphere.radius;
this.geometry.boundingSphere || this.geometry.computeBoundingSphere();
}
};
}
THREE.Mesh.prototype = new THREE.Object3D();
THREE.Mesh.prototype = new THREE.Object3D();
THREE.Mesh.prototype.constructor = THREE.Mesh;
THREE.Mesh.prototype.supr = THREE.Object3D.prototype;
/*
* Update
*/
THREE.Mesh.prototype.update = function( parentGlobalMatrix, forceUpdate, camera, renderer ) {
// visible?
if( this.visible ) {
// update local
if( this.autoUpdateMatrix )
forceUpdate |= this.updateMatrix();
// update global
if( forceUpdate || this.matrixNeedsToUpdate ) {
if( parentGlobalMatrix )
this.globalMatrix.multiply( parentGlobalMatrix, this.localMatrix );
else
this.globalMatrix.copy( this.localMatrix );
this.matrixNeedsToUpdate = false;
forceUpdate = true;
// update normal
this.normalMatrix = THREE.Matrix4.makeInvert3x3( this.globalMatrix ).transpose();
}
// update children
for( var i = 0; i < this.children.length; i++ )
this.children[ i ].update( this.globalMatrix, forceUpdate, camera, renderer );
// check camera frustum and add to render list
if( renderer && camera ) {
if( camera.frustumContains( this ))
renderer.addToRenderList( this );
else
renderer.removeFromRenderList( this );
}
} else {
renderer.removeFromRenderList( this );
}
}
/**
* @author mr.doob / http://mrdoob.com/
* @author mikael emtinger / http://gomo.se/
* @author alteredq / http://alteredqualia.com/
*/
THREE.Object3D = function () {
THREE.Object3D = function() {
this.id = THREE.Object3DCounter.value ++;
this.visible = true;
this.autoUpdateMatrix = true;
this.matrixNeedsToUpdate = true;
this.parent = undefined;
this.children = [];
this.position = new THREE.Vector3();
this.rotation = new THREE.Vector3();
this.scale = new THREE.Vector3( 1.0, 1.0, 1.0 );
this.localMatrix = new THREE.Matrix4();
this.globalMatrix = new THREE.Matrix4();
this.quaternion = new THREE.Quaternion();
this.useQuaternion = false;
this.screenPosition = new THREE.Vector4(); // xyzr
this.boundRadius = 0.0;
this.boundRadiusScale = 1.0;
this.id = THREE.Object3DCounter.value ++; // TODO: Probably not needed?
};
/*
* Update
*/
THREE.Object3D.prototype.update = function( parentGlobalMatrix, forceUpdate, camera, renderer ) {
this.position = new THREE.Vector3();
this.rotation = new THREE.Vector3();
this.scale = new THREE.Vector3( 1, 1, 1 );
// visible and auto update?
if( this.visible ) {
this.matrix = new THREE.Matrix4();
this.matrixWorld = new THREE.Matrix4();
this.rotationMatrix = new THREE.Matrix4();
this.tmpMatrix = new THREE.Matrix4();
// update local
if( this.autoUpdateMatrix )
forceUpdate |= this.updateMatrix();
// update global
if( forceUpdate || this.matrixNeedsToUpdate ) {
if( parentGlobalMatrix )
this.globalMatrix.multiply( parentGlobalMatrix, this.localMatrix );
else
this.globalMatrix.copy( this.localMatrix );
this.matrixNeedsToUpdate = false;
forceUpdate = true;
}
this.screen = new THREE.Vector3();
this.autoUpdateMatrix = true;
this.visible = true;
// update children
for( var i = 0; i < this.children.length; i++ ) {
this.children[ i ].update( this.globalMatrix, forceUpdate, camera, renderer );
}
this.children = [];
}
};
THREE.Object3D.prototype = {
addChild: function ( object ) {
/*
* Update Matrix
*/
var i = this.children.indexOf( object );
THREE.Object3D.prototype.updateMatrix = function() {
// update position
var isDirty = false;
if( this.position.isDirty ) {
this.localMatrix.setPosition( this.position );
this.position.isDirty = false;
isDirty = true;
if ( i === -1 ) {
}
this.children.push( object );
}
// update quaternion
if( this.useQuaternion ) {
if( this.quaternion.isDirty ) {
this.localMatrix.setRotationFromQuaternion( this.quaternion );
this.quaternion.isDirty = false;
this.rotation .isDirty = false;
if( this.scale.isDirty || this.scale.x !== 1 || this.scale.y !== 1 || this.scale.z !== 1 ) {
this.localMatrix.scale( this.scale );
this.scale.isDirty = false;
this.boundRadiusScale = Math.max( this.scale.x, Math.max( this.scale.y, this.scale.z ) );
}
isDirty = true;
},
}
removeChild: function ( object ) {
}
var i = this.children.indexOf( object );
// update rotation
if ( i !== -1 ) {
else if( this.rotation.isDirty ) {
this.localMatrix.setRotationFromEuler( this.rotation );
this.rotation.isDirty = false;
this.children.splice( i, 1 );
if( this.scale.isDirty || this.scale.x !== 1 || this.scale.y !== 1 || this.scale.z !== 1 ) {
this.localMatrix.scale( this.scale );
this.scale.isDirty = false;
this.boundRadiusScale = Math.max( this.scale.x, Math.max( this.scale.y, this.scale.z ) );
}
},
isDirty = true;
}
// update scale
if( this.scale.isDirty ) {
if( this.useQuaternion )
this.localMatrix.setRotationFromQuaternion( this.quaternion );
else
this.localMatrix.setRotationFromEuler( this.rotation );
this.localMatrix.scale( this.scale );
this.scale.isDirty = false;
this.boundRadiusScale = Math.max( this.scale.x, Math.max( this.scale.y, this.scale.z ));
isDirty = true;
}
return isDirty;
};
updateMatrix: function () {
var p = this.position, r = this.rotation, s = this.scale,
matrix = this.matrix, rotationMatrix = this.rotationMatrix,
tmpMatrix = this.tmpMatrix;
/*
* AddChild
*/
matrix.setTranslation( p.x, p.y, p.z );
THREE.Object3D.prototype.addChild = function( child ) {
if( this.children.indexOf( child ) === -1 ) {
rotationMatrix.setRotX( r.x );
if( child.parent !== undefined )
child.parent.removeChild( child );
child.parent = this;
this.children.push( child );
if ( r.y != 0 ) rotationMatrix.multiplySelf( tmpMatrix.setRotY( r.y ) );
if ( r.z != 0 ) rotationMatrix.multiplySelf( tmpMatrix.setRotZ( r.z ) );
}
matrix.multiplySelf( rotationMatrix );
};
if ( s.x != 0 || s.y != 0 || s.z != 0 ) matrix.multiplySelf( tmpMatrix.setScale( s.x, s.y, s.z ) );
/*
* RemoveChild
*/
THREE.Object3D.prototype.removeChild = function() {
var childIndex = this.children.indexOf( child );
if( childIndex !== -1 ) {
this.children.splice( childIndex, 1 );
child.parent = undefined;
}
};
THREE.Object3DCounter = { value: 0 };
/**
* @author mikael emtinger / http://gomo.se/
*/
THREE.SkinnedMesh = function( geometry, materials ) {
THREE.Mesh.call( this, geometry, materials );
// init bones
this.identityMatrix = new THREE.Matrix4();
this.bones = [];
this.boneMatrices = [];
if( this.geometry.bones !== undefined ) {
for( var b = 0; b < this.geometry.bones.length; b++ ) {
var bone = this.addBone();
bone.name = this.geometry.bones[ b ].name;
bone.position.x = this.geometry.bones[ b ].pos [ 0 ];
bone.position.y = this.geometry.bones[ b ].pos [ 1 ];
bone.position.z = this.geometry.bones[ b ].pos [ 2 ];
bone.quaternion.x = this.geometry.bones[ b ].rotq[ 0 ];
bone.quaternion.y = this.geometry.bones[ b ].rotq[ 1 ];
bone.quaternion.z = this.geometry.bones[ b ].rotq[ 2 ];
bone.quaternion.w = this.geometry.bones[ b ].rotq[ 3 ];
bone.scale.x = this.geometry.bones[ b ].scl !== undefined ? this.geometry.bones[ b ].scl[ 0 ] : 1;
bone.scale.y = this.geometry.bones[ b ].scl !== undefined ? this.geometry.bones[ b ].scl[ 1 ] : 1;
bone.scale.z = this.geometry.bones[ b ].scl !== undefined ? this.geometry.bones[ b ].scl[ 2 ] : 1;
}
for( var b = 0; b < this.bones.length; b++ ) {
if( this.geometry.bones[ b ].parent === -1 )
this.addChild( this.bones[ b ] );
else
this.bones[ this.geometry.bones[ b ].parent ].addChild( this.bones[ b ] );
}
this.pose();
}
};
THREE.SkinnedMesh.prototype = new THREE.Mesh();
THREE.SkinnedMesh.prototype.constructor = THREE.SkinnedMesh;
/*
* Update
*/
THREE.SkinnedMesh.prototype.update = function( parentGlobalMatrix, forceUpdate, camera, renderer ) {
// visible?
if( this.visible ) {
// update local
if( this.autoUpdateMatrix )
forceUpdate |= this.updateMatrix();
// update global
if( forceUpdate || this.matrixNeedsToUpdate ) {
if( parentGlobalMatrix )
this.globalMatrix.multiply( parentGlobalMatrix, this.localMatrix );
else
this.globalMatrix.copy( this.localMatrix );
this.matrixNeedsToUpdate = false;
forceUpdate = true;
// update normal
this.normalMatrix = THREE.Matrix4.makeInvert3x3( this.globalMatrix ).transpose();
}
// update children
for( var i = 0; i < this.children.length; i++ )
if( this.children[ i ] instanceof THREE.Bone )
this.children[ i ].update( this.identityMatrix, false, camera, renderer );
else
this.children[ i ].update( this.globalMatrix, forceUpdate, camera, renderer );
// check camera frustum and add to render list
if( renderer && camera ) {
if( camera.frustumContains( this ) )
renderer.addToRenderList( this );
else
renderer.removeFromRenderList( this );
}
} else {
renderer.removeFromRenderList( this );
}
};
/*
* Add
*/
THREE.SkinnedMesh.prototype.addBone = function( bone ) {
if( bone === undefined )
bone = new THREE.Bone( this );
this.bones.push( bone );
return bone;
};
/*
* Pose
*/
THREE.SkinnedMesh.prototype.pose = function() {
this.update( undefined, true );
var boneInverses = [];
for( var b = 0; b < this.bones.length; b++ ) {
boneInverses.push( THREE.Matrix4.makeInvert( this.bones[ b ].skinMatrix, new THREE.Matrix4()));
this.boneMatrices.push( this.bones[ b ].skinMatrix.flatten32 );
}
// project vertices to local
if( this.geometry.skinVerticesA === undefined ) {
this.geometry.skinVerticesA = [];
this.geometry.skinVerticesB = [];
var orgVertex;
var vertex;
for( var i = 0; i < this.geometry.skinIndices.length; i++ ) {
orgVertex = this.geometry.vertices[ i ].position;
var indexA = this.geometry.skinIndices[ i ].x;
var indexB = this.geometry.skinIndices[ i ].y;
vertex = new THREE.Vector3( orgVertex.x, orgVertex.y, orgVertex.z );
this.geometry.skinVerticesA.push( boneInverses[ indexA ].multiplyVector3( vertex ));
vertex = new THREE.Vector3( orgVertex.x, orgVertex.y, orgVertex.z );
this.geometry.skinVerticesB.push( boneInverses[ indexB ].multiplyVector3( vertex ));
// todo: add more influences
// normalize weights
if( this.geometry.skinWeights[ i ].x + this.geometry.skinWeights[ i ].y !== 1 ) {
var len = ( 1.0 - ( this.geometry.skinWeights[ i ].x + this.geometry.skinWeights[ i ].y )) * 0.5;
this.geometry.skinWeights[ i ].x += len;
this.geometry.skinWeights[ i ].y += len;
}
}
}
};
......@@ -64,6 +64,7 @@ THREE.WebGLRenderer = function ( parameters ) {
this.domElement = _canvas;
this.autoClear = true;
this.sortObjects = false;
initGL( antialias, clearColor, clearAlpha );
......@@ -809,7 +810,7 @@ THREE.WebGLRenderer = function ( parameters ) {
if ( object.sortParticles ) {
_projScreenMatrix.multiplySelf( object.matrixWorld );
_projScreenMatrix.multiplySelf( object.globalMatrix );
for ( v = 0; v < vl; v++ ) {
......@@ -1355,7 +1356,7 @@ THREE.WebGLRenderer = function ( parameters ) {
function isInFrustum( object ) {
var distance, matrix = object.matrix,
var distance, matrix = object.globalMatrix,
radius = - object.geometry.boundingSphere.radius * Math.max( object.scale.x, Math.max( object.scale.y, object.scale.z ) );
for ( var i = 0; i < 6; i ++ ) {
......@@ -1446,39 +1447,31 @@ THREE.WebGLRenderer = function ( parameters ) {
};
function updateChildren( object ) {
var i, l, child, children = object.children;
for ( i = 0, l = children.length; i < l; i ++ ) {
function painterSort( a, b ) {
child = children[ i ];
return b.z - a.z;
child.autoUpdateMatrix && child.updateMatrix();
child.matrixWorld.multiply( object.matrixWorld, child.matrix );
updateChildren( child );
}
};
this.render = function( scene, camera, renderTarget, clear ) {
var i, program, opaque, transparent,
o, ol, oil, webGLObject, object, buffer,
lights = scene.lights,
fog = scene.fog,
ol;
camera.autoUpdateMatrix && camera.updateMatrix();
camera.autoUpdateMatrix && camera.update();
camera.matrix.flattenToArray( _viewMatrixArray );
camera.globalMatrix.flattenToArray( _viewMatrixArray );
camera.projectionMatrix.flattenToArray( _projectionMatrixArray );
_projScreenMatrix.multiply( camera.projectionMatrix, camera.matrix );
_projScreenMatrix.multiply( camera.projectionMatrix, camera.globalMatrix );
computeFrustum( _projScreenMatrix );
scene.update( undefined, false, camera, this );
this.initWebGLObjects( scene, camera );
setRenderTarget( renderTarget, clear !== undefined ? clear : true );
......@@ -1498,20 +1491,11 @@ THREE.WebGLRenderer = function ( parameters ) {
webGLObject = scene.__webGLObjects[ o ];
object = webGLObject.object;
if ( object.visible ) {
if ( webGLObject.root ) {
object.autoUpdateMatrix && object.updateMatrix();
object.matrixWorld.copy( object.matrix );
updateChildren( object );
}
if ( object.visible ) {
if ( ! ( object instanceof THREE.Mesh ) || isInFrustum( object ) ) {
object.matrixWorld.flattenToArray( object._objectMatrixArray );
object.globalMatrix.flattenToArray( object._objectMatrixArray );
setupMatrices( object, camera );
......@@ -1519,6 +1503,14 @@ THREE.WebGLRenderer = function ( parameters ) {
webGLObject.render = true;
if ( this.sortObjects ) {
_vector3.copy( object.position );
_projScreenMatrix.multiplyVector3( _vector3 );
webGLObject.z = _vector3.z;
}
} else {
......@@ -1534,6 +1526,12 @@ THREE.WebGLRenderer = function ( parameters ) {
}
if ( this.sortObjects ) {
scene.__webGLObjects.sort( painterSort );
}
oil = scene.__webGLObjectsImmediate.length;
for ( o = 0; o < oil; o++ ) {
......@@ -1545,9 +1543,7 @@ THREE.WebGLRenderer = function ( parameters ) {
if( object.autoUpdateMatrix ) {
object.updateMatrix();
object.matrixWorld.copy( object.matrix );
object.matrixWorld.flattenToArray( object._objectMatrixArray );
object.globalMatrix.flattenToArray( object._objectMatrixArray );
}
......@@ -1681,22 +1677,7 @@ THREE.WebGLRenderer = function ( parameters ) {
};
function addChildren( scene, object ) {
var i, l, children = object.children;
for ( i = 0, l = children.length; i < l; i ++ ) {
child = children[ i ];
addObject( scene, child, false );
addChildren( scene, child );
}
};
function addObject( scene, object, root ) {
function addObject( scene, object ) {
var g, geometry, geometryChunk, objmap;
......@@ -1712,7 +1693,7 @@ THREE.WebGLRenderer = function ( parameters ) {
object._modelViewMatrixArray = new Float32Array( 16 );
object._objectMatrixArray = new Float32Array( 16 );
object.matrix.flattenToArray( object._objectMatrixArray );
object.globalMatrix.flattenToArray( object._objectMatrixArray );
}
......@@ -1753,7 +1734,7 @@ THREE.WebGLRenderer = function ( parameters ) {
// create separate wrapper per each use of VBO
add_buffer( objlist, objmap, g, geometryChunk, object, root );
add_buffer( objlist, objmap, g, geometryChunk, object );
}
......@@ -1782,7 +1763,7 @@ THREE.WebGLRenderer = function ( parameters ) {
}
add_buffer( objlist, objmap, 0, geometry, object, root );
add_buffer( objlist, objmap, 0, geometry, object );
geometry.__dirtyVertices = false;
geometry.__dirtyColors = false;
......@@ -1805,14 +1786,14 @@ THREE.WebGLRenderer = function ( parameters ) {
}
add_buffer( objlist, objmap, 0, geometry, object, root );
add_buffer( objlist, objmap, 0, geometry, object );
geometry.__dirtyVertices = false;
geometry.__dirtyColors = false;
} else if ( object instanceof THREE.MarchingCubes ) {
add_buffer_immediate( scene.__webGLObjectsImmediate, objmap, 0, object, root );
add_buffer_immediate( scene.__webGLObjectsImmediate, objmap, 0, object );
}/*else if ( object instanceof THREE.Particle ) {
......@@ -1820,14 +1801,13 @@ THREE.WebGLRenderer = function ( parameters ) {
};
function add_buffer( objlist, objmap, id, buffer, object, root ) {
function add_buffer( objlist, objmap, id, buffer, object ) {
if ( objmap[ id ] == undefined ) {
objlist.push( { buffer: buffer, object: object,
opaque: { list: [], count: 0 },
transparent: { list: [], count: 0 },
root: root
transparent: { list: [], count: 0 }
} );
objmap[ id ] = 1;
......@@ -1836,14 +1816,13 @@ THREE.WebGLRenderer = function ( parameters ) {
};
function add_buffer_immediate( objlist, objmap, id, object, root ) {
function add_buffer_immediate( objlist, objmap, id, object ) {
if ( objmap[ id ] == undefined ) {
objlist.push( { object: object,
opaque: { list: [], count: 0 },
transparent: { list: [], count: 0 },
root: root
transparent: { list: [], count: 0 }
} );
objmap[ id ] = 1;
......@@ -1869,8 +1848,7 @@ THREE.WebGLRenderer = function ( parameters ) {
object = scene.objects[ o ];
addObject( scene, object, true );
addChildren( scene, object );
addObject( scene, object );
}
......@@ -1894,9 +1872,21 @@ THREE.WebGLRenderer = function ( parameters ) {
};
this.addToRenderList = function( object ) {
// TODO: implement this
};
this.removeFromRenderList = function( object ) {
// TODO: implement this
};
function setupMatrices ( object, camera ) {
object._modelViewMatrix.multiplyToArray( camera.matrix, object.matrixWorld, object._modelViewMatrixArray );
object._modelViewMatrix.multiplyToArray( camera.globalMatrix, object.globalMatrix, object._modelViewMatrixArray );
object._normalMatrix = THREE.Matrix4.makeInvert3x3( object._modelViewMatrix ).transposeIntoArray( object._normalMatrixArray );
};
......
/**
* @author mr.doob / http://mrdoob.com/
* @author mikael emtinger / http://gomo.se/
*/
THREE.Scene = function () {
THREE.Scene = function() {
// call super
THREE.Object3D.call( this );
this.objects = [];
this.lights = [];
this.fog = null;
this.addObject = function ( object ) {
var i = this.objects.indexOf( object );
if ( i === -1 ) {
// vars
this.objects.push( object );
}
};
this.objects = [];
this.lights = [];
this.fog = null;
this.removeObject = function ( object ) {
};
var i = this.objects.indexOf( object );
THREE.Scene.prototype = new THREE.Object3D();
THREE.Scene.prototype.constructor = THREE.Scene;
THREE.Scene.prototype.supr = THREE.Object3D.prototype;
if ( i !== -1 ) {
/*
* Add Child
*/
this.objects.splice( i, 1 );
THREE.Scene.prototype.addChild = function( child ) {
}
this.supr.addChild.call( this, child );
this.addChildRecurse( child );
};
}
this.addLight = function ( light ) {
THREE.Scene.prototype.addChildRecurse = function( object ) {
if( object instanceof THREE.Light ) {
if( this.lights.indexOf( object ) === -1 )
this.lights.push( object );
var i = this.lights.indexOf( light );
} else if( !( object instanceof THREE.Camera ) ) {
if( this.objects.indexOf( object ) === -1 )
this.objects.push( object );
if ( i === -1 ) {
}
for( var c = 0; c < object.children.length; c++ )
this.addChildRecurse( object.children[ c ] );
this.lights.push( light );
}
}
};
/*
* Remove Child
*/
this.removeLight = function ( light ) {
THREE.Scene.prototype.removeChild = function( child ) {
var i = this.lights.indexOf( light );
this.supr.removeChild.call( this, child );
this.removeChildRecurse( child );
if ( i !== -1 ) {
}
THREE.Scene.prototype.removeChildRecurse = function( child ) {
if( object instanceof THREE.Light ) {
var i = this.lights.indexOf( object );
if( i === -1 )
this.lights.splice( i, 1 );
}
} else if( !( object instanceof THREE.Camera ) ) {
var i = this.objects.indexOf( object );
if( i === -1 )
this.objects.splice( i, 1 );
};
}
for( var c = 0; c < object.children.length; c++ )
this.removeChildRecurse( object.children[ c ] );
this.toString = function () {
}
return 'THREE.Scene ( ' + this.objects + ' )';
};
};
/*
* Backward Compatibility
*/
THREE.Scene.prototype.addObject = THREE.Scene.prototype.addChild;
THREE.Scene.prototype.removeObject = THREE.Scene.prototype.removeChild;
THREE.Scene.prototype.addLight = THREE.Scene.prototype.addChild;
THREE.Scene.prototype.removeLight = THREE.Scene.prototype.removeChild;
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册