initial commit

This commit is contained in:
Mahdi Dibaiee
2018-12-25 17:29:22 +03:30
commit e983346ffc
388 changed files with 174266 additions and 0 deletions

26
lib/objects/Bone.js Normal file
View File

@ -0,0 +1,26 @@
import { Object3D } from '../core/Object3D.js';
/**
* @author mikael emtinger / http://gomo.se/
* @author alteredq / http://alteredqualia.com/
* @author ikerr / http://verold.com
*/
function Bone() {
Object3D.call( this );
this.type = 'Bone';
}
Bone.prototype = Object.assign( Object.create( Object3D.prototype ), {
constructor: Bone,
isBone: true
} );
export { Bone };

24
lib/objects/Group.js Normal file
View File

@ -0,0 +1,24 @@
import { Object3D } from '../core/Object3D.js';
/**
* @author mrdoob / http://mrdoob.com/
*/
function Group() {
Object3D.call( this );
this.type = 'Group';
}
Group.prototype = Object.assign( Object.create( Object3D.prototype ), {
constructor: Group,
isGroup: true
} );
export { Group };

176
lib/objects/LOD.js Normal file
View File

@ -0,0 +1,176 @@
import { Vector3 } from '../math/Vector3.js';
import { Object3D } from '../core/Object3D.js';
/**
* @author mikael emtinger / http://gomo.se/
* @author alteredq / http://alteredqualia.com/
* @author mrdoob / http://mrdoob.com/
*/
function LOD() {
Object3D.call( this );
this.type = 'LOD';
Object.defineProperties( this, {
levels: {
enumerable: true,
value: []
}
} );
}
LOD.prototype = Object.assign( Object.create( Object3D.prototype ), {
constructor: LOD,
copy: function ( source ) {
Object3D.prototype.copy.call( this, source, false );
var levels = source.levels;
for ( var i = 0, l = levels.length; i < l; i ++ ) {
var level = levels[ i ];
this.addLevel( level.object.clone(), level.distance );
}
return this;
},
addLevel: function ( object, distance ) {
if ( distance === undefined ) distance = 0;
distance = Math.abs( distance );
var levels = this.levels;
for ( var l = 0; l < levels.length; l ++ ) {
if ( distance < levels[ l ].distance ) {
break;
}
}
levels.splice( l, 0, { distance: distance, object: object } );
this.add( object );
},
getObjectForDistance: function ( distance ) {
var levels = this.levels;
for ( var i = 1, l = levels.length; i < l; i ++ ) {
if ( distance < levels[ i ].distance ) {
break;
}
}
return levels[ i - 1 ].object;
},
raycast: ( function () {
var matrixPosition = new Vector3();
return function raycast( raycaster, intersects ) {
matrixPosition.setFromMatrixPosition( this.matrixWorld );
var distance = raycaster.ray.origin.distanceTo( matrixPosition );
this.getObjectForDistance( distance ).raycast( raycaster, intersects );
};
}() ),
update: function () {
var v1 = new Vector3();
var v2 = new Vector3();
return function update( camera ) {
var levels = this.levels;
if ( levels.length > 1 ) {
v1.setFromMatrixPosition( camera.matrixWorld );
v2.setFromMatrixPosition( this.matrixWorld );
var distance = v1.distanceTo( v2 );
levels[ 0 ].object.visible = true;
for ( var i = 1, l = levels.length; i < l; i ++ ) {
if ( distance >= levels[ i ].distance ) {
levels[ i - 1 ].object.visible = false;
levels[ i ].object.visible = true;
} else {
break;
}
}
for ( ; i < l; i ++ ) {
levels[ i ].object.visible = false;
}
}
};
}(),
toJSON: function ( meta ) {
var data = Object3D.prototype.toJSON.call( this, meta );
data.object.levels = [];
var levels = this.levels;
for ( var i = 0, l = levels.length; i < l; i ++ ) {
var level = levels[ i ];
data.object.levels.push( {
object: level.object.uuid,
distance: level.distance
} );
}
return data;
}
} );
export { LOD };

267
lib/objects/Line.js Normal file
View File

@ -0,0 +1,267 @@
import { Sphere } from '../math/Sphere.js';
import { Ray } from '../math/Ray.js';
import { Matrix4 } from '../math/Matrix4.js';
import { Object3D } from '../core/Object3D.js';
import { Vector3 } from '../math/Vector3.js';
import { LineBasicMaterial } from '../materials/LineBasicMaterial.js';
import { BufferGeometry } from '../core/BufferGeometry.js';
import { Float32BufferAttribute } from '../core/BufferAttribute.js';
/**
* @author mrdoob / http://mrdoob.com/
*/
function Line( geometry, material, mode ) {
if ( mode === 1 ) {
console.error( 'THREE.Line: parameter THREE.LinePieces no longer supported. Use THREE.LineSegments instead.' );
}
Object3D.call( this );
this.type = 'Line';
this.geometry = geometry !== undefined ? geometry : new BufferGeometry();
this.material = material !== undefined ? material : new LineBasicMaterial( { color: Math.random() * 0xffffff } );
}
Line.prototype = Object.assign( Object.create( Object3D.prototype ), {
constructor: Line,
isLine: true,
computeLineDistances: ( function () {
var start = new Vector3();
var end = new Vector3();
return function computeLineDistances() {
var geometry = this.geometry;
if ( geometry.isBufferGeometry ) {
// we assume non-indexed geometry
if ( geometry.index === null ) {
var positionAttribute = geometry.attributes.position;
var lineDistances = [ 0 ];
for ( var i = 1, l = positionAttribute.count; i < l; i ++ ) {
start.fromBufferAttribute( positionAttribute, i - 1 );
end.fromBufferAttribute( positionAttribute, i );
lineDistances[ i ] = lineDistances[ i - 1 ];
lineDistances[ i ] += start.distanceTo( end );
}
geometry.addAttribute( 'lineDistance', new Float32BufferAttribute( lineDistances, 1 ) );
} else {
console.warn( 'THREE.Line.computeLineDistances(): Computation only possible with non-indexed BufferGeometry.' );
}
} else if ( geometry.isGeometry ) {
var vertices = geometry.vertices;
var lineDistances = geometry.lineDistances;
lineDistances[ 0 ] = 0;
for ( var i = 1, l = vertices.length; i < l; i ++ ) {
lineDistances[ i ] = lineDistances[ i - 1 ];
lineDistances[ i ] += vertices[ i - 1 ].distanceTo( vertices[ i ] );
}
}
return this;
};
}() ),
raycast: ( function () {
var inverseMatrix = new Matrix4();
var ray = new Ray();
var sphere = new Sphere();
return function raycast( raycaster, intersects ) {
var precision = raycaster.linePrecision;
var geometry = this.geometry;
var matrixWorld = this.matrixWorld;
// Checking boundingSphere distance to ray
if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere();
sphere.copy( geometry.boundingSphere );
sphere.applyMatrix4( matrixWorld );
sphere.radius += precision;
if ( raycaster.ray.intersectsSphere( sphere ) === false ) return;
//
inverseMatrix.getInverse( matrixWorld );
ray.copy( raycaster.ray ).applyMatrix4( inverseMatrix );
var localPrecision = precision / ( ( this.scale.x + this.scale.y + this.scale.z ) / 3 );
var localPrecisionSq = localPrecision * localPrecision;
var vStart = new Vector3();
var vEnd = new Vector3();
var interSegment = new Vector3();
var interRay = new Vector3();
var step = ( this && this.isLineSegments ) ? 2 : 1;
if ( geometry.isBufferGeometry ) {
var index = geometry.index;
var attributes = geometry.attributes;
var positions = attributes.position.array;
if ( index !== null ) {
var indices = index.array;
for ( var i = 0, l = indices.length - 1; i < l; i += step ) {
var a = indices[ i ];
var b = indices[ i + 1 ];
vStart.fromArray( positions, a * 3 );
vEnd.fromArray( positions, b * 3 );
var distSq = ray.distanceSqToSegment( vStart, vEnd, interRay, interSegment );
if ( distSq > localPrecisionSq ) continue;
interRay.applyMatrix4( this.matrixWorld ); //Move back to world space for distance calculation
var distance = raycaster.ray.origin.distanceTo( interRay );
if ( distance < raycaster.near || distance > raycaster.far ) continue;
intersects.push( {
distance: distance,
// What do we want? intersection point on the ray or on the segment??
// point: raycaster.ray.at( distance ),
point: interSegment.clone().applyMatrix4( this.matrixWorld ),
index: i,
face: null,
faceIndex: null,
object: this
} );
}
} else {
for ( var i = 0, l = positions.length / 3 - 1; i < l; i += step ) {
vStart.fromArray( positions, 3 * i );
vEnd.fromArray( positions, 3 * i + 3 );
var distSq = ray.distanceSqToSegment( vStart, vEnd, interRay, interSegment );
if ( distSq > localPrecisionSq ) continue;
interRay.applyMatrix4( this.matrixWorld ); //Move back to world space for distance calculation
var distance = raycaster.ray.origin.distanceTo( interRay );
if ( distance < raycaster.near || distance > raycaster.far ) continue;
intersects.push( {
distance: distance,
// What do we want? intersection point on the ray or on the segment??
// point: raycaster.ray.at( distance ),
point: interSegment.clone().applyMatrix4( this.matrixWorld ),
index: i,
face: null,
faceIndex: null,
object: this
} );
}
}
} else if ( geometry.isGeometry ) {
var vertices = geometry.vertices;
var nbVertices = vertices.length;
for ( var i = 0; i < nbVertices - 1; i += step ) {
var distSq = ray.distanceSqToSegment( vertices[ i ], vertices[ i + 1 ], interRay, interSegment );
if ( distSq > localPrecisionSq ) continue;
interRay.applyMatrix4( this.matrixWorld ); //Move back to world space for distance calculation
var distance = raycaster.ray.origin.distanceTo( interRay );
if ( distance < raycaster.near || distance > raycaster.far ) continue;
intersects.push( {
distance: distance,
// What do we want? intersection point on the ray or on the segment??
// point: raycaster.ray.at( distance ),
point: interSegment.clone().applyMatrix4( this.matrixWorld ),
index: i,
face: null,
faceIndex: null,
object: this
} );
}
}
};
}() ),
copy: function ( source ) {
Object3D.prototype.copy.call( this, source );
this.geometry.copy( source.geometry );
this.material.copy( source.material );
return this;
},
clone: function () {
return new this.constructor().copy( this );
}
} );
export { Line };

24
lib/objects/LineLoop.js Normal file
View File

@ -0,0 +1,24 @@
import { Line } from './Line.js';
/**
* @author mgreter / http://github.com/mgreter
*/
function LineLoop( geometry, material ) {
Line.call( this, geometry, material );
this.type = 'LineLoop';
}
LineLoop.prototype = Object.assign( Object.create( Line.prototype ), {
constructor: LineLoop,
isLineLoop: true,
} );
export { LineLoop };

View File

@ -0,0 +1,85 @@
import { Line } from './Line.js';
import { Vector3 } from '../math/Vector3.js';
import { Float32BufferAttribute } from '../core/BufferAttribute.js';
/**
* @author mrdoob / http://mrdoob.com/
*/
function LineSegments( geometry, material ) {
Line.call( this, geometry, material );
this.type = 'LineSegments';
}
LineSegments.prototype = Object.assign( Object.create( Line.prototype ), {
constructor: LineSegments,
isLineSegments: true,
computeLineDistances: ( function () {
var start = new Vector3();
var end = new Vector3();
return function computeLineDistances() {
var geometry = this.geometry;
if ( geometry.isBufferGeometry ) {
// we assume non-indexed geometry
if ( geometry.index === null ) {
var positionAttribute = geometry.attributes.position;
var lineDistances = [];
for ( var i = 0, l = positionAttribute.count; i < l; i += 2 ) {
start.fromBufferAttribute( positionAttribute, i );
end.fromBufferAttribute( positionAttribute, i + 1 );
lineDistances[ i ] = ( i === 0 ) ? 0 : lineDistances[ i - 1 ];
lineDistances[ i + 1 ] = lineDistances[ i ] + start.distanceTo( end );
}
geometry.addAttribute( 'lineDistance', new Float32BufferAttribute( lineDistances, 1 ) );
} else {
console.warn( 'THREE.LineSegments.computeLineDistances(): Computation only possible with non-indexed BufferGeometry.' );
}
} else if ( geometry.isGeometry ) {
var vertices = geometry.vertices;
var lineDistances = geometry.lineDistances;
for ( var i = 0, l = vertices.length; i < l; i += 2 ) {
start.copy( vertices[ i ] );
end.copy( vertices[ i + 1 ] );
lineDistances[ i ] = ( i === 0 ) ? 0 : lineDistances[ i - 1 ];
lineDistances[ i + 1 ] = lineDistances[ i ] + start.distanceTo( end );
}
}
return this;
};
}() )
} );
export { LineSegments };

462
lib/objects/Mesh.js Normal file
View File

@ -0,0 +1,462 @@
import { Vector3 } from '../math/Vector3.js';
import { Vector2 } from '../math/Vector2.js';
import { Sphere } from '../math/Sphere.js';
import { Ray } from '../math/Ray.js';
import { Matrix4 } from '../math/Matrix4.js';
import { Object3D } from '../core/Object3D.js';
import { Triangle } from '../math/Triangle.js';
import { Face3 } from '../core/Face3.js';
import { DoubleSide, BackSide, TrianglesDrawMode } from '../constants.js';
import { MeshBasicMaterial } from '../materials/MeshBasicMaterial.js';
import { BufferGeometry } from '../core/BufferGeometry.js';
/**
* @author mrdoob / http://mrdoob.com/
* @author alteredq / http://alteredqualia.com/
* @author mikael emtinger / http://gomo.se/
* @author jonobr1 / http://jonobr1.com/
*/
function Mesh( geometry, material ) {
Object3D.call( this );
this.type = 'Mesh';
this.geometry = geometry !== undefined ? geometry : new BufferGeometry();
this.material = material !== undefined ? material : new MeshBasicMaterial( { color: Math.random() * 0xffffff } );
this.drawMode = TrianglesDrawMode;
this.updateMorphTargets();
}
Mesh.prototype = Object.assign( Object.create( Object3D.prototype ), {
constructor: Mesh,
isMesh: true,
setDrawMode: function ( value ) {
this.drawMode = value;
},
copy: function ( source ) {
Object3D.prototype.copy.call( this, source );
this.drawMode = source.drawMode;
if ( source.morphTargetInfluences !== undefined ) {
this.morphTargetInfluences = source.morphTargetInfluences.slice();
}
if ( source.morphTargetDictionary !== undefined ) {
this.morphTargetDictionary = Object.assign( {}, source.morphTargetDictionary );
}
return this;
},
updateMorphTargets: function () {
var geometry = this.geometry;
var m, ml, name;
if ( geometry.isBufferGeometry ) {
var morphAttributes = geometry.morphAttributes;
var keys = Object.keys( morphAttributes );
if ( keys.length > 0 ) {
var morphAttribute = morphAttributes[ keys[ 0 ] ];
if ( morphAttribute !== undefined ) {
this.morphTargetInfluences = [];
this.morphTargetDictionary = {};
for ( m = 0, ml = morphAttribute.length; m < ml; m ++ ) {
name = morphAttribute[ m ].name || String( m );
this.morphTargetInfluences.push( 0 );
this.morphTargetDictionary[ name ] = m;
}
}
}
} else {
var morphTargets = geometry.morphTargets;
if ( morphTargets !== undefined && morphTargets.length > 0 ) {
this.morphTargetInfluences = [];
this.morphTargetDictionary = {};
for ( m = 0, ml = morphTargets.length; m < ml; m ++ ) {
name = morphTargets[ m ].name || String( m );
this.morphTargetInfluences.push( 0 );
this.morphTargetDictionary[ name ] = m;
}
}
}
},
raycast: ( function () {
var inverseMatrix = new Matrix4();
var ray = new Ray();
var sphere = new Sphere();
var vA = new Vector3();
var vB = new Vector3();
var vC = new Vector3();
var tempA = new Vector3();
var tempB = new Vector3();
var tempC = new Vector3();
var uvA = new Vector2();
var uvB = new Vector2();
var uvC = new Vector2();
var intersectionPoint = new Vector3();
var intersectionPointWorld = new Vector3();
function checkIntersection( object, material, raycaster, ray, pA, pB, pC, point ) {
var intersect;
if ( material.side === BackSide ) {
intersect = ray.intersectTriangle( pC, pB, pA, true, point );
} else {
intersect = ray.intersectTriangle( pA, pB, pC, material.side !== DoubleSide, point );
}
if ( intersect === null ) return null;
intersectionPointWorld.copy( point );
intersectionPointWorld.applyMatrix4( object.matrixWorld );
var distance = raycaster.ray.origin.distanceTo( intersectionPointWorld );
if ( distance < raycaster.near || distance > raycaster.far ) return null;
return {
distance: distance,
point: intersectionPointWorld.clone(),
object: object
};
}
function checkBufferGeometryIntersection( object, material, raycaster, ray, position, uv, a, b, c ) {
vA.fromBufferAttribute( position, a );
vB.fromBufferAttribute( position, b );
vC.fromBufferAttribute( position, c );
var intersection = checkIntersection( object, material, raycaster, ray, vA, vB, vC, intersectionPoint );
if ( intersection ) {
if ( uv ) {
uvA.fromBufferAttribute( uv, a );
uvB.fromBufferAttribute( uv, b );
uvC.fromBufferAttribute( uv, c );
intersection.uv = Triangle.getUV( intersectionPoint, vA, vB, vC, uvA, uvB, uvC, new Vector2() );
}
var face = new Face3( a, b, c );
Triangle.getNormal( vA, vB, vC, face.normal );
intersection.face = face;
}
return intersection;
}
return function raycast( raycaster, intersects ) {
var geometry = this.geometry;
var material = this.material;
var matrixWorld = this.matrixWorld;
if ( material === undefined ) return;
// Checking boundingSphere distance to ray
if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere();
sphere.copy( geometry.boundingSphere );
sphere.applyMatrix4( matrixWorld );
if ( raycaster.ray.intersectsSphere( sphere ) === false ) return;
//
inverseMatrix.getInverse( matrixWorld );
ray.copy( raycaster.ray ).applyMatrix4( inverseMatrix );
// Check boundingBox before continuing
if ( geometry.boundingBox !== null ) {
if ( ray.intersectsBox( geometry.boundingBox ) === false ) return;
}
var intersection;
if ( geometry.isBufferGeometry ) {
var a, b, c;
var index = geometry.index;
var position = geometry.attributes.position;
var uv = geometry.attributes.uv;
var groups = geometry.groups;
var drawRange = geometry.drawRange;
var i, j, il, jl;
var group, groupMaterial;
var start, end;
if ( index !== null ) {
// indexed buffer geometry
if ( Array.isArray( material ) ) {
for ( i = 0, il = groups.length; i < il; i ++ ) {
group = groups[ i ];
groupMaterial = material[ group.materialIndex ];
start = Math.max( group.start, drawRange.start );
end = Math.min( ( group.start + group.count ), ( drawRange.start + drawRange.count ) );
for ( j = start, jl = end; j < jl; j += 3 ) {
a = index.getX( j );
b = index.getX( j + 1 );
c = index.getX( j + 2 );
intersection = checkBufferGeometryIntersection( this, groupMaterial, raycaster, ray, position, uv, a, b, c );
if ( intersection ) {
intersection.faceIndex = Math.floor( j / 3 ); // triangle number in indexed buffer semantics
intersects.push( intersection );
}
}
}
} else {
start = Math.max( 0, drawRange.start );
end = Math.min( index.count, ( drawRange.start + drawRange.count ) );
for ( i = start, il = end; i < il; i += 3 ) {
a = index.getX( i );
b = index.getX( i + 1 );
c = index.getX( i + 2 );
intersection = checkBufferGeometryIntersection( this, material, raycaster, ray, position, uv, a, b, c );
if ( intersection ) {
intersection.faceIndex = Math.floor( i / 3 ); // triangle number in indexed buffer semantics
intersects.push( intersection );
}
}
}
} else if ( position !== undefined ) {
// non-indexed buffer geometry
if ( Array.isArray( material ) ) {
for ( i = 0, il = groups.length; i < il; i ++ ) {
group = groups[ i ];
groupMaterial = material[ group.materialIndex ];
start = Math.max( group.start, drawRange.start );
end = Math.min( ( group.start + group.count ), ( drawRange.start + drawRange.count ) );
for ( j = start, jl = end; j < jl; j += 3 ) {
a = j;
b = j + 1;
c = j + 2;
intersection = checkBufferGeometryIntersection( this, groupMaterial, raycaster, ray, position, uv, a, b, c );
if ( intersection ) {
intersection.faceIndex = Math.floor( j / 3 ); // triangle number in non-indexed buffer semantics
intersects.push( intersection );
}
}
}
} else {
start = Math.max( 0, drawRange.start );
end = Math.min( position.count, ( drawRange.start + drawRange.count ) );
for ( i = start, il = end; i < il; i += 3 ) {
a = i;
b = i + 1;
c = i + 2;
intersection = checkBufferGeometryIntersection( this, material, raycaster, ray, position, uv, a, b, c );
if ( intersection ) {
intersection.faceIndex = Math.floor( i / 3 ); // triangle number in non-indexed buffer semantics
intersects.push( intersection );
}
}
}
}
} else if ( geometry.isGeometry ) {
var fvA, fvB, fvC;
var isMultiMaterial = Array.isArray( material );
var vertices = geometry.vertices;
var faces = geometry.faces;
var uvs;
var faceVertexUvs = geometry.faceVertexUvs[ 0 ];
if ( faceVertexUvs.length > 0 ) uvs = faceVertexUvs;
for ( var f = 0, fl = faces.length; f < fl; f ++ ) {
var face = faces[ f ];
var faceMaterial = isMultiMaterial ? material[ face.materialIndex ] : material;
if ( faceMaterial === undefined ) continue;
fvA = vertices[ face.a ];
fvB = vertices[ face.b ];
fvC = vertices[ face.c ];
if ( faceMaterial.morphTargets === true ) {
var morphTargets = geometry.morphTargets;
var morphInfluences = this.morphTargetInfluences;
vA.set( 0, 0, 0 );
vB.set( 0, 0, 0 );
vC.set( 0, 0, 0 );
for ( var t = 0, tl = morphTargets.length; t < tl; t ++ ) {
var influence = morphInfluences[ t ];
if ( influence === 0 ) continue;
var targets = morphTargets[ t ].vertices;
vA.addScaledVector( tempA.subVectors( targets[ face.a ], fvA ), influence );
vB.addScaledVector( tempB.subVectors( targets[ face.b ], fvB ), influence );
vC.addScaledVector( tempC.subVectors( targets[ face.c ], fvC ), influence );
}
vA.add( fvA );
vB.add( fvB );
vC.add( fvC );
fvA = vA;
fvB = vB;
fvC = vC;
}
intersection = checkIntersection( this, faceMaterial, raycaster, ray, fvA, fvB, fvC, intersectionPoint );
if ( intersection ) {
if ( uvs && uvs[ f ] ) {
var uvs_f = uvs[ f ];
uvA.copy( uvs_f[ 0 ] );
uvB.copy( uvs_f[ 1 ] );
uvC.copy( uvs_f[ 2 ] );
intersection.uv = Triangle.getUV( intersectionPoint, fvA, fvB, fvC, uvA, uvB, uvC, new Vector2() );
}
intersection.face = face;
intersection.faceIndex = f;
intersects.push( intersection );
}
}
}
};
}() ),
clone: function () {
return new this.constructor( this.geometry, this.material ).copy( this );
}
} );
export { Mesh };

148
lib/objects/Points.js Normal file
View File

@ -0,0 +1,148 @@
import { Sphere } from '../math/Sphere.js';
import { Ray } from '../math/Ray.js';
import { Matrix4 } from '../math/Matrix4.js';
import { Object3D } from '../core/Object3D.js';
import { Vector3 } from '../math/Vector3.js';
import { PointsMaterial } from '../materials/PointsMaterial.js';
import { BufferGeometry } from '../core/BufferGeometry.js';
/**
* @author alteredq / http://alteredqualia.com/
*/
function Points( geometry, material ) {
Object3D.call( this );
this.type = 'Points';
this.geometry = geometry !== undefined ? geometry : new BufferGeometry();
this.material = material !== undefined ? material : new PointsMaterial( { color: Math.random() * 0xffffff } );
}
Points.prototype = Object.assign( Object.create( Object3D.prototype ), {
constructor: Points,
isPoints: true,
raycast: ( function () {
var inverseMatrix = new Matrix4();
var ray = new Ray();
var sphere = new Sphere();
return function raycast( raycaster, intersects ) {
var object = this;
var geometry = this.geometry;
var matrixWorld = this.matrixWorld;
var threshold = raycaster.params.Points.threshold;
// Checking boundingSphere distance to ray
if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere();
sphere.copy( geometry.boundingSphere );
sphere.applyMatrix4( matrixWorld );
sphere.radius += threshold;
if ( raycaster.ray.intersectsSphere( sphere ) === false ) return;
//
inverseMatrix.getInverse( matrixWorld );
ray.copy( raycaster.ray ).applyMatrix4( inverseMatrix );
var localThreshold = threshold / ( ( this.scale.x + this.scale.y + this.scale.z ) / 3 );
var localThresholdSq = localThreshold * localThreshold;
var position = new Vector3();
var intersectPoint = new Vector3();
function testPoint( point, index ) {
var rayPointDistanceSq = ray.distanceSqToPoint( point );
if ( rayPointDistanceSq < localThresholdSq ) {
ray.closestPointToPoint( point, intersectPoint );
intersectPoint.applyMatrix4( matrixWorld );
var distance = raycaster.ray.origin.distanceTo( intersectPoint );
if ( distance < raycaster.near || distance > raycaster.far ) return;
intersects.push( {
distance: distance,
distanceToRay: Math.sqrt( rayPointDistanceSq ),
point: intersectPoint.clone(),
index: index,
face: null,
object: object
} );
}
}
if ( geometry.isBufferGeometry ) {
var index = geometry.index;
var attributes = geometry.attributes;
var positions = attributes.position.array;
if ( index !== null ) {
var indices = index.array;
for ( var i = 0, il = indices.length; i < il; i ++ ) {
var a = indices[ i ];
position.fromArray( positions, a * 3 );
testPoint( position, a );
}
} else {
for ( var i = 0, l = positions.length / 3; i < l; i ++ ) {
position.fromArray( positions, i * 3 );
testPoint( position, i );
}
}
} else {
var vertices = geometry.vertices;
for ( var i = 0, l = vertices.length; i < l; i ++ ) {
testPoint( vertices[ i ], i );
}
}
};
}() ),
clone: function () {
return new this.constructor( this.geometry, this.material ).copy( this );
}
} );
export { Points };

178
lib/objects/Skeleton.js Normal file
View File

@ -0,0 +1,178 @@
import { Matrix4 } from '../math/Matrix4.js';
/**
* @author mikael emtinger / http://gomo.se/
* @author alteredq / http://alteredqualia.com/
* @author michael guerrero / http://realitymeltdown.com
* @author ikerr / http://verold.com
*/
function Skeleton( bones, boneInverses ) {
// copy the bone array
bones = bones || [];
this.bones = bones.slice( 0 );
this.boneMatrices = new Float32Array( this.bones.length * 16 );
// use the supplied bone inverses or calculate the inverses
if ( boneInverses === undefined ) {
this.calculateInverses();
} else {
if ( this.bones.length === boneInverses.length ) {
this.boneInverses = boneInverses.slice( 0 );
} else {
console.warn( 'THREE.Skeleton boneInverses is the wrong length.' );
this.boneInverses = [];
for ( var i = 0, il = this.bones.length; i < il; i ++ ) {
this.boneInverses.push( new Matrix4() );
}
}
}
}
Object.assign( Skeleton.prototype, {
calculateInverses: function () {
this.boneInverses = [];
for ( var i = 0, il = this.bones.length; i < il; i ++ ) {
var inverse = new Matrix4();
if ( this.bones[ i ] ) {
inverse.getInverse( this.bones[ i ].matrixWorld );
}
this.boneInverses.push( inverse );
}
},
pose: function () {
var bone, i, il;
// recover the bind-time world matrices
for ( i = 0, il = this.bones.length; i < il; i ++ ) {
bone = this.bones[ i ];
if ( bone ) {
bone.matrixWorld.getInverse( this.boneInverses[ i ] );
}
}
// compute the local matrices, positions, rotations and scales
for ( i = 0, il = this.bones.length; i < il; i ++ ) {
bone = this.bones[ i ];
if ( bone ) {
if ( bone.parent && bone.parent.isBone ) {
bone.matrix.getInverse( bone.parent.matrixWorld );
bone.matrix.multiply( bone.matrixWorld );
} else {
bone.matrix.copy( bone.matrixWorld );
}
bone.matrix.decompose( bone.position, bone.quaternion, bone.scale );
}
}
},
update: ( function () {
var offsetMatrix = new Matrix4();
var identityMatrix = new Matrix4();
return function update() {
var bones = this.bones;
var boneInverses = this.boneInverses;
var boneMatrices = this.boneMatrices;
var boneTexture = this.boneTexture;
// flatten bone matrices to array
for ( var i = 0, il = bones.length; i < il; i ++ ) {
// compute the offset between the current and the original transform
var matrix = bones[ i ] ? bones[ i ].matrixWorld : identityMatrix;
offsetMatrix.multiplyMatrices( matrix, boneInverses[ i ] );
offsetMatrix.toArray( boneMatrices, i * 16 );
}
if ( boneTexture !== undefined ) {
boneTexture.needsUpdate = true;
}
};
} )(),
clone: function () {
return new Skeleton( this.bones, this.boneInverses );
},
getBoneByName: function ( name ) {
for ( var i = 0, il = this.bones.length; i < il; i ++ ) {
var bone = this.bones[ i ];
if ( bone.name === name ) {
return bone;
}
}
return undefined;
}
} );
export { Skeleton };

209
lib/objects/SkinnedMesh.js Normal file
View File

@ -0,0 +1,209 @@
import { Mesh } from './Mesh.js';
import { Vector4 } from '../math/Vector4.js';
import { Skeleton } from './Skeleton.js';
import { Bone } from './Bone.js';
import { Matrix4 } from '../math/Matrix4.js';
/**
* @author mikael emtinger / http://gomo.se/
* @author alteredq / http://alteredqualia.com/
* @author ikerr / http://verold.com
*/
function SkinnedMesh( geometry, material ) {
Mesh.call( this, geometry, material );
this.type = 'SkinnedMesh';
this.bindMode = 'attached';
this.bindMatrix = new Matrix4();
this.bindMatrixInverse = new Matrix4();
var bones = this.initBones();
var skeleton = new Skeleton( bones );
this.bind( skeleton, this.matrixWorld );
this.normalizeSkinWeights();
}
SkinnedMesh.prototype = Object.assign( Object.create( Mesh.prototype ), {
constructor: SkinnedMesh,
isSkinnedMesh: true,
initBones: function () {
var bones = [], bone, gbone;
var i, il;
if ( this.geometry && this.geometry.bones !== undefined ) {
// first, create array of 'Bone' objects from geometry data
for ( i = 0, il = this.geometry.bones.length; i < il; i ++ ) {
gbone = this.geometry.bones[ i ];
// create new 'Bone' object
bone = new Bone();
bones.push( bone );
// apply values
bone.name = gbone.name;
bone.position.fromArray( gbone.pos );
bone.quaternion.fromArray( gbone.rotq );
if ( gbone.scl !== undefined ) bone.scale.fromArray( gbone.scl );
}
// second, create bone hierarchy
for ( i = 0, il = this.geometry.bones.length; i < il; i ++ ) {
gbone = this.geometry.bones[ i ];
if ( ( gbone.parent !== - 1 ) && ( gbone.parent !== null ) && ( bones[ gbone.parent ] !== undefined ) ) {
// subsequent bones in the hierarchy
bones[ gbone.parent ].add( bones[ i ] );
} else {
// topmost bone, immediate child of the skinned mesh
this.add( bones[ i ] );
}
}
}
// now the bones are part of the scene graph and children of the skinned mesh.
// let's update the corresponding matrices
this.updateMatrixWorld( true );
return bones;
},
bind: function ( skeleton, bindMatrix ) {
this.skeleton = skeleton;
if ( bindMatrix === undefined ) {
this.updateMatrixWorld( true );
this.skeleton.calculateInverses();
bindMatrix = this.matrixWorld;
}
this.bindMatrix.copy( bindMatrix );
this.bindMatrixInverse.getInverse( bindMatrix );
},
pose: function () {
this.skeleton.pose();
},
normalizeSkinWeights: function () {
var scale, i;
if ( this.geometry && this.geometry.isGeometry ) {
for ( i = 0; i < this.geometry.skinWeights.length; i ++ ) {
var sw = this.geometry.skinWeights[ i ];
scale = 1.0 / sw.manhattanLength();
if ( scale !== Infinity ) {
sw.multiplyScalar( scale );
} else {
sw.set( 1, 0, 0, 0 ); // do something reasonable
}
}
} else if ( this.geometry && this.geometry.isBufferGeometry ) {
var vec = new Vector4();
var skinWeight = this.geometry.attributes.skinWeight;
for ( i = 0; i < skinWeight.count; i ++ ) {
vec.x = skinWeight.getX( i );
vec.y = skinWeight.getY( i );
vec.z = skinWeight.getZ( i );
vec.w = skinWeight.getW( i );
scale = 1.0 / vec.manhattanLength();
if ( scale !== Infinity ) {
vec.multiplyScalar( scale );
} else {
vec.set( 1, 0, 0, 0 ); // do something reasonable
}
skinWeight.setXYZW( i, vec.x, vec.y, vec.z, vec.w );
}
}
},
updateMatrixWorld: function ( force ) {
Mesh.prototype.updateMatrixWorld.call( this, force );
if ( this.bindMode === 'attached' ) {
this.bindMatrixInverse.getInverse( this.matrixWorld );
} else if ( this.bindMode === 'detached' ) {
this.bindMatrixInverse.getInverse( this.bindMatrix );
} else {
console.warn( 'THREE.SkinnedMesh: Unrecognized bindMode: ' + this.bindMode );
}
},
clone: function () {
return new this.constructor( this.geometry, this.material ).copy( this );
}
} );
export { SkinnedMesh };

222
lib/objects/Sky.js Normal file
View File

@ -0,0 +1,222 @@
/**
* @author zz85 / https://github.com/zz85
*
* Based on "A Practical Analytic Model for Daylight"
* aka The Preetham Model, the de facto standard analytic skydome model
* http://www.cs.utah.edu/~shirley/papers/sunsky/sunsky.pdf
*
* First implemented by Simon Wallner
* http://www.simonwallner.at/projects/atmospheric-scattering
*
* Improved by Martin Upitis
* http://blenderartists.org/forum/showthread.php?245954-preethams-sky-impementation-HDR
*
* Three.js integration by zz85 http://twitter.com/blurspline
*/
THREE.Sky = function () {
var shader = THREE.Sky.SkyShader;
var material = new THREE.ShaderMaterial( {
fragmentShader: shader.fragmentShader,
vertexShader: shader.vertexShader,
uniforms: THREE.UniformsUtils.clone( shader.uniforms ),
side: THREE.BackSide
} );
THREE.Mesh.call( this, new THREE.BoxBufferGeometry( 1, 1, 1 ), material );
};
THREE.Sky.prototype = Object.create( THREE.Mesh.prototype );
THREE.Sky.SkyShader = {
uniforms: {
luminance: { value: 1 },
turbidity: { value: 2 },
rayleigh: { value: 1 },
mieCoefficient: { value: 0.005 },
mieDirectionalG: { value: 0.8 },
sunPosition: { value: new THREE.Vector3() }
},
vertexShader: [
'uniform vec3 sunPosition;',
'uniform float rayleigh;',
'uniform float turbidity;',
'uniform float mieCoefficient;',
'varying vec3 vWorldPosition;',
'varying vec3 vSunDirection;',
'varying float vSunfade;',
'varying vec3 vBetaR;',
'varying vec3 vBetaM;',
'varying float vSunE;',
'const vec3 up = vec3( 0.0, 1.0, 0.0 );',
// constants for atmospheric scattering
'const float e = 2.71828182845904523536028747135266249775724709369995957;',
'const float pi = 3.141592653589793238462643383279502884197169;',
// wavelength of used primaries, according to preetham
'const vec3 lambda = vec3( 680E-9, 550E-9, 450E-9 );',
// this pre-calcuation replaces older TotalRayleigh(vec3 lambda) function:
// (8.0 * pow(pi, 3.0) * pow(pow(n, 2.0) - 1.0, 2.0) * (6.0 + 3.0 * pn)) / (3.0 * N * pow(lambda, vec3(4.0)) * (6.0 - 7.0 * pn))
'const vec3 totalRayleigh = vec3( 5.804542996261093E-6, 1.3562911419845635E-5, 3.0265902468824876E-5 );',
// mie stuff
// K coefficient for the primaries
'const float v = 4.0;',
'const vec3 K = vec3( 0.686, 0.678, 0.666 );',
// MieConst = pi * pow( ( 2.0 * pi ) / lambda, vec3( v - 2.0 ) ) * K
'const vec3 MieConst = vec3( 1.8399918514433978E14, 2.7798023919660528E14, 4.0790479543861094E14 );',
// earth shadow hack
// cutoffAngle = pi / 1.95;
'const float cutoffAngle = 1.6110731556870734;',
'const float steepness = 1.5;',
'const float EE = 1000.0;',
'float sunIntensity( float zenithAngleCos ) {',
' zenithAngleCos = clamp( zenithAngleCos, -1.0, 1.0 );',
' return EE * max( 0.0, 1.0 - pow( e, -( ( cutoffAngle - acos( zenithAngleCos ) ) / steepness ) ) );',
'}',
'vec3 totalMie( float T ) {',
' float c = ( 0.2 * T ) * 10E-18;',
' return 0.434 * c * MieConst;',
'}',
'void main() {',
' vec4 worldPosition = modelMatrix * vec4( position, 1.0 );',
' vWorldPosition = worldPosition.xyz;',
' gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );',
' gl_Position.z = gl_Position.w;', // set z to camera.far
' vSunDirection = normalize( sunPosition );',
' vSunE = sunIntensity( dot( vSunDirection, up ) );',
' vSunfade = 1.0 - clamp( 1.0 - exp( ( sunPosition.y / 450000.0 ) ), 0.0, 1.0 );',
' float rayleighCoefficient = rayleigh - ( 1.0 * ( 1.0 - vSunfade ) );',
// extinction (absorbtion + out scattering)
// rayleigh coefficients
' vBetaR = totalRayleigh * rayleighCoefficient;',
// mie coefficients
' vBetaM = totalMie( turbidity ) * mieCoefficient;',
'}'
].join( '\n' ),
fragmentShader: [
'varying vec3 vWorldPosition;',
'varying vec3 vSunDirection;',
'varying float vSunfade;',
'varying vec3 vBetaR;',
'varying vec3 vBetaM;',
'varying float vSunE;',
'uniform float luminance;',
'uniform float mieDirectionalG;',
'const vec3 cameraPos = vec3( 0.0, 0.0, 0.0 );',
// constants for atmospheric scattering
'const float pi = 3.141592653589793238462643383279502884197169;',
'const float n = 1.0003;', // refractive index of air
'const float N = 2.545E25;', // number of molecules per unit volume for air at
// 288.15K and 1013mb (sea level -45 celsius)
// optical length at zenith for molecules
'const float rayleighZenithLength = 8.4E3;',
'const float mieZenithLength = 1.25E3;',
'const vec3 up = vec3( 0.0, 1.0, 0.0 );',
// 66 arc seconds -> degrees, and the cosine of that
'const float sunAngularDiameterCos = 0.999956676946448443553574619906976478926848692873900859324;',
// 3.0 / ( 16.0 * pi )
'const float THREE_OVER_SIXTEENPI = 0.05968310365946075;',
// 1.0 / ( 4.0 * pi )
'const float ONE_OVER_FOURPI = 0.07957747154594767;',
'float rayleighPhase( float cosTheta ) {',
' return THREE_OVER_SIXTEENPI * ( 1.0 + pow( cosTheta, 2.0 ) );',
'}',
'float hgPhase( float cosTheta, float g ) {',
' float g2 = pow( g, 2.0 );',
' float inverse = 1.0 / pow( 1.0 - 2.0 * g * cosTheta + g2, 1.5 );',
' return ONE_OVER_FOURPI * ( ( 1.0 - g2 ) * inverse );',
'}',
// Filmic ToneMapping http://filmicgames.com/archives/75
'const float A = 0.15;',
'const float B = 0.50;',
'const float C = 0.10;',
'const float D = 0.20;',
'const float E = 0.02;',
'const float F = 0.30;',
'const float whiteScale = 1.0748724675633854;', // 1.0 / Uncharted2Tonemap(1000.0)
'vec3 Uncharted2Tonemap( vec3 x ) {',
' return ( ( x * ( A * x + C * B ) + D * E ) / ( x * ( A * x + B ) + D * F ) ) - E / F;',
'}',
'void main() {',
// optical length
// cutoff angle at 90 to avoid singularity in next formula.
' float zenithAngle = acos( max( 0.0, dot( up, normalize( vWorldPosition - cameraPos ) ) ) );',
' float inverse = 1.0 / ( cos( zenithAngle ) + 0.15 * pow( 93.885 - ( ( zenithAngle * 180.0 ) / pi ), -1.253 ) );',
' float sR = rayleighZenithLength * inverse;',
' float sM = mieZenithLength * inverse;',
// combined extinction factor
' vec3 Fex = exp( -( vBetaR * sR + vBetaM * sM ) );',
// in scattering
' float cosTheta = dot( normalize( vWorldPosition - cameraPos ), vSunDirection );',
' float rPhase = rayleighPhase( cosTheta * 0.5 + 0.5 );',
' vec3 betaRTheta = vBetaR * rPhase;',
' float mPhase = hgPhase( cosTheta, mieDirectionalG );',
' vec3 betaMTheta = vBetaM * mPhase;',
' vec3 Lin = pow( vSunE * ( ( betaRTheta + betaMTheta ) / ( vBetaR + vBetaM ) ) * ( 1.0 - Fex ), vec3( 1.5 ) );',
' Lin *= mix( vec3( 1.0 ), pow( vSunE * ( ( betaRTheta + betaMTheta ) / ( vBetaR + vBetaM ) ) * Fex, vec3( 1.0 / 2.0 ) ), clamp( pow( 1.0 - dot( up, vSunDirection ), 5.0 ), 0.0, 1.0 ) );',
// nightsky
' vec3 direction = normalize( vWorldPosition - cameraPos );',
' float theta = acos( direction.y ); // elevation --> y-axis, [-pi/2, pi/2]',
' float phi = atan( direction.z, direction.x ); // azimuth --> x-axis [-pi/2, pi/2]',
' vec2 uv = vec2( phi, theta ) / vec2( 2.0 * pi, pi ) + vec2( 0.5, 0.0 );',
' vec3 L0 = vec3( 0.1 ) * Fex;',
// composition + solar disc
' float sundisk = smoothstep( sunAngularDiameterCos, sunAngularDiameterCos + 0.00002, cosTheta );',
' L0 += ( vSunE * 19000.0 * Fex ) * sundisk;',
' vec3 texColor = ( Lin + L0 ) * 0.04 + vec3( 0.0, 0.0003, 0.00075 );',
' vec3 curr = Uncharted2Tonemap( ( log2( 2.0 / pow( luminance, 4.0 ) ) ) * texColor );',
' vec3 color = curr * whiteScale;',
' vec3 retColor = pow( color, vec3( 1.0 / ( 1.2 + ( 1.2 * vSunfade ) ) ) );',
' gl_FragColor = vec4( retColor, 1.0 );',
'}'
].join( '\n' )
};

181
lib/objects/Sprite.js Normal file
View File

@ -0,0 +1,181 @@
/**
* @author mikael emtinger / http://gomo.se/
* @author alteredq / http://alteredqualia.com/
*/
import { Vector2 } from '../math/Vector2.js';
import { Vector3 } from '../math/Vector3.js';
import { Matrix4 } from '../math/Matrix4.js';
import { Triangle } from '../math/Triangle.js';
import { Object3D } from '../core/Object3D.js';
import { BufferGeometry } from '../core/BufferGeometry.js';
import { InterleavedBuffer } from '../core/InterleavedBuffer.js';
import { InterleavedBufferAttribute } from '../core/InterleavedBufferAttribute.js';
import { SpriteMaterial } from '../materials/SpriteMaterial.js';
var geometry;
function Sprite( material ) {
Object3D.call( this );
this.type = 'Sprite';
if ( geometry === undefined ) {
geometry = new BufferGeometry();
var float32Array = new Float32Array( [
- 0.5, - 0.5, 0, 0, 0,
0.5, - 0.5, 0, 1, 0,
0.5, 0.5, 0, 1, 1,
- 0.5, 0.5, 0, 0, 1
] );
var interleavedBuffer = new InterleavedBuffer( float32Array, 5 );
geometry.setIndex( [ 0, 1, 2, 0, 2, 3 ] );
geometry.addAttribute( 'position', new InterleavedBufferAttribute( interleavedBuffer, 3, 0, false ) );
geometry.addAttribute( 'uv', new InterleavedBufferAttribute( interleavedBuffer, 2, 3, false ) );
}
this.geometry = geometry;
this.material = ( material !== undefined ) ? material : new SpriteMaterial();
this.center = new Vector2( 0.5, 0.5 );
}
Sprite.prototype = Object.assign( Object.create( Object3D.prototype ), {
constructor: Sprite,
isSprite: true,
raycast: ( function () {
var intersectPoint = new Vector3();
var worldScale = new Vector3();
var mvPosition = new Vector3();
var alignedPosition = new Vector2();
var rotatedPosition = new Vector2();
var viewWorldMatrix = new Matrix4();
var vA = new Vector3();
var vB = new Vector3();
var vC = new Vector3();
var uvA = new Vector2();
var uvB = new Vector2();
var uvC = new Vector2();
function transformVertex( vertexPosition, mvPosition, center, scale, sin, cos ) {
// compute position in camera space
alignedPosition.subVectors( vertexPosition, center ).addScalar( 0.5 ).multiply( scale );
// to check if rotation is not zero
if ( sin !== undefined ) {
rotatedPosition.x = ( cos * alignedPosition.x ) - ( sin * alignedPosition.y );
rotatedPosition.y = ( sin * alignedPosition.x ) + ( cos * alignedPosition.y );
} else {
rotatedPosition.copy( alignedPosition );
}
vertexPosition.copy( mvPosition );
vertexPosition.x += rotatedPosition.x;
vertexPosition.y += rotatedPosition.y;
// transform to world space
vertexPosition.applyMatrix4( viewWorldMatrix );
}
return function raycast( raycaster, intersects ) {
worldScale.setFromMatrixScale( this.matrixWorld );
viewWorldMatrix.getInverse( this.modelViewMatrix ).premultiply( this.matrixWorld );
mvPosition.setFromMatrixPosition( this.modelViewMatrix );
var rotation = this.material.rotation;
var sin, cos;
if ( rotation !== 0 ) {
cos = Math.cos( rotation );
sin = Math.sin( rotation );
}
var center = this.center;
transformVertex( vA.set( - 0.5, - 0.5, 0 ), mvPosition, center, worldScale, sin, cos );
transformVertex( vB.set( 0.5, - 0.5, 0 ), mvPosition, center, worldScale, sin, cos );
transformVertex( vC.set( 0.5, 0.5, 0 ), mvPosition, center, worldScale, sin, cos );
uvA.set( 0, 0 );
uvB.set( 1, 0 );
uvC.set( 1, 1 );
// check first triangle
var intersect = raycaster.ray.intersectTriangle( vA, vB, vC, false, intersectPoint );
if ( intersect === null ) {
// check second triangle
transformVertex( vB.set( - 0.5, 0.5, 0 ), mvPosition, center, worldScale, sin, cos );
uvB.set( 0, 1 );
intersect = raycaster.ray.intersectTriangle( vA, vC, vB, false, intersectPoint );
if ( intersect === null ) {
return;
}
}
var distance = raycaster.ray.origin.distanceTo( intersectPoint );
if ( distance < raycaster.near || distance > raycaster.far ) return;
intersects.push( {
distance: distance,
point: intersectPoint.clone(),
uv: Triangle.getUV( intersectPoint, vA, vB, vC, uvA, uvB, uvC, new Vector2() ),
face: null,
object: this
} );
};
}() ),
clone: function () {
return new this.constructor( this.material ).copy( this );
},
copy: function ( source ) {
Object3D.prototype.copy.call( this, source );
if ( source.center !== undefined ) this.center.copy( source.center );
return this;
}
} );
export { Sprite };