未验证 提交 3452a4e3 编写于 作者: M Michael Herzog 提交者: GitHub

Examples: Convert misc to ES6. (#21618)

上级 8f6cc7df
......@@ -29,40 +29,42 @@
*
*/
var ConvexObjectBreaker = function ( minSizeForBreak, smallDelta ) {
this.minSizeForBreak = minSizeForBreak || 1.4;
this.smallDelta = smallDelta || 0.0001;
this.tempLine1 = new THREE.Line3();
this.tempPlane1 = new THREE.Plane();
this.tempPlane2 = new THREE.Plane();
this.tempPlane_Cut = new THREE.Plane();
this.tempCM1 = new THREE.Vector3();
this.tempCM2 = new THREE.Vector3();
this.tempVector3 = new THREE.Vector3();
this.tempVector3_2 = new THREE.Vector3();
this.tempVector3_3 = new THREE.Vector3();
this.tempVector3_P0 = new THREE.Vector3();
this.tempVector3_P1 = new THREE.Vector3();
this.tempVector3_P2 = new THREE.Vector3();
this.tempVector3_N0 = new THREE.Vector3();
this.tempVector3_N1 = new THREE.Vector3();
this.tempVector3_AB = new THREE.Vector3();
this.tempVector3_CB = new THREE.Vector3();
this.tempResultObjects = {
object1: null,
object2: null
};
this.segments = [];
var n = 30 * 30;
for ( var i = 0; i < n; i ++ ) this.segments[ i ] = false;
};
ConvexObjectBreaker.prototype = {
constructor: ConvexObjectBreaker,
prepareBreakableObject: function ( object, mass, velocity, angularVelocity, breakable ) {
const _v1 = new THREE.Vector3();
class ConvexObjectBreaker {
constructor( minSizeForBreak = 1.4, smallDelta = 0.0001 ) {
this.minSizeForBreak = minSizeForBreak;
this.smallDelta = smallDelta;
this.tempLine1 = new THREE.Line3();
this.tempPlane1 = new THREE.Plane();
this.tempPlane2 = new THREE.Plane();
this.tempPlane_Cut = new THREE.Plane();
this.tempCM1 = new THREE.Vector3();
this.tempCM2 = new THREE.Vector3();
this.tempVector3 = new THREE.Vector3();
this.tempVector3_2 = new THREE.Vector3();
this.tempVector3_3 = new THREE.Vector3();
this.tempVector3_P0 = new THREE.Vector3();
this.tempVector3_P1 = new THREE.Vector3();
this.tempVector3_P2 = new THREE.Vector3();
this.tempVector3_N0 = new THREE.Vector3();
this.tempVector3_N1 = new THREE.Vector3();
this.tempVector3_AB = new THREE.Vector3();
this.tempVector3_CB = new THREE.Vector3();
this.tempResultObjects = {
object1: null,
object2: null
};
this.segments = [];
const n = 30 * 30;
for ( let i = 0; i < n; i ++ ) this.segments[ i ] = false;
}
prepareBreakableObject( object, mass, velocity, angularVelocity, breakable ) {
// object is a Object3d (normally a THREE.Mesh), must have a BufferGeometry, and it must be convex.
// Its material property is propagated to its children (sub-pieces)
......@@ -73,29 +75,30 @@
}
var userData = object.userData;
const userData = object.userData;
userData.mass = mass;
userData.velocity = velocity.clone();
userData.angularVelocity = angularVelocity.clone();
userData.breakable = breakable;
},
}
/*
* @param {int} maxRadialIterations Iterations for radial cuts.
* @param {int} maxRandomIterations Max random iterations for not-radial cuts
*
* Returns the array of pieces
*/
subdivideByImpact: function ( object, pointOfImpact, normal, maxRadialIterations, maxRandomIterations ) {
var debris = [];
var tempPlane1 = this.tempPlane1;
var tempPlane2 = this.tempPlane2;
subdivideByImpact( object, pointOfImpact, normal, maxRadialIterations, maxRandomIterations ) {
const debris = [];
const tempPlane1 = this.tempPlane1;
const tempPlane2 = this.tempPlane2;
this.tempVector3.addVectors( pointOfImpact, normal );
tempPlane1.setFromCoplanarPoints( pointOfImpact, object.position, this.tempVector3 );
var maxTotalIterations = maxRandomIterations + maxRadialIterations;
var scope = this;
const maxTotalIterations = maxRandomIterations + maxRadialIterations;
const scope = this;
function subdivideRadial( subObject, startAngle, endAngle, numIterations ) {
......@@ -106,7 +109,7 @@
}
var angle = Math.PI;
let angle = Math.PI;
if ( numIterations === 0 ) {
......@@ -136,8 +139,8 @@
scope.cutByPlane( subObject, tempPlane2, scope.tempResultObjects );
var obj1 = scope.tempResultObjects.object1;
var obj2 = scope.tempResultObjects.object2;
const obj1 = scope.tempResultObjects.object1;
const obj2 = scope.tempResultObjects.object2;
if ( obj1 ) {
......@@ -156,19 +159,20 @@
subdivideRadial( object, 0, 2 * Math.PI, 0 );
return debris;
},
cutByPlane: function ( object, plane, output ) {
}
cutByPlane( object, plane, output ) {
// Returns breakable objects in output.object1 and output.object2 members, the resulting 2 pieces of the cut.
// object2 can be null if the plane doesn't cut the object.
// object1 can be null only in case of internal error
// Returned value is number of pieces, 0 for error.
var geometry = object.geometry;
var coords = geometry.attributes.position.array;
var normals = geometry.attributes.normal.array;
var numPoints = coords.length / 3;
var numFaces = numPoints / 3;
var indices = geometry.getIndex();
const geometry = object.geometry;
const coords = geometry.attributes.position.array;
const normals = geometry.attributes.normal.array;
const numPoints = coords.length / 3;
let numFaces = numPoints / 3;
let indices = geometry.getIndex();
if ( indices ) {
......@@ -180,40 +184,40 @@
function getVertexIndex( faceIdx, vert ) {
// vert = 0, 1 or 2.
var idx = faceIdx * 3 + vert;
const idx = faceIdx * 3 + vert;
return indices ? indices[ idx ] : idx;
}
var points1 = [];
var points2 = [];
var delta = this.smallDelta; // Reset segments mark
const points1 = [];
const points2 = [];
const delta = this.smallDelta; // Reset segments mark
var numPointPairs = numPoints * numPoints;
const numPointPairs = numPoints * numPoints;
for ( var i = 0; i < numPointPairs; i ++ ) this.segments[ i ] = false;
for ( let i = 0; i < numPointPairs; i ++ ) this.segments[ i ] = false;
var p0 = this.tempVector3_P0;
var p1 = this.tempVector3_P1;
var n0 = this.tempVector3_N0;
var n1 = this.tempVector3_N1; // Iterate through the faces to mark edges shared by coplanar faces
const p0 = this.tempVector3_P0;
const p1 = this.tempVector3_P1;
const n0 = this.tempVector3_N0;
const n1 = this.tempVector3_N1; // Iterate through the faces to mark edges shared by coplanar faces
for ( var i = 0; i < numFaces - 1; i ++ ) {
for ( let i = 0; i < numFaces - 1; i ++ ) {
var a1 = getVertexIndex( i, 0 );
var b1 = getVertexIndex( i, 1 );
var c1 = getVertexIndex( i, 2 ); // Assuming all 3 vertices have the same normal
const a1 = getVertexIndex( i, 0 );
const b1 = getVertexIndex( i, 1 );
const c1 = getVertexIndex( i, 2 ); // Assuming all 3 vertices have the same normal
n0.set( normals[ a1 ], normals[ a1 ] + 1, normals[ a1 ] + 2 );
for ( var j = i + 1; j < numFaces; j ++ ) {
for ( let j = i + 1; j < numFaces; j ++ ) {
var a2 = getVertexIndex( j, 0 );
var b2 = getVertexIndex( j, 1 );
var c2 = getVertexIndex( j, 2 ); // Assuming all 3 vertices have the same normal
const a2 = getVertexIndex( j, 0 );
const b2 = getVertexIndex( j, 1 );
const c2 = getVertexIndex( j, 2 ); // Assuming all 3 vertices have the same normal
n1.set( normals[ a2 ], normals[ a2 ] + 1, normals[ a2 ] + 2 );
var coplanar = 1 - n0.dot( n1 ) < delta;
const coplanar = 1 - n0.dot( n1 ) < delta;
if ( coplanar ) {
......@@ -245,21 +249,21 @@
} // Transform the plane to object local space
var localPlane = this.tempPlane_Cut;
const localPlane = this.tempPlane_Cut;
object.updateMatrix();
ConvexObjectBreaker.transformPlaneToLocalSpace( plane, object.matrix, localPlane ); // Iterate through the faces adding points to both pieces
for ( var i = 0; i < numFaces; i ++ ) {
for ( let i = 0; i < numFaces; i ++ ) {
var va = getVertexIndex( i, 0 );
var vb = getVertexIndex( i, 1 );
var vc = getVertexIndex( i, 2 );
const va = getVertexIndex( i, 0 );
const vb = getVertexIndex( i, 1 );
const vc = getVertexIndex( i, 2 );
for ( var segment = 0; segment < 3; segment ++ ) {
for ( let segment = 0; segment < 3; segment ++ ) {
var i0 = segment === 0 ? va : segment === 1 ? vb : vc;
var i1 = segment === 0 ? vb : segment === 1 ? vc : va;
var segmentState = this.segments[ i0 * numPoints + i1 ];
const i0 = segment === 0 ? va : segment === 1 ? vb : vc;
const i1 = segment === 0 ? vb : segment === 1 ? vc : va;
const segmentState = this.segments[ i0 * numPoints + i1 ];
if ( segmentState ) continue; // The segment already has been processed in another face
// Mark segment as processed (also inverted segment)
......@@ -268,8 +272,8 @@
p0.set( coords[ 3 * i0 ], coords[ 3 * i0 + 1 ], coords[ 3 * i0 + 2 ] );
p1.set( coords[ 3 * i1 ], coords[ 3 * i1 + 1 ], coords[ 3 * i1 + 2 ] ); // mark: 1 for negative side, 2 for positive side, 3 for coplanar point
var mark0 = 0;
var d = localPlane.distanceToPoint( p0 );
let mark0 = 0;
let d = localPlane.distanceToPoint( p0 );
if ( d > delta ) {
......@@ -290,8 +294,8 @@
} // mark: 1 for negative side, 2 for positive side, 3 for coplanar point
var mark1 = 0;
var d = localPlane.distanceToPoint( p1 );
let mark1 = 0;
d = localPlane.distanceToPoint( p1 );
if ( d > delta ) {
......@@ -316,7 +320,7 @@
// Intersection of segment with the plane
this.tempLine1.start.copy( p0 );
this.tempLine1.end.copy( p1 );
var intersection = new THREE.Vector3();
let intersection = new THREE.Vector3();
intersection = localPlane.intersectLine( this.tempLine1, intersection );
if ( intersection === null ) {
......@@ -339,21 +343,21 @@
} // Calculate debris mass (very fast and imprecise):
var newMass = object.userData.mass * 0.5; // Calculate debris Center of Mass (again fast and imprecise)
const newMass = object.userData.mass * 0.5; // Calculate debris Center of Mass (again fast and imprecise)
this.tempCM1.set( 0, 0, 0 );
var radius1 = 0;
var numPoints1 = points1.length;
let radius1 = 0;
const numPoints1 = points1.length;
if ( numPoints1 > 0 ) {
for ( var i = 0; i < numPoints1; i ++ ) this.tempCM1.add( points1[ i ] );
for ( let i = 0; i < numPoints1; i ++ ) this.tempCM1.add( points1[ i ] );
this.tempCM1.divideScalar( numPoints1 );
for ( var i = 0; i < numPoints1; i ++ ) {
for ( let i = 0; i < numPoints1; i ++ ) {
var p = points1[ i ];
const p = points1[ i ];
p.sub( this.tempCM1 );
radius1 = Math.max( radius1, p.x, p.y, p.z );
......@@ -364,18 +368,18 @@
}
this.tempCM2.set( 0, 0, 0 );
var radius2 = 0;
var numPoints2 = points2.length;
let radius2 = 0;
const numPoints2 = points2.length;
if ( numPoints2 > 0 ) {
for ( var i = 0; i < numPoints2; i ++ ) this.tempCM2.add( points2[ i ] );
for ( let i = 0; i < numPoints2; i ++ ) this.tempCM2.add( points2[ i ] );
this.tempCM2.divideScalar( numPoints2 );
for ( var i = 0; i < numPoints2; i ++ ) {
for ( let i = 0; i < numPoints2; i ++ ) {
var p = points2[ i ];
const p = points2[ i ];
p.sub( this.tempCM2 );
radius2 = Math.max( radius2, p.x, p.y, p.z );
......@@ -385,9 +389,9 @@
}
var object1 = null;
var object2 = null;
var numObjects = 0;
let object1 = null;
let object2 = null;
let numObjects = 0;
if ( numPoints1 > 4 ) {
......@@ -414,71 +418,67 @@
return numObjects;
}
};
ConvexObjectBreaker.transformFreeVector = function ( v, m ) {
// input:
// vector interpreted as a free vector
// THREE.Matrix4 orthogonal matrix (matrix without scale)
var x = v.x,
y = v.y,
z = v.z;
var e = m.elements;
v.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z;
v.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z;
v.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z;
return v;
};
ConvexObjectBreaker.transformFreeVectorInverse = function ( v, m ) {
// input:
// vector interpreted as a free vector
// THREE.Matrix4 orthogonal matrix (matrix without scale)
var x = v.x,
y = v.y,
z = v.z;
var e = m.elements;
v.x = e[ 0 ] * x + e[ 1 ] * y + e[ 2 ] * z;
v.y = e[ 4 ] * x + e[ 5 ] * y + e[ 6 ] * z;
v.z = e[ 8 ] * x + e[ 9 ] * y + e[ 10 ] * z;
return v;
};
ConvexObjectBreaker.transformTiedVectorInverse = function ( v, m ) {
// input:
// vector interpreted as a tied (ordinary) vector
// THREE.Matrix4 orthogonal matrix (matrix without scale)
var x = v.x,
y = v.y,
z = v.z;
var e = m.elements;
v.x = e[ 0 ] * x + e[ 1 ] * y + e[ 2 ] * z - e[ 12 ];
v.y = e[ 4 ] * x + e[ 5 ] * y + e[ 6 ] * z - e[ 13 ];
v.z = e[ 8 ] * x + e[ 9 ] * y + e[ 10 ] * z - e[ 14 ];
return v;
};
ConvexObjectBreaker.transformPlaneToLocalSpace = function () {
var v1 = new THREE.Vector3();
return function transformPlaneToLocalSpace( plane, m, resultPlane ) {
static transformFreeVector( v, m ) {
// input:
// vector interpreted as a free vector
// THREE.Matrix4 orthogonal matrix (matrix without scale)
const x = v.x,
y = v.y,
z = v.z;
const e = m.elements;
v.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z;
v.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z;
v.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z;
return v;
}
static transformFreeVectorInverse( v, m ) {
// input:
// vector interpreted as a free vector
// THREE.Matrix4 orthogonal matrix (matrix without scale)
const x = v.x,
y = v.y,
z = v.z;
const e = m.elements;
v.x = e[ 0 ] * x + e[ 1 ] * y + e[ 2 ] * z;
v.y = e[ 4 ] * x + e[ 5 ] * y + e[ 6 ] * z;
v.z = e[ 8 ] * x + e[ 9 ] * y + e[ 10 ] * z;
return v;
}
static transformTiedVectorInverse( v, m ) {
// input:
// vector interpreted as a tied (ordinary) vector
// THREE.Matrix4 orthogonal matrix (matrix without scale)
const x = v.x,
y = v.y,
z = v.z;
const e = m.elements;
v.x = e[ 0 ] * x + e[ 1 ] * y + e[ 2 ] * z - e[ 12 ];
v.y = e[ 4 ] * x + e[ 5 ] * y + e[ 6 ] * z - e[ 13 ];
v.z = e[ 8 ] * x + e[ 9 ] * y + e[ 10 ] * z - e[ 14 ];
return v;
}
static transformPlaneToLocalSpace( plane, m, resultPlane ) {
resultPlane.normal.copy( plane.normal );
resultPlane.constant = plane.constant;
var referencePoint = ConvexObjectBreaker.transformTiedVectorInverse( plane.coplanarPoint( v1 ), m );
const referencePoint = ConvexObjectBreaker.transformTiedVectorInverse( plane.coplanarPoint( _v1 ), m );
ConvexObjectBreaker.transformFreeVectorInverse( resultPlane.normal, m ); // recalculate constant (like in setFromNormalAndCoplanarPoint)
resultPlane.constant = - referencePoint.dot( resultPlane.normal );
};
}
}();
}
THREE.ConvexObjectBreaker = ConvexObjectBreaker;
......
......@@ -28,16 +28,16 @@
* // Initialization...
*
* // Create computation renderer
* var gpuCompute = new GPUComputationRenderer( 1024, 1024, renderer );
* const gpuCompute = new GPUComputationRenderer( 1024, 1024, renderer );
*
* // Create initial state float textures
* var pos0 = gpuCompute.createTexture();
* var vel0 = gpuCompute.createTexture();
* const pos0 = gpuCompute.createTexture();
* const vel0 = gpuCompute.createTexture();
* // and fill in here the texture data...
*
* // Add texture variables
* var velVar = gpuCompute.addVariable( "textureVelocity", fragmentShaderVel, pos0 );
* var posVar = gpuCompute.addVariable( "texturePosition", fragmentShaderPos, vel0 );
* const velVar = gpuCompute.addVariable( "textureVelocity", fragmentShaderVel, pos0 );
* const posVar = gpuCompute.addVariable( "texturePosition", fragmentShaderPos, vel0 );
*
* // Add variable dependencies
* gpuCompute.setVariableDependencies( velVar, [ velVar, posVar ] );
......@@ -47,7 +47,7 @@
* velVar.material.uniforms.time = { value: 0.0 };
*
* // Check for completeness
* var error = gpuCompute.init();
* const error = gpuCompute.init();
* if ( error !== null ) {
* console.error( error );
* }
......@@ -69,19 +69,19 @@
* Also, you can use utility functions to create THREE.ShaderMaterial and perform computations (rendering between textures)
* Note that the shaders can have multiple input textures.
*
* var myFilter1 = gpuCompute.createShaderMaterial( myFilterFragmentShader1, { theTexture: { value: null } } );
* var myFilter2 = gpuCompute.createShaderMaterial( myFilterFragmentShader2, { theTexture: { value: null } } );
* const myFilter1 = gpuCompute.createShaderMaterial( myFilterFragmentShader1, { theTexture: { value: null } } );
* const myFilter2 = gpuCompute.createShaderMaterial( myFilterFragmentShader2, { theTexture: { value: null } } );
*
* var inputTexture = gpuCompute.createTexture();
* const inputTexture = gpuCompute.createTexture();
*
* // Fill in here inputTexture...
*
* myFilter1.uniforms.theTexture.value = inputTexture;
*
* var myRenderTarget = gpuCompute.createRenderTarget();
* const myRenderTarget = gpuCompute.createRenderTarget();
* myFilter2.uniforms.theTexture.value = myRenderTarget.texture;
*
* var outputRenderTarget = gpuCompute.createRenderTarget();
* const outputRenderTarget = gpuCompute.createRenderTarget();
*
* // Now use the output texture where you want:
* myMaterial.uniforms.map.value = outputRenderTarget.texture;
......@@ -97,257 +97,261 @@
* @param {WebGLRenderer} renderer The renderer
*/
var GPUComputationRenderer = function ( sizeX, sizeY, renderer ) {
this.variables = [];
this.currentTextureIndex = 0;
var dataType = THREE.FloatType;
var scene = new THREE.Scene();
var camera = new THREE.Camera();
camera.position.z = 1;
var passThruUniforms = {
passThruTexture: {
value: null
}
};
var passThruShader = createShaderMaterial( getPassThroughFragmentShader(), passThruUniforms );
var mesh = new THREE.Mesh( new THREE.PlaneGeometry( 2, 2 ), passThruShader );
scene.add( mesh );
this.setDataType = function ( type ) {
dataType = type;
return this;
};
this.addVariable = function ( variableName, computeFragmentShader, initialValueTexture ) {
var material = this.createShaderMaterial( computeFragmentShader );
var variable = {
name: variableName,
initialValueTexture: initialValueTexture,
material: material,
dependencies: null,
renderTargets: [],
wrapS: null,
wrapT: null,
minFilter: THREE.NearestFilter,
magFilter: THREE.NearestFilter
class GPUComputationRenderer {
constructor( sizeX, sizeY, renderer ) {
this.variables = [];
this.currentTextureIndex = 0;
let dataType = THREE.FloatType;
const scene = new THREE.Scene();
const camera = new THREE.Camera();
camera.position.z = 1;
const passThruUniforms = {
passThruTexture: {
value: null
}
};
this.variables.push( variable );
return variable;
const passThruShader = createShaderMaterial( getPassThroughFragmentShader(), passThruUniforms );
const mesh = new THREE.Mesh( new THREE.PlaneGeometry( 2, 2 ), passThruShader );
scene.add( mesh );
};
this.setDataType = function ( type ) {
this.setVariableDependencies = function ( variable, dependencies ) {
dataType = type;
return this;
variable.dependencies = dependencies;
};
};
this.addVariable = function ( variableName, computeFragmentShader, initialValueTexture ) {
const material = this.createShaderMaterial( computeFragmentShader );
const variable = {
name: variableName,
initialValueTexture: initialValueTexture,
material: material,
dependencies: null,
renderTargets: [],
wrapS: null,
wrapT: null,
minFilter: THREE.NearestFilter,
magFilter: THREE.NearestFilter
};
this.variables.push( variable );
return variable;
this.init = function () {
};
if ( renderer.capabilities.isWebGL2 === false && renderer.extensions.has( 'OES_texture_float' ) === false ) {
this.setVariableDependencies = function ( variable, dependencies ) {
return 'No OES_texture_float support for float textures.';
variable.dependencies = dependencies;
}
};
if ( renderer.capabilities.maxVertexTextures === 0 ) {
this.init = function () {
return 'No support for vertex shader textures.';
if ( renderer.capabilities.isWebGL2 === false && renderer.extensions.has( 'OES_texture_float' ) === false ) {
}
return 'No OES_texture_float support for float textures.';
}
if ( renderer.capabilities.maxVertexTextures === 0 ) {
return 'No support for vertex shader textures.';
}
for ( let i = 0; i < this.variables.length; i ++ ) {
for ( var i = 0; i < this.variables.length; i ++ ) {
const variable = this.variables[ i ]; // Creates rendertargets and initialize them with input texture
var variable = this.variables[ i ]; // Creates rendertargets and initialize them with input texture
variable.renderTargets[ 0 ] = this.createRenderTarget( sizeX, sizeY, variable.wrapS, variable.wrapT, variable.minFilter, variable.magFilter );
variable.renderTargets[ 1 ] = this.createRenderTarget( sizeX, sizeY, variable.wrapS, variable.wrapT, variable.minFilter, variable.magFilter );
this.renderTexture( variable.initialValueTexture, variable.renderTargets[ 0 ] );
this.renderTexture( variable.initialValueTexture, variable.renderTargets[ 1 ] ); // Adds dependencies uniforms to the THREE.ShaderMaterial
variable.renderTargets[ 0 ] = this.createRenderTarget( sizeX, sizeY, variable.wrapS, variable.wrapT, variable.minFilter, variable.magFilter );
variable.renderTargets[ 1 ] = this.createRenderTarget( sizeX, sizeY, variable.wrapS, variable.wrapT, variable.minFilter, variable.magFilter );
this.renderTexture( variable.initialValueTexture, variable.renderTargets[ 0 ] );
this.renderTexture( variable.initialValueTexture, variable.renderTargets[ 1 ] ); // Adds dependencies uniforms to the THREE.ShaderMaterial
const material = variable.material;
const uniforms = material.uniforms;
var material = variable.material;
var uniforms = material.uniforms;
if ( variable.dependencies !== null ) {
if ( variable.dependencies !== null ) {
for ( let d = 0; d < variable.dependencies.length; d ++ ) {
for ( var d = 0; d < variable.dependencies.length; d ++ ) {
const depVar = variable.dependencies[ d ];
var depVar = variable.dependencies[ d ];
if ( depVar.name !== variable.name ) {
if ( depVar.name !== variable.name ) {
// Checks if variable exists
let found = false;
// Checks if variable exists
var found = false;
for ( let j = 0; j < this.variables.length; j ++ ) {
for ( var j = 0; j < this.variables.length; j ++ ) {
if ( depVar.name === this.variables[ j ].name ) {
if ( depVar.name === this.variables[ j ].name ) {
found = true;
break;
found = true;
break;
}
}
}
if ( ! found ) {
if ( ! found ) {
return 'Variable dependency not found. Variable=' + variable.name + ', dependency=' + depVar.name;
return 'Variable dependency not found. Variable=' + variable.name + ', dependency=' + depVar.name;
}
}
}
uniforms[ depVar.name ] = {
value: null
};
material.fragmentShader = '\nuniform sampler2D ' + depVar.name + ';\n' + material.fragmentShader;
uniforms[ depVar.name ] = {
value: null
};
material.fragmentShader = '\nuniform sampler2D ' + depVar.name + ';\n' + material.fragmentShader;
}
}
}
}
this.currentTextureIndex = 0;
return null;
this.currentTextureIndex = 0;
return null;
};
};
this.compute = function () {
this.compute = function () {
var currentTextureIndex = this.currentTextureIndex;
var nextTextureIndex = this.currentTextureIndex === 0 ? 1 : 0;
const currentTextureIndex = this.currentTextureIndex;
const nextTextureIndex = this.currentTextureIndex === 0 ? 1 : 0;
for ( var i = 0, il = this.variables.length; i < il; i ++ ) {
for ( let i = 0, il = this.variables.length; i < il; i ++ ) {
var variable = this.variables[ i ]; // Sets texture dependencies uniforms
const variable = this.variables[ i ]; // Sets texture dependencies uniforms
if ( variable.dependencies !== null ) {
if ( variable.dependencies !== null ) {
var uniforms = variable.material.uniforms;
const uniforms = variable.material.uniforms;
for ( var d = 0, dl = variable.dependencies.length; d < dl; d ++ ) {
for ( let d = 0, dl = variable.dependencies.length; d < dl; d ++ ) {
var depVar = variable.dependencies[ d ];
uniforms[ depVar.name ].value = depVar.renderTargets[ currentTextureIndex ].texture;
const depVar = variable.dependencies[ d ];
uniforms[ depVar.name ].value = depVar.renderTargets[ currentTextureIndex ].texture;
}
}
} // Performs the computation for this variable
} // Performs the computation for this variable
this.doRenderTarget( variable.material, variable.renderTargets[ nextTextureIndex ] );
this.doRenderTarget( variable.material, variable.renderTargets[ nextTextureIndex ] );
}
}
this.currentTextureIndex = nextTextureIndex;
this.currentTextureIndex = nextTextureIndex;
};
};
this.getCurrentRenderTarget = function ( variable ) {
this.getCurrentRenderTarget = function ( variable ) {
return variable.renderTargets[ this.currentTextureIndex ];
return variable.renderTargets[ this.currentTextureIndex ];
};
};
this.getAlternateRenderTarget = function ( variable ) {
this.getAlternateRenderTarget = function ( variable ) {
return variable.renderTargets[ this.currentTextureIndex === 0 ? 1 : 0 ];
return variable.renderTargets[ this.currentTextureIndex === 0 ? 1 : 0 ];
};
};
function addResolutionDefine( materialShader ) {
function addResolutionDefine( materialShader ) {
materialShader.defines.resolution = 'vec2( ' + sizeX.toFixed( 1 ) + ', ' + sizeY.toFixed( 1 ) + ' )';
materialShader.defines.resolution = 'vec2( ' + sizeX.toFixed( 1 ) + ', ' + sizeY.toFixed( 1 ) + ' )';
}
this.addResolutionDefine = addResolutionDefine; // The following functions can be used to compute things manually
}
function createShaderMaterial( computeFragmentShader, uniforms ) {
this.addResolutionDefine = addResolutionDefine; // The following functions can be used to compute things manually
uniforms = uniforms || {};
var material = new THREE.ShaderMaterial( {
uniforms: uniforms,
vertexShader: getPassThroughVertexShader(),
fragmentShader: computeFragmentShader
} );
addResolutionDefine( material );
return material;
function createShaderMaterial( computeFragmentShader, uniforms ) {
}
uniforms = uniforms || {};
const material = new THREE.ShaderMaterial( {
uniforms: uniforms,
vertexShader: getPassThroughVertexShader(),
fragmentShader: computeFragmentShader
} );
addResolutionDefine( material );
return material;
this.createShaderMaterial = createShaderMaterial;
}
this.createRenderTarget = function ( sizeXTexture, sizeYTexture, wrapS, wrapT, minFilter, magFilter ) {
this.createShaderMaterial = createShaderMaterial;
this.createRenderTarget = function ( sizeXTexture, sizeYTexture, wrapS, wrapT, minFilter, magFilter ) {
sizeXTexture = sizeXTexture || sizeX;
sizeYTexture = sizeYTexture || sizeY;
wrapS = wrapS || THREE.ClampToEdgeWrapping;
wrapT = wrapT || THREE.ClampToEdgeWrapping;
minFilter = minFilter || THREE.NearestFilter;
magFilter = magFilter || THREE.NearestFilter;
const renderTarget = new THREE.WebGLRenderTarget( sizeXTexture, sizeYTexture, {
wrapS: wrapS,
wrapT: wrapT,
minFilter: minFilter,
magFilter: magFilter,
format: THREE.RGBAFormat,
type: dataType,
depthBuffer: false
} );
return renderTarget;
sizeXTexture = sizeXTexture || sizeX;
sizeYTexture = sizeYTexture || sizeY;
wrapS = wrapS || THREE.ClampToEdgeWrapping;
wrapT = wrapT || THREE.ClampToEdgeWrapping;
minFilter = minFilter || THREE.NearestFilter;
magFilter = magFilter || THREE.NearestFilter;
var renderTarget = new THREE.WebGLRenderTarget( sizeXTexture, sizeYTexture, {
wrapS: wrapS,
wrapT: wrapT,
minFilter: minFilter,
magFilter: magFilter,
format: THREE.RGBAFormat,
type: dataType,
depthBuffer: false
} );
return renderTarget;
};
};
this.createTexture = function () {
this.createTexture = function () {
const data = new Float32Array( sizeX * sizeY * 4 );
return new THREE.DataTexture( data, sizeX, sizeY, THREE.RGBAFormat, THREE.FloatType );
var data = new Float32Array( sizeX * sizeY * 4 );
return new THREE.DataTexture( data, sizeX, sizeY, THREE.RGBAFormat, THREE.FloatType );
};
};
this.renderTexture = function ( input, output ) {
this.renderTexture = function ( input, output ) {
// Takes a texture, and render out in rendertarget
// input = Texture
// output = RenderTarget
passThruUniforms.passThruTexture.value = input;
this.doRenderTarget( passThruShader, output );
passThruUniforms.passThruTexture.value = null;
// Takes a texture, and render out in rendertarget
// input = Texture
// output = RenderTarget
passThruUniforms.passThruTexture.value = input;
this.doRenderTarget( passThruShader, output );
passThruUniforms.passThruTexture.value = null;
};
};
this.doRenderTarget = function ( material, output ) {
this.doRenderTarget = function ( material, output ) {
const currentRenderTarget = renderer.getRenderTarget();
mesh.material = material;
renderer.setRenderTarget( output );
renderer.render( scene, camera );
mesh.material = passThruShader;
renderer.setRenderTarget( currentRenderTarget );
var currentRenderTarget = renderer.getRenderTarget();
mesh.material = material;
renderer.setRenderTarget( output );
renderer.render( scene, camera );
mesh.material = passThruShader;
renderer.setRenderTarget( currentRenderTarget );
}; // Shaders
}; // Shaders
function getPassThroughVertexShader() {
function getPassThroughVertexShader() {
return 'void main() {\n' + '\n' + ' gl_Position = vec4( position, 1.0 );\n' + '\n' + '}\n';
return 'void main() {\n' + '\n' + ' gl_Position = vec4( position, 1.0 );\n' + '\n' + '}\n';
}
}
function getPassThroughFragmentShader() {
function getPassThroughFragmentShader() {
return 'uniform sampler2D passThruTexture;\n' + '\n' + 'void main() {\n' + '\n' + ' vec2 uv = gl_FragCoord.xy / resolution.xy;\n' + '\n' + ' gl_FragColor = texture2D( passThruTexture, uv );\n' + '\n' + '}\n';
return 'uniform sampler2D passThruTexture;\n' + '\n' + 'void main() {\n' + '\n' + ' vec2 uv = gl_FragCoord.xy / resolution.xy;\n' + '\n' + ' gl_FragColor = texture2D( passThruTexture, uv );\n' + '\n' + '}\n';
}
}
};
}
THREE.GPUComputationRenderer = GPUComputationRenderer;
......
( function () {
var Gyroscope = function () {
const _translationObject = new THREE.Vector3();
THREE.Object3D.call( this );
const _quaternionObject = new THREE.Quaternion();
};
const _scaleObject = new THREE.Vector3();
Gyroscope.prototype = Object.create( THREE.Object3D.prototype );
Gyroscope.prototype.constructor = Gyroscope;
const _translationWorld = new THREE.Vector3();
Gyroscope.prototype.updateMatrixWorld = function () {
const _quaternionWorld = new THREE.Quaternion();
var translationObject = new THREE.Vector3();
var quaternionObject = new THREE.Quaternion();
var scaleObject = new THREE.Vector3();
var translationWorld = new THREE.Vector3();
var quaternionWorld = new THREE.Quaternion();
var scaleWorld = new THREE.Vector3();
return function updateMatrixWorld( force ) {
const _scaleWorld = new THREE.Vector3();
class Gyroscope extends THREE.Object3D {
constructor() {
super();
}
updateMatrixWorld( force ) {
this.matrixAutoUpdate && this.updateMatrix(); // update matrixWorld
......@@ -26,9 +29,9 @@
if ( this.parent !== null ) {
this.matrixWorld.multiplyMatrices( this.parent.matrixWorld, this.matrix );
this.matrixWorld.decompose( translationWorld, quaternionWorld, scaleWorld );
this.matrix.decompose( translationObject, quaternionObject, scaleObject );
this.matrixWorld.compose( translationWorld, quaternionObject, scaleWorld );
this.matrixWorld.decompose( _translationWorld, _quaternionWorld, _scaleWorld );
this.matrix.decompose( _translationObject, _quaternionObject, _scaleObject );
this.matrixWorld.compose( _translationWorld, _quaternionObject, _scaleWorld );
} else {
......@@ -42,15 +45,15 @@
} // update children
for ( var i = 0, l = this.children.length; i < l; i ++ ) {
for ( let i = 0, l = this.children.length; i < l; i ++ ) {
this.children[ i ].updateMatrixWorld( force );
}
};
}
}();
}
THREE.Gyroscope = Gyroscope;
......
( function () {
var MD2Character = function () {
class MD2Character {
var scope = this;
this.scale = 1;
this.animationFPS = 6;
this.root = new THREE.Object3D();
this.meshBody = null;
this.meshWeapon = null;
this.skinsBody = [];
this.skinsWeapon = [];
this.weapons = [];
this.activeAnimation = null;
this.mixer = null;
constructor() {
this.onLoadComplete = function () {};
this.scale = 1;
this.animationFPS = 6;
this.root = new THREE.Object3D();
this.meshBody = null;
this.meshWeapon = null;
this.skinsBody = [];
this.skinsWeapon = [];
this.weapons = [];
this.activeAnimation = null;
this.mixer = null;
this.loadCounter = 0;
this.onLoadComplete = function () {};
this.loadParts = function ( config ) {
this.loadCounter = 0;
}
loadParts( config ) {
const scope = this;
function createPart( geometry, skinMap ) {
const materialWireframe = new THREE.MeshLambertMaterial( {
color: 0xffaa00,
wireframe: true,
morphTargets: true,
morphNormals: true
} );
const materialTexture = new THREE.MeshLambertMaterial( {
color: 0xffffff,
wireframe: false,
map: skinMap,
morphTargets: true,
morphNormals: true
} ); //
const mesh = new THREE.Mesh( geometry, materialTexture );
mesh.rotation.y = - Math.PI / 2;
mesh.castShadow = true;
mesh.receiveShadow = true; //
mesh.materialTexture = materialTexture;
mesh.materialWireframe = materialWireframe;
return mesh;
}
function loadTextures( baseUrl, textureUrls ) {
const textureLoader = new THREE.TextureLoader();
const textures = [];
for ( let i = 0; i < textureUrls.length; i ++ ) {
textures[ i ] = textureLoader.load( baseUrl + textureUrls[ i ], checkLoadingComplete );
textures[ i ].mapping = THREE.UVMapping;
textures[ i ].name = textureUrls[ i ];
textures[ i ].encoding = THREE.sRGBEncoding;
}
return textures;
}
function checkLoadingComplete() {
scope.loadCounter -= 1;
if ( scope.loadCounter === 0 ) scope.onLoadComplete();
}
this.loadCounter = config.weapons.length * 2 + config.skins.length + 1;
var weaponsTextures = [];
const weaponsTextures = [];
for ( var i = 0; i < config.weapons.length; i ++ ) weaponsTextures[ i ] = config.weapons[ i ][ 1 ]; // SKINS
for ( let i = 0; i < config.weapons.length; i ++ ) weaponsTextures[ i ] = config.weapons[ i ][ 1 ]; // SKINS
this.skinsBody = loadTextures( config.baseUrl + 'skins/', config.skins );
this.skinsWeapon = loadTextures( config.baseUrl + 'skins/', weaponsTextures ); // BODY
var loader = new THREE.MD2Loader();
const loader = new THREE.MD2Loader();
loader.load( config.baseUrl + config.body, function ( geo ) {
var boundingBox = new THREE.Box3();
const boundingBox = new THREE.Box3();
boundingBox.setFromBufferAttribute( geo.attributes.position );
scope.root.position.y = - scope.scale * boundingBox.min.y;
var mesh = createPart( geo, scope.skinsBody[ 0 ] );
const mesh = createPart( geo, scope.skinsBody[ 0 ] );
mesh.scale.set( scope.scale, scope.scale, scope.scale );
scope.root.add( mesh );
scope.meshBody = mesh;
......@@ -46,11 +103,11 @@
} ); // WEAPONS
var generateCallback = function ( index, name ) {
const generateCallback = function ( index, name ) {
return function ( geo ) {
var mesh = createPart( geo, scope.skinsWeapon[ index ] );
const mesh = createPart( geo, scope.skinsWeapon[ index ] );
mesh.scale.set( scope.scale, scope.scale, scope.scale );
mesh.visible = false;
mesh.name = name;
......@@ -63,15 +120,15 @@
};
for ( var i = 0; i < config.weapons.length; i ++ ) {
for ( let i = 0; i < config.weapons.length; i ++ ) {
loader.load( config.baseUrl + config.weapons[ i ][ 0 ], generateCallback( i, config.weapons[ i ][ 0 ] ) );
}
};
}
this.setPlaybackRate = function ( rate ) {
setPlaybackRate( rate ) {
if ( rate !== 0 ) {
......@@ -83,9 +140,9 @@
}
};
}
this.setWireframe = function ( wireframeEnabled ) {
setWireframe( wireframeEnabled ) {
if ( wireframeEnabled ) {
......@@ -99,9 +156,9 @@
}
};
}
this.setSkin = function ( index ) {
setSkin( index ) {
if ( this.meshBody && this.meshBody.material.wireframe === false ) {
......@@ -109,25 +166,25 @@
}
};
}
this.setWeapon = function ( index ) {
setWeapon( index ) {
for ( var i = 0; i < this.weapons.length; i ++ ) this.weapons[ i ].visible = false;
for ( let i = 0; i < this.weapons.length; i ++ ) this.weapons[ i ].visible = false;
var activeWeapon = this.weapons[ index ];
const activeWeapon = this.weapons[ index ];
if ( activeWeapon ) {
activeWeapon.visible = true;
this.meshWeapon = activeWeapon;
scope.syncWeaponAnimation();
this.syncWeaponAnimation();
}
};
}
this.setAnimation = function ( clipName ) {
setAnimation( clipName ) {
if ( this.meshBody ) {
......@@ -138,7 +195,7 @@
}
var action = this.mixer.clipAction( clipName, this.meshBody );
const action = this.mixer.clipAction( clipName, this.meshBody );
if ( action ) {
......@@ -148,16 +205,16 @@
}
scope.activeClipName = clipName;
scope.syncWeaponAnimation();
this.activeClipName = clipName;
this.syncWeaponAnimation();
};
}
this.syncWeaponAnimation = function () {
syncWeaponAnimation() {
var clipName = scope.activeClipName;
const clipName = this.activeClipName;
if ( scope.meshWeapon ) {
if ( this.meshWeapon ) {
if ( this.meshWeapon.activeAction ) {
......@@ -166,7 +223,7 @@
}
var action = this.mixer.clipAction( clipName, this.meshWeapon );
const action = this.mixer.clipAction( clipName, this.meshWeapon );
if ( action ) {
......@@ -176,67 +233,15 @@
}
};
this.update = function ( delta ) {
if ( this.mixer ) this.mixer.update( delta );
};
function loadTextures( baseUrl, textureUrls ) {
var textureLoader = new THREE.TextureLoader();
var textures = [];
for ( var i = 0; i < textureUrls.length; i ++ ) {
textures[ i ] = textureLoader.load( baseUrl + textureUrls[ i ], checkLoadingComplete );
textures[ i ].mapping = THREE.UVMapping;
textures[ i ].name = textureUrls[ i ];
textures[ i ].encoding = THREE.sRGBEncoding;
}
return textures;
}
function createPart( geometry, skinMap ) {
var materialWireframe = new THREE.MeshLambertMaterial( {
color: 0xffaa00,
wireframe: true,
morphTargets: true,
morphNormals: true
} );
var materialTexture = new THREE.MeshLambertMaterial( {
color: 0xffffff,
wireframe: false,
map: skinMap,
morphTargets: true,
morphNormals: true
} ); //
var mesh = new THREE.Mesh( geometry, materialTexture );
mesh.rotation.y = - Math.PI / 2;
mesh.castShadow = true;
mesh.receiveShadow = true; //
mesh.materialTexture = materialTexture;
mesh.materialWireframe = materialWireframe;
return mesh;
}
update( delta ) {
function checkLoadingComplete() {
scope.loadCounter -= 1;
if ( scope.loadCounter === 0 ) scope.onLoadComplete();
if ( this.mixer ) this.mixer.update( delta );
}
};
}
THREE.MD2Character = MD2Character;
......
( function () {
var MD2CharacterComplex = function () {
class MD2CharacterComplex {
var scope = this;
this.scale = 1; // animation parameters
constructor() {
this.animationFPS = 6;
this.transitionFrames = 15; // movement model parameters
this.scale = 1; // animation parameters
this.maxSpeed = 275;
this.maxReverseSpeed = - 275;
this.frontAcceleration = 600;
this.backAcceleration = 600;
this.frontDecceleration = 600;
this.angularSpeed = 2.5; // rig
this.animationFPS = 6;
this.transitionFrames = 15; // movement model parameters
this.root = new THREE.Object3D();
this.meshBody = null;
this.meshWeapon = null;
this.controls = null; // skins
this.maxSpeed = 275;
this.maxReverseSpeed = - 275;
this.frontAcceleration = 600;
this.backAcceleration = 600;
this.frontDecceleration = 600;
this.angularSpeed = 2.5; // rig
this.skinsBody = [];
this.skinsWeapon = [];
this.weapons = [];
this.currentSkin = undefined; //
this.root = new THREE.Object3D();
this.meshBody = null;
this.meshWeapon = null;
this.controls = null; // skins
this.onLoadComplete = function () {}; // internals
this.skinsBody = [];
this.skinsWeapon = [];
this.weapons = [];
this.currentSkin = undefined; //
this.onLoadComplete = function () {}; // internals
this.meshes = [];
this.animations = {};
this.loadCounter = 0; // internal movement control variables
this.speed = 0;
this.bodyOrientation = 0;
this.walkSpeed = this.maxSpeed;
this.crouchSpeed = this.maxSpeed * 0.5; // internal animation parameters
this.meshes = [];
this.animations = {};
this.loadCounter = 0; // internal movement control variables
this.activeAnimation = null;
this.oldAnimation = null; // API
this.speed = 0;
this.bodyOrientation = 0;
this.walkSpeed = this.maxSpeed;
this.crouchSpeed = this.maxSpeed * 0.5; // internal animation parameters
this.enableShadows = function ( enable ) {
this.activeAnimation = null;
this.oldAnimation = null; // API
for ( var i = 0; i < this.meshes.length; i ++ ) {
}
enableShadows( enable ) {
for ( let i = 0; i < this.meshes.length; i ++ ) {
this.meshes[ i ].castShadow = enable;
this.meshes[ i ].receiveShadow = enable;
}
};
}
this.setVisible = function ( enable ) {
setVisible( enable ) {
for ( var i = 0; i < this.meshes.length; i ++ ) {
for ( let i = 0; i < this.meshes.length; i ++ ) {
this.meshes[ i ].visible = enable;
this.meshes[ i ].visible = enable;
}
};
}
this.shareParts = function ( original ) {
shareParts( original ) {
this.animations = original.animations;
this.walkSpeed = original.walkSpeed;
......@@ -70,16 +73,18 @@
this.skinsBody = original.skinsBody;
this.skinsWeapon = original.skinsWeapon; // BODY
var mesh = createPart( original.meshBody.geometry, this.skinsBody[ 0 ] );
const mesh = this._createPart( original.meshBody.geometry, this.skinsBody[ 0 ] );
mesh.scale.set( this.scale, this.scale, this.scale );
this.root.position.y = original.root.position.y;
this.root.add( mesh );
this.meshBody = mesh;
this.meshes.push( mesh ); // WEAPONS
for ( var i = 0; i < original.weapons.length; i ++ ) {
for ( let i = 0; i < original.weapons.length; i ++ ) {
const meshWeapon = this._createPart( original.weapons[ i ].geometry, this.skinsWeapon[ i ] );
var meshWeapon = createPart( original.weapons[ i ].geometry, this.skinsWeapon[ i ] );
meshWeapon.scale.set( this.scale, this.scale, this.scale );
meshWeapon.visible = false;
meshWeapon.name = original.weapons[ i ].name;
......@@ -90,29 +95,58 @@
}
};
}
loadParts( config ) {
const scope = this;
function loadTextures( baseUrl, textureUrls ) {
const textureLoader = new THREE.TextureLoader();
const textures = [];
for ( let i = 0; i < textureUrls.length; i ++ ) {
textures[ i ] = textureLoader.load( baseUrl + textureUrls[ i ], checkLoadingComplete );
textures[ i ].mapping = THREE.UVMapping;
textures[ i ].name = textureUrls[ i ];
textures[ i ].encoding = THREE.sRGBEncoding;
}
return textures;
}
function checkLoadingComplete() {
scope.loadCounter -= 1;
if ( scope.loadCounter === 0 ) scope.onLoadComplete();
this.loadParts = function ( config ) {
}
this.animations = config.animations;
this.walkSpeed = config.walkSpeed;
this.crouchSpeed = config.crouchSpeed;
this.loadCounter = config.weapons.length * 2 + config.skins.length + 1;
var weaponsTextures = [];
const weaponsTextures = [];
for ( var i = 0; i < config.weapons.length; i ++ ) weaponsTextures[ i ] = config.weapons[ i ][ 1 ]; // SKINS
for ( let i = 0; i < config.weapons.length; i ++ ) weaponsTextures[ i ] = config.weapons[ i ][ 1 ]; // SKINS
this.skinsBody = loadTextures( config.baseUrl + 'skins/', config.skins );
this.skinsWeapon = loadTextures( config.baseUrl + 'skins/', weaponsTextures ); // BODY
var loader = new THREE.MD2Loader();
const loader = new THREE.MD2Loader();
loader.load( config.baseUrl + config.body, function ( geo ) {
var boundingBox = new THREE.Box3();
const boundingBox = new THREE.Box3();
boundingBox.setFromBufferAttribute( geo.attributes.position );
scope.root.position.y = - scope.scale * boundingBox.min.y;
var mesh = createPart( geo, scope.skinsBody[ 0 ] );
const mesh = scope._createPart( geo, scope.skinsBody[ 0 ] );
mesh.scale.set( scope.scale, scope.scale, scope.scale );
scope.root.add( mesh );
scope.meshBody = mesh;
......@@ -121,11 +155,12 @@
} ); // WEAPONS
var generateCallback = function ( index, name ) {
const generateCallback = function ( index, name ) {
return function ( geo ) {
var mesh = createPart( geo, scope.skinsWeapon[ index ] );
const mesh = scope._createPart( geo, scope.skinsWeapon[ index ] );
mesh.scale.set( scope.scale, scope.scale, scope.scale );
mesh.visible = false;
mesh.name = name;
......@@ -139,22 +174,22 @@
};
for ( var i = 0; i < config.weapons.length; i ++ ) {
for ( let i = 0; i < config.weapons.length; i ++ ) {
loader.load( config.baseUrl + config.weapons[ i ][ 0 ], generateCallback( i, config.weapons[ i ][ 0 ] ) );
}
};
}
this.setPlaybackRate = function ( rate ) {
setPlaybackRate( rate ) {
if ( this.meshBody ) this.meshBody.duration = this.meshBody.baseDuration / rate;
if ( this.meshWeapon ) this.meshWeapon.duration = this.meshWeapon.baseDuration / rate;
};
}
this.setWireframe = function ( wireframeEnabled ) {
setWireframe( wireframeEnabled ) {
if ( wireframeEnabled ) {
......@@ -168,9 +203,9 @@
}
};
}
this.setSkin = function ( index ) {
setSkin( index ) {
if ( this.meshBody && this.meshBody.material.wireframe === false ) {
......@@ -179,13 +214,13 @@
}
};
}
this.setWeapon = function ( index ) {
setWeapon( index ) {
for ( var i = 0; i < this.weapons.length; i ++ ) this.weapons[ i ].visible = false;
for ( let i = 0; i < this.weapons.length; i ++ ) this.weapons[ i ].visible = false;
var activeWeapon = this.weapons[ index ];
const activeWeapon = this.weapons[ index ];
if ( activeWeapon ) {
......@@ -201,9 +236,9 @@
}
};
}
this.setAnimation = function ( animationName ) {
setAnimation( animationName ) {
if ( animationName === this.activeAnimation || ! animationName ) return;
......@@ -224,9 +259,9 @@
}
};
}
this.update = function ( delta ) {
update( delta ) {
if ( this.controls ) this.updateMovementModel( delta );
......@@ -237,11 +272,11 @@
}
};
}
this.updateAnimations = function ( delta ) {
updateAnimations( delta ) {
var mix = 1;
let mix = 1;
if ( this.blendCounter > 0 ) {
......@@ -266,13 +301,13 @@
}
};
}
this.updateBehaviors = function () {
updateBehaviors() {
var controls = this.controls;
var animations = this.animations;
var moveAnimation, idleAnimation; // crouch vs stand
const controls = this.controls;
const animations = this.animations;
let moveAnimation, idleAnimation; // crouch vs stand
if ( controls.crouch ) {
......@@ -368,11 +403,17 @@
}
};
}
updateMovementModel( delta ) {
this.updateMovementModel = function ( delta ) {
function exponentialEaseOut( k ) {
var controls = this.controls; // speed based on controls
return k === 1 ? 1 : - Math.pow( 2, - 10 * k ) + 1;
}
const controls = this.controls; // speed based on controls
if ( controls.crouch ) this.maxSpeed = this.crouchSpeed; else this.maxSpeed = this.walkSpeed;
this.maxReverseSpeed = - this.maxSpeed;
......@@ -380,7 +421,7 @@
if ( controls.moveBackward ) this.speed = THREE.MathUtils.clamp( this.speed - delta * this.backAcceleration, this.maxReverseSpeed, this.maxSpeed ); // orientation based on controls
// (don't just stand while turning)
var dir = 1;
const dir = 1;
if ( controls.moveLeft ) {
......@@ -401,12 +442,12 @@
if ( this.speed > 0 ) {
var k = exponentialEaseOut( this.speed / this.maxSpeed );
const k = exponentialEaseOut( this.speed / this.maxSpeed );
this.speed = THREE.MathUtils.clamp( this.speed - k * delta * this.frontDecceleration, 0, this.maxSpeed );
} else {
var k = exponentialEaseOut( this.speed / this.maxReverseSpeed );
const k = exponentialEaseOut( this.speed / this.maxReverseSpeed );
this.speed = THREE.MathUtils.clamp( this.speed + k * delta * this.backAcceleration, this.maxReverseSpeed, 0 );
}
......@@ -414,42 +455,24 @@
} // displacement
var forwardDelta = this.speed * delta;
const forwardDelta = this.speed * delta;
this.root.position.x += Math.sin( this.bodyOrientation ) * forwardDelta;
this.root.position.z += Math.cos( this.bodyOrientation ) * forwardDelta; // steering
this.root.rotation.y = this.bodyOrientation;
}; // internal helpers
} // internal
function loadTextures( baseUrl, textureUrls ) {
var textureLoader = new THREE.TextureLoader();
var textures = [];
_createPart( geometry, skinMap ) {
for ( var i = 0; i < textureUrls.length; i ++ ) {
textures[ i ] = textureLoader.load( baseUrl + textureUrls[ i ], checkLoadingComplete );
textures[ i ].mapping = THREE.UVMapping;
textures[ i ].name = textureUrls[ i ];
textures[ i ].encoding = THREE.sRGBEncoding;
}
return textures;
}
function createPart( geometry, skinMap ) {
var materialWireframe = new THREE.MeshLambertMaterial( {
const materialWireframe = new THREE.MeshLambertMaterial( {
color: 0xffaa00,
wireframe: true,
morphTargets: true,
morphNormals: true
} );
var materialTexture = new THREE.MeshLambertMaterial( {
const materialTexture = new THREE.MeshLambertMaterial( {
color: 0xffffff,
wireframe: false,
map: skinMap,
......@@ -457,31 +480,18 @@
morphNormals: true
} ); //
var mesh = new THREE.MorphBlendMesh( geometry, materialTexture );
const mesh = new THREE.MorphBlendMesh( geometry, materialTexture );
mesh.rotation.y = - Math.PI / 2; //
mesh.materialTexture = materialTexture;
mesh.materialWireframe = materialWireframe; //
mesh.autoCreateAnimations( scope.animationFPS );
mesh.autoCreateAnimations( this.animationFPS );
return mesh;
}
function checkLoadingComplete() {
scope.loadCounter -= 1;
if ( scope.loadCounter === 0 ) scope.onLoadComplete();
}
function exponentialEaseOut( k ) {
return k === 1 ? 1 : - Math.pow( 2, - 10 * k ) + 1;
}
};
}
THREE.MD2CharacterComplex = MD2CharacterComplex;
......
( function () {
var MorphAnimMesh = function ( geometry, material ) {
class MorphAnimMesh extends THREE.Mesh {
THREE.Mesh.call( this, geometry, material );
this.type = 'MorphAnimMesh';
this.mixer = new THREE.AnimationMixer( this );
this.activeAction = null;
constructor( geometry, material ) {
};
super( geometry, material );
this.type = 'MorphAnimMesh';
this.mixer = new THREE.AnimationMixer( this );
this.activeAction = null;
MorphAnimMesh.prototype = Object.create( THREE.Mesh.prototype );
MorphAnimMesh.prototype.constructor = MorphAnimMesh;
}
MorphAnimMesh.prototype.setDirectionForward = function () {
setDirectionForward() {
this.mixer.timeScale = 1.0;
this.mixer.timeScale = 1.0;
};
}
MorphAnimMesh.prototype.setDirectionBackward = function () {
setDirectionBackward() {
this.mixer.timeScale = - 1.0;
this.mixer.timeScale = - 1.0;
};
}
MorphAnimMesh.prototype.playAnimation = function ( label, fps ) {
playAnimation( label, fps ) {
if ( this.activeAction ) {
if ( this.activeAction ) {
this.activeAction.stop();
this.activeAction = null;
this.activeAction.stop();
this.activeAction = null;
}
}
const clip = THREE.AnimationClip.findByName( this, label );
var clip = THREE.AnimationClip.findByName( this, label );
if ( clip ) {
if ( clip ) {
const action = this.mixer.clipAction( clip );
action.timeScale = clip.tracks.length * fps / clip.duration;
this.activeAction = action.play();
var action = this.mixer.clipAction( clip );
action.timeScale = clip.tracks.length * fps / clip.duration;
this.activeAction = action.play();
} else {
} else {
throw new Error( 'THREE.MorphAnimMesh: animations[' + label + '] undefined in .playAnimation()' );
throw new Error( 'THREE.MorphAnimMesh: animations[' + label + '] undefined in .playAnimation()' );
}
}
};
updateAnimation( delta ) {
MorphAnimMesh.prototype.updateAnimation = function ( delta ) {
this.mixer.update( delta );
this.mixer.update( delta );
}
};
copy( source ) {
MorphAnimMesh.prototype.copy = function ( source ) {
super.copy( source );
this.mixer = new THREE.AnimationMixer( this );
return this;
THREE.Mesh.prototype.copy.call( this, source );
this.mixer = new THREE.AnimationMixer( this );
return this;
}
};
}
THREE.MorphAnimMesh = MorphAnimMesh;
......
( function () {
var MorphBlendMesh = function ( geometry, material ) {
class MorphBlendMesh extends THREE.Mesh {
THREE.Mesh.call( this, geometry, material );
this.animationsMap = {};
this.animationsList = []; // prepare default animation
// (all frames played together in 1 second)
constructor( geometry, material ) {
var numFrames = Object.keys( this.morphTargetDictionary ).length;
var name = '__default';
var startFrame = 0;
var endFrame = numFrames - 1;
var fps = numFrames / 1;
this.createAnimation( name, startFrame, endFrame, fps );
this.setAnimationWeight( name, 1 );
super( geometry, material );
this.animationsMap = {};
this.animationsList = []; // prepare default animation
// (all frames played together in 1 second)
};
const numFrames = Object.keys( this.morphTargetDictionary ).length;
const name = '__default';
const startFrame = 0;
const endFrame = numFrames - 1;
const fps = numFrames / 1;
this.createAnimation( name, startFrame, endFrame, fps );
this.setAnimationWeight( name, 1 );
MorphBlendMesh.prototype = Object.assign( Object.create( THREE.Mesh.prototype ), {
constructor: MorphBlendMesh,
createAnimation: function ( name, start, end, fps ) {
}
createAnimation( name, start, end, fps ) {
var animation = {
const animation = {
start: start,
end: end,
length: end - start + 1,
......@@ -39,26 +39,27 @@
this.animationsMap[ name ] = animation;
this.animationsList.push( animation );
},
autoCreateAnimations: function ( fps ) {
}
autoCreateAnimations( fps ) {
var pattern = /([a-z]+)_?(\d+)/i;
var firstAnimation,
frameRanges = {};
var i = 0;
const pattern = /([a-z]+)_?(\d+)/i;
let firstAnimation;
const frameRanges = {};
let i = 0;
for ( var key in this.morphTargetDictionary ) {
for ( const key in this.morphTargetDictionary ) {
var chunks = key.match( pattern );
const chunks = key.match( pattern );
if ( chunks && chunks.length > 1 ) {
var name = chunks[ 1 ];
const name = chunks[ 1 ];
if ( ! frameRanges[ name ] ) frameRanges[ name ] = {
start: Infinity,
end: - Infinity
};
var range = frameRanges[ name ];
const range = frameRanges[ name ];
if ( i < range.start ) range.start = i;
if ( i > range.end ) range.end = i;
if ( ! firstAnimation ) firstAnimation = name;
......@@ -69,19 +70,20 @@
}
for ( var name in frameRanges ) {
for ( const name in frameRanges ) {
var range = frameRanges[ name ];
const range = frameRanges[ name ];
this.createAnimation( name, range.start, range.end, fps );
}
this.firstAnimation = firstAnimation;
},
setAnimationDirectionForward: function ( name ) {
}
setAnimationDirectionForward( name ) {
var animation = this.animationsMap[ name ];
const animation = this.animationsMap[ name ];
if ( animation ) {
......@@ -90,10 +92,11 @@
}
},
setAnimationDirectionBackward: function ( name ) {
}
setAnimationDirectionBackward( name ) {
var animation = this.animationsMap[ name ];
const animation = this.animationsMap[ name ];
if ( animation ) {
......@@ -102,10 +105,11 @@
}
},
setAnimationFPS: function ( name, fps ) {
}
setAnimationFPS( name, fps ) {
var animation = this.animationsMap[ name ];
const animation = this.animationsMap[ name ];
if ( animation ) {
......@@ -114,10 +118,11 @@
}
},
setAnimationDuration: function ( name, duration ) {
}
var animation = this.animationsMap[ name ];
setAnimationDuration( name, duration ) {
const animation = this.animationsMap[ name ];
if ( animation ) {
......@@ -126,10 +131,11 @@
}
},
setAnimationWeight: function ( name, weight ) {
}
setAnimationWeight( name, weight ) {
var animation = this.animationsMap[ name ];
const animation = this.animationsMap[ name ];
if ( animation ) {
......@@ -137,10 +143,11 @@
}
},
setAnimationTime: function ( name, time ) {
}
setAnimationTime( name, time ) {
var animation = this.animationsMap[ name ];
const animation = this.animationsMap[ name ];
if ( animation ) {
......@@ -148,11 +155,12 @@
}
},
getAnimationTime: function ( name ) {
}
getAnimationTime( name ) {
var time = 0;
var animation = this.animationsMap[ name ];
let time = 0;
const animation = this.animationsMap[ name ];
if ( animation ) {
......@@ -162,11 +170,12 @@
return time;
},
getAnimationDuration: function ( name ) {
}
getAnimationDuration( name ) {
var duration = - 1;
var animation = this.animationsMap[ name ];
let duration = - 1;
const animation = this.animationsMap[ name ];
if ( animation ) {
......@@ -176,10 +185,11 @@
return duration;
},
playAnimation: function ( name ) {
}
var animation = this.animationsMap[ name ];
playAnimation( name ) {
const animation = this.animationsMap[ name ];
if ( animation ) {
......@@ -192,10 +202,11 @@
}
},
stopAnimation: function ( name ) {
}
stopAnimation( name ) {
var animation = this.animationsMap[ name ];
const animation = this.animationsMap[ name ];
if ( animation ) {
......@@ -203,14 +214,15 @@
}
},
update: function ( delta ) {
}
update( delta ) {
for ( var i = 0, il = this.animationsList.length; i < il; i ++ ) {
for ( let i = 0, il = this.animationsList.length; i < il; i ++ ) {
var animation = this.animationsList[ i ];
const animation = this.animationsList[ i ];
if ( ! animation.active ) continue;
var frameTime = animation.duration / animation.length;
const frameTime = animation.duration / animation.length;
animation.time += animation.direction * delta;
if ( animation.mirroredLoop ) {
......@@ -242,8 +254,8 @@
}
var keyframe = animation.start + THREE.MathUtils.clamp( Math.floor( animation.time / frameTime ), 0, animation.length - 1 );
var weight = animation.weight;
const keyframe = animation.start + THREE.MathUtils.clamp( Math.floor( animation.time / frameTime ), 0, animation.length - 1 );
const weight = animation.weight;
if ( keyframe !== animation.currentFrame ) {
......@@ -255,7 +267,7 @@
}
var mix = animation.time % frameTime / frameTime;
let mix = animation.time % frameTime / frameTime;
if ( animation.directionBackwards ) mix = 1 - mix;
if ( animation.currentFrame !== animation.lastFrame ) {
......@@ -272,7 +284,8 @@
}
}
} );
}
THREE.MorphBlendMesh = MorphBlendMesh;
......
此差异已折叠。
......@@ -35,40 +35,40 @@ import { ConvexGeometry } from '../geometries/ConvexGeometry.js';
*
*/
var ConvexObjectBreaker = function ( minSizeForBreak, smallDelta ) {
const _v1 = new Vector3();
class ConvexObjectBreaker {
constructor( minSizeForBreak = 1.4, smallDelta = 0.0001 ) {
this.minSizeForBreak = minSizeForBreak;
this.smallDelta = smallDelta;
this.tempLine1 = new Line3();
this.tempPlane1 = new Plane();
this.tempPlane2 = new Plane();
this.tempPlane_Cut = new Plane();
this.tempCM1 = new Vector3();
this.tempCM2 = new Vector3();
this.tempVector3 = new Vector3();
this.tempVector3_2 = new Vector3();
this.tempVector3_3 = new Vector3();
this.tempVector3_P0 = new Vector3();
this.tempVector3_P1 = new Vector3();
this.tempVector3_P2 = new Vector3();
this.tempVector3_N0 = new Vector3();
this.tempVector3_N1 = new Vector3();
this.tempVector3_AB = new Vector3();
this.tempVector3_CB = new Vector3();
this.tempResultObjects = { object1: null, object2: null };
this.segments = [];
const n = 30 * 30;
for ( let i = 0; i < n; i ++ ) this.segments[ i ] = false;
this.minSizeForBreak = minSizeForBreak || 1.4;
this.smallDelta = smallDelta || 0.0001;
this.tempLine1 = new Line3();
this.tempPlane1 = new Plane();
this.tempPlane2 = new Plane();
this.tempPlane_Cut = new Plane();
this.tempCM1 = new Vector3();
this.tempCM2 = new Vector3();
this.tempVector3 = new Vector3();
this.tempVector3_2 = new Vector3();
this.tempVector3_3 = new Vector3();
this.tempVector3_P0 = new Vector3();
this.tempVector3_P1 = new Vector3();
this.tempVector3_P2 = new Vector3();
this.tempVector3_N0 = new Vector3();
this.tempVector3_N1 = new Vector3();
this.tempVector3_AB = new Vector3();
this.tempVector3_CB = new Vector3();
this.tempResultObjects = { object1: null, object2: null };
this.segments = [];
var n = 30 * 30;
for ( var i = 0; i < n; i ++ ) this.segments[ i ] = false;
};
ConvexObjectBreaker.prototype = {
constructor: ConvexObjectBreaker,
}
prepareBreakableObject: function ( object, mass, velocity, angularVelocity, breakable ) {
prepareBreakableObject( object, mass, velocity, angularVelocity, breakable ) {
// object is a Object3d (normally a Mesh), must have a BufferGeometry, and it must be convex.
// Its material property is propagated to its children (sub-pieces)
......@@ -80,13 +80,13 @@ ConvexObjectBreaker.prototype = {
}
var userData = object.userData;
const userData = object.userData;
userData.mass = mass;
userData.velocity = velocity.clone();
userData.angularVelocity = angularVelocity.clone();
userData.breakable = breakable;
},
}
/*
* @param {int} maxRadialIterations Iterations for radial cuts.
......@@ -94,19 +94,19 @@ ConvexObjectBreaker.prototype = {
*
* Returns the array of pieces
*/
subdivideByImpact: function ( object, pointOfImpact, normal, maxRadialIterations, maxRandomIterations ) {
subdivideByImpact( object, pointOfImpact, normal, maxRadialIterations, maxRandomIterations ) {
var debris = [];
const debris = [];
var tempPlane1 = this.tempPlane1;
var tempPlane2 = this.tempPlane2;
const tempPlane1 = this.tempPlane1;
const tempPlane2 = this.tempPlane2;
this.tempVector3.addVectors( pointOfImpact, normal );
tempPlane1.setFromCoplanarPoints( pointOfImpact, object.position, this.tempVector3 );
var maxTotalIterations = maxRandomIterations + maxRadialIterations;
const maxTotalIterations = maxRandomIterations + maxRadialIterations;
var scope = this;
const scope = this;
function subdivideRadial( subObject, startAngle, endAngle, numIterations ) {
......@@ -118,7 +118,7 @@ ConvexObjectBreaker.prototype = {
}
var angle = Math.PI;
let angle = Math.PI;
if ( numIterations === 0 ) {
......@@ -151,8 +151,8 @@ ConvexObjectBreaker.prototype = {
// Perform the cut
scope.cutByPlane( subObject, tempPlane2, scope.tempResultObjects );
var obj1 = scope.tempResultObjects.object1;
var obj2 = scope.tempResultObjects.object2;
const obj1 = scope.tempResultObjects.object1;
const obj2 = scope.tempResultObjects.object2;
if ( obj1 ) {
......@@ -172,23 +172,23 @@ ConvexObjectBreaker.prototype = {
return debris;
},
}
cutByPlane: function ( object, plane, output ) {
cutByPlane( object, plane, output ) {
// Returns breakable objects in output.object1 and output.object2 members, the resulting 2 pieces of the cut.
// object2 can be null if the plane doesn't cut the object.
// object1 can be null only in case of internal error
// Returned value is number of pieces, 0 for error.
var geometry = object.geometry;
var coords = geometry.attributes.position.array;
var normals = geometry.attributes.normal.array;
const geometry = object.geometry;
const coords = geometry.attributes.position.array;
const normals = geometry.attributes.normal.array;
var numPoints = coords.length / 3;
var numFaces = numPoints / 3;
const numPoints = coords.length / 3;
let numFaces = numPoints / 3;
var indices = geometry.getIndex();
let indices = geometry.getIndex();
if ( indices ) {
......@@ -201,46 +201,46 @@ ConvexObjectBreaker.prototype = {
// vert = 0, 1 or 2.
var idx = faceIdx * 3 + vert;
const idx = faceIdx * 3 + vert;
return indices ? indices[ idx ] : idx;
}
var points1 = [];
var points2 = [];
const points1 = [];
const points2 = [];
var delta = this.smallDelta;
const delta = this.smallDelta;
// Reset segments mark
var numPointPairs = numPoints * numPoints;
for ( var i = 0; i < numPointPairs; i ++ ) this.segments[ i ] = false;
const numPointPairs = numPoints * numPoints;
for ( let i = 0; i < numPointPairs; i ++ ) this.segments[ i ] = false;
var p0 = this.tempVector3_P0;
var p1 = this.tempVector3_P1;
var n0 = this.tempVector3_N0;
var n1 = this.tempVector3_N1;
const p0 = this.tempVector3_P0;
const p1 = this.tempVector3_P1;
const n0 = this.tempVector3_N0;
const n1 = this.tempVector3_N1;
// Iterate through the faces to mark edges shared by coplanar faces
for ( var i = 0; i < numFaces - 1; i ++ ) {
for ( let i = 0; i < numFaces - 1; i ++ ) {
var a1 = getVertexIndex( i, 0 );
var b1 = getVertexIndex( i, 1 );
var c1 = getVertexIndex( i, 2 );
const a1 = getVertexIndex( i, 0 );
const b1 = getVertexIndex( i, 1 );
const c1 = getVertexIndex( i, 2 );
// Assuming all 3 vertices have the same normal
n0.set( normals[ a1 ], normals[ a1 ] + 1, normals[ a1 ] + 2 );
for ( var j = i + 1; j < numFaces; j ++ ) {
for ( let j = i + 1; j < numFaces; j ++ ) {
var a2 = getVertexIndex( j, 0 );
var b2 = getVertexIndex( j, 1 );
var c2 = getVertexIndex( j, 2 );
const a2 = getVertexIndex( j, 0 );
const b2 = getVertexIndex( j, 1 );
const c2 = getVertexIndex( j, 2 );
// Assuming all 3 vertices have the same normal
n1.set( normals[ a2 ], normals[ a2 ] + 1, normals[ a2 ] + 2 );
var coplanar = 1 - n0.dot( n1 ) < delta;
const coplanar = 1 - n0.dot( n1 ) < delta;
if ( coplanar ) {
......@@ -272,23 +272,23 @@ ConvexObjectBreaker.prototype = {
}
// Transform the plane to object local space
var localPlane = this.tempPlane_Cut;
const localPlane = this.tempPlane_Cut;
object.updateMatrix();
ConvexObjectBreaker.transformPlaneToLocalSpace( plane, object.matrix, localPlane );
// Iterate through the faces adding points to both pieces
for ( var i = 0; i < numFaces; i ++ ) {
for ( let i = 0; i < numFaces; i ++ ) {
var va = getVertexIndex( i, 0 );
var vb = getVertexIndex( i, 1 );
var vc = getVertexIndex( i, 2 );
const va = getVertexIndex( i, 0 );
const vb = getVertexIndex( i, 1 );
const vc = getVertexIndex( i, 2 );
for ( var segment = 0; segment < 3; segment ++ ) {
for ( let segment = 0; segment < 3; segment ++ ) {
var i0 = segment === 0 ? va : ( segment === 1 ? vb : vc );
var i1 = segment === 0 ? vb : ( segment === 1 ? vc : va );
const i0 = segment === 0 ? va : ( segment === 1 ? vb : vc );
const i1 = segment === 0 ? vb : ( segment === 1 ? vc : va );
var segmentState = this.segments[ i0 * numPoints + i1 ];
const segmentState = this.segments[ i0 * numPoints + i1 ];
if ( segmentState ) continue; // The segment already has been processed in another face
......@@ -300,9 +300,9 @@ ConvexObjectBreaker.prototype = {
p1.set( coords[ 3 * i1 ], coords[ 3 * i1 + 1 ], coords[ 3 * i1 + 2 ] );
// mark: 1 for negative side, 2 for positive side, 3 for coplanar point
var mark0 = 0;
let mark0 = 0;
var d = localPlane.distanceToPoint( p0 );
let d = localPlane.distanceToPoint( p0 );
if ( d > delta ) {
......@@ -323,9 +323,9 @@ ConvexObjectBreaker.prototype = {
}
// mark: 1 for negative side, 2 for positive side, 3 for coplanar point
var mark1 = 0;
let mark1 = 0;
var d = localPlane.distanceToPoint( p1 );
d = localPlane.distanceToPoint( p1 );
if ( d > delta ) {
......@@ -352,7 +352,7 @@ ConvexObjectBreaker.prototype = {
this.tempLine1.start.copy( p0 );
this.tempLine1.end.copy( p1 );
var intersection = new Vector3();
let intersection = new Vector3();
intersection = localPlane.intersectLine( this.tempLine1, intersection );
if ( intersection === null ) {
......@@ -375,21 +375,21 @@ ConvexObjectBreaker.prototype = {
}
// Calculate debris mass (very fast and imprecise):
var newMass = object.userData.mass * 0.5;
const newMass = object.userData.mass * 0.5;
// Calculate debris Center of Mass (again fast and imprecise)
this.tempCM1.set( 0, 0, 0 );
var radius1 = 0;
var numPoints1 = points1.length;
let radius1 = 0;
const numPoints1 = points1.length;
if ( numPoints1 > 0 ) {
for ( var i = 0; i < numPoints1; i ++ ) this.tempCM1.add( points1[ i ] );
for ( let i = 0; i < numPoints1; i ++ ) this.tempCM1.add( points1[ i ] );
this.tempCM1.divideScalar( numPoints1 );
for ( var i = 0; i < numPoints1; i ++ ) {
for ( let i = 0; i < numPoints1; i ++ ) {
var p = points1[ i ];
const p = points1[ i ];
p.sub( this.tempCM1 );
radius1 = Math.max( radius1, p.x, p.y, p.z );
......@@ -400,16 +400,16 @@ ConvexObjectBreaker.prototype = {
}
this.tempCM2.set( 0, 0, 0 );
var radius2 = 0;
var numPoints2 = points2.length;
let radius2 = 0;
const numPoints2 = points2.length;
if ( numPoints2 > 0 ) {
for ( var i = 0; i < numPoints2; i ++ ) this.tempCM2.add( points2[ i ] );
for ( let i = 0; i < numPoints2; i ++ ) this.tempCM2.add( points2[ i ] );
this.tempCM2.divideScalar( numPoints2 );
for ( var i = 0; i < numPoints2; i ++ ) {
for ( let i = 0; i < numPoints2; i ++ ) {
var p = points2[ i ];
const p = points2[ i ];
p.sub( this.tempCM2 );
radius2 = Math.max( radius2, p.x, p.y, p.z );
......@@ -419,10 +419,10 @@ ConvexObjectBreaker.prototype = {
}
var object1 = null;
var object2 = null;
let object1 = null;
let object2 = null;
var numObjects = 0;
let numObjects = 0;
if ( numPoints1 > 4 ) {
......@@ -455,78 +455,71 @@ ConvexObjectBreaker.prototype = {
}
};
static transformFreeVector( v, m ) {
ConvexObjectBreaker.transformFreeVector = function ( v, m ) {
// input:
// vector interpreted as a free vector
// THREE.Matrix4 orthogonal matrix (matrix without scale)
// input:
// vector interpreted as a free vector
// THREE.Matrix4 orthogonal matrix (matrix without scale)
const x = v.x, y = v.y, z = v.z;
const e = m.elements;
var x = v.x, y = v.y, z = v.z;
var e = m.elements;
v.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z;
v.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z;
v.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z;
v.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z;
v.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z;
v.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z;
return v;
return v;
};
ConvexObjectBreaker.transformFreeVectorInverse = function ( v, m ) {
// input:
// vector interpreted as a free vector
// THREE.Matrix4 orthogonal matrix (matrix without scale)
}
var x = v.x, y = v.y, z = v.z;
var e = m.elements;
static transformFreeVectorInverse( v, m ) {
v.x = e[ 0 ] * x + e[ 1 ] * y + e[ 2 ] * z;
v.y = e[ 4 ] * x + e[ 5 ] * y + e[ 6 ] * z;
v.z = e[ 8 ] * x + e[ 9 ] * y + e[ 10 ] * z;
// input:
// vector interpreted as a free vector
// THREE.Matrix4 orthogonal matrix (matrix without scale)
return v;
const x = v.x, y = v.y, z = v.z;
const e = m.elements;
};
v.x = e[ 0 ] * x + e[ 1 ] * y + e[ 2 ] * z;
v.y = e[ 4 ] * x + e[ 5 ] * y + e[ 6 ] * z;
v.z = e[ 8 ] * x + e[ 9 ] * y + e[ 10 ] * z;
ConvexObjectBreaker.transformTiedVectorInverse = function ( v, m ) {
return v;
// input:
// vector interpreted as a tied (ordinary) vector
// THREE.Matrix4 orthogonal matrix (matrix without scale)
}
var x = v.x, y = v.y, z = v.z;
var e = m.elements;
static transformTiedVectorInverse( v, m ) {
v.x = e[ 0 ] * x + e[ 1 ] * y + e[ 2 ] * z - e[ 12 ];
v.y = e[ 4 ] * x + e[ 5 ] * y + e[ 6 ] * z - e[ 13 ];
v.z = e[ 8 ] * x + e[ 9 ] * y + e[ 10 ] * z - e[ 14 ];
// input:
// vector interpreted as a tied (ordinary) vector
// THREE.Matrix4 orthogonal matrix (matrix without scale)
return v;
const x = v.x, y = v.y, z = v.z;
const e = m.elements;
};
v.x = e[ 0 ] * x + e[ 1 ] * y + e[ 2 ] * z - e[ 12 ];
v.y = e[ 4 ] * x + e[ 5 ] * y + e[ 6 ] * z - e[ 13 ];
v.z = e[ 8 ] * x + e[ 9 ] * y + e[ 10 ] * z - e[ 14 ];
ConvexObjectBreaker.transformPlaneToLocalSpace = function () {
return v;
var v1 = new Vector3();
}
return function transformPlaneToLocalSpace( plane, m, resultPlane ) {
static transformPlaneToLocalSpace( plane, m, resultPlane ) {
resultPlane.normal.copy( plane.normal );
resultPlane.constant = plane.constant;
var referencePoint = ConvexObjectBreaker.transformTiedVectorInverse( plane.coplanarPoint( v1 ), m );
const referencePoint = ConvexObjectBreaker.transformTiedVectorInverse( plane.coplanarPoint( _v1 ), m );
ConvexObjectBreaker.transformFreeVectorInverse( resultPlane.normal, m );
// recalculate constant (like in setFromNormalAndCoplanarPoint)
resultPlane.constant = - referencePoint.dot( resultPlane.normal );
}
};
}();
}
export { ConvexObjectBreaker };
......@@ -40,16 +40,16 @@ import {
* // Initialization...
*
* // Create computation renderer
* var gpuCompute = new GPUComputationRenderer( 1024, 1024, renderer );
* const gpuCompute = new GPUComputationRenderer( 1024, 1024, renderer );
*
* // Create initial state float textures
* var pos0 = gpuCompute.createTexture();
* var vel0 = gpuCompute.createTexture();
* const pos0 = gpuCompute.createTexture();
* const vel0 = gpuCompute.createTexture();
* // and fill in here the texture data...
*
* // Add texture variables
* var velVar = gpuCompute.addVariable( "textureVelocity", fragmentShaderVel, pos0 );
* var posVar = gpuCompute.addVariable( "texturePosition", fragmentShaderPos, vel0 );
* const velVar = gpuCompute.addVariable( "textureVelocity", fragmentShaderVel, pos0 );
* const posVar = gpuCompute.addVariable( "texturePosition", fragmentShaderPos, vel0 );
*
* // Add variable dependencies
* gpuCompute.setVariableDependencies( velVar, [ velVar, posVar ] );
......@@ -59,7 +59,7 @@ import {
* velVar.material.uniforms.time = { value: 0.0 };
*
* // Check for completeness
* var error = gpuCompute.init();
* const error = gpuCompute.init();
* if ( error !== null ) {
* console.error( error );
* }
......@@ -81,19 +81,19 @@ import {
* Also, you can use utility functions to create ShaderMaterial and perform computations (rendering between textures)
* Note that the shaders can have multiple input textures.
*
* var myFilter1 = gpuCompute.createShaderMaterial( myFilterFragmentShader1, { theTexture: { value: null } } );
* var myFilter2 = gpuCompute.createShaderMaterial( myFilterFragmentShader2, { theTexture: { value: null } } );
* const myFilter1 = gpuCompute.createShaderMaterial( myFilterFragmentShader1, { theTexture: { value: null } } );
* const myFilter2 = gpuCompute.createShaderMaterial( myFilterFragmentShader2, { theTexture: { value: null } } );
*
* var inputTexture = gpuCompute.createTexture();
* const inputTexture = gpuCompute.createTexture();
*
* // Fill in here inputTexture...
*
* myFilter1.uniforms.theTexture.value = inputTexture;
*
* var myRenderTarget = gpuCompute.createRenderTarget();
* const myRenderTarget = gpuCompute.createRenderTarget();
* myFilter2.uniforms.theTexture.value = myRenderTarget.texture;
*
* var outputRenderTarget = gpuCompute.createRenderTarget();
* const outputRenderTarget = gpuCompute.createRenderTarget();
*
* // Now use the output texture where you want:
* myMaterial.uniforms.map.value = outputRenderTarget.texture;
......@@ -109,295 +109,301 @@ import {
* @param {WebGLRenderer} renderer The renderer
*/
var GPUComputationRenderer = function ( sizeX, sizeY, renderer ) {
class GPUComputationRenderer {
this.variables = [];
constructor( sizeX, sizeY, renderer ) {
this.currentTextureIndex = 0;
this.variables = [];
var dataType = FloatType;
this.currentTextureIndex = 0;
var scene = new Scene();
let dataType = FloatType;
var camera = new Camera();
camera.position.z = 1;
const scene = new Scene();
var passThruUniforms = {
passThruTexture: { value: null }
};
const camera = new Camera();
camera.position.z = 1;
var passThruShader = createShaderMaterial( getPassThroughFragmentShader(), passThruUniforms );
const passThruUniforms = {
passThruTexture: { value: null }
};
var mesh = new Mesh( new PlaneGeometry( 2, 2 ), passThruShader );
scene.add( mesh );
const passThruShader = createShaderMaterial( getPassThroughFragmentShader(), passThruUniforms );
const mesh = new Mesh( new PlaneGeometry( 2, 2 ), passThruShader );
scene.add( mesh );
this.setDataType = function ( type ) {
dataType = type;
return this;
this.setDataType = function ( type ) {
};
dataType = type;
return this;
this.addVariable = function ( variableName, computeFragmentShader, initialValueTexture ) {
};
var material = this.createShaderMaterial( computeFragmentShader );
this.addVariable = function ( variableName, computeFragmentShader, initialValueTexture ) {
var variable = {
name: variableName,
initialValueTexture: initialValueTexture,
material: material,
dependencies: null,
renderTargets: [],
wrapS: null,
wrapT: null,
minFilter: NearestFilter,
magFilter: NearestFilter
};
const material = this.createShaderMaterial( computeFragmentShader );
const variable = {
name: variableName,
initialValueTexture: initialValueTexture,
material: material,
dependencies: null,
renderTargets: [],
wrapS: null,
wrapT: null,
minFilter: NearestFilter,
magFilter: NearestFilter
};
this.variables.push( variable );
this.variables.push( variable );
return variable;
return variable;
};
};
this.setVariableDependencies = function ( variable, dependencies ) {
this.setVariableDependencies = function ( variable, dependencies ) {
variable.dependencies = dependencies;
variable.dependencies = dependencies;
};
};
this.init = function () {
this.init = function () {
if ( renderer.capabilities.isWebGL2 === false && renderer.extensions.has( 'OES_texture_float' ) === false ) {
if ( renderer.capabilities.isWebGL2 === false && renderer.extensions.has( 'OES_texture_float' ) === false ) {
return 'No OES_texture_float support for float textures.';
return 'No OES_texture_float support for float textures.';
}
}
if ( renderer.capabilities.maxVertexTextures === 0 ) {
if ( renderer.capabilities.maxVertexTextures === 0 ) {
return 'No support for vertex shader textures.';
return 'No support for vertex shader textures.';
}
}
for ( let i = 0; i < this.variables.length; i ++ ) {
const variable = this.variables[ i ];
for ( var i = 0; i < this.variables.length; i ++ ) {
// Creates rendertargets and initialize them with input texture
variable.renderTargets[ 0 ] = this.createRenderTarget( sizeX, sizeY, variable.wrapS, variable.wrapT, variable.minFilter, variable.magFilter );
variable.renderTargets[ 1 ] = this.createRenderTarget( sizeX, sizeY, variable.wrapS, variable.wrapT, variable.minFilter, variable.magFilter );
this.renderTexture( variable.initialValueTexture, variable.renderTargets[ 0 ] );
this.renderTexture( variable.initialValueTexture, variable.renderTargets[ 1 ] );
var variable = this.variables[ i ];
// Adds dependencies uniforms to the ShaderMaterial
const material = variable.material;
const uniforms = material.uniforms;
// Creates rendertargets and initialize them with input texture
variable.renderTargets[ 0 ] = this.createRenderTarget( sizeX, sizeY, variable.wrapS, variable.wrapT, variable.minFilter, variable.magFilter );
variable.renderTargets[ 1 ] = this.createRenderTarget( sizeX, sizeY, variable.wrapS, variable.wrapT, variable.minFilter, variable.magFilter );
this.renderTexture( variable.initialValueTexture, variable.renderTargets[ 0 ] );
this.renderTexture( variable.initialValueTexture, variable.renderTargets[ 1 ] );
if ( variable.dependencies !== null ) {
// Adds dependencies uniforms to the ShaderMaterial
var material = variable.material;
var uniforms = material.uniforms;
for ( let d = 0; d < variable.dependencies.length; d ++ ) {
if ( variable.dependencies !== null ) {
const depVar = variable.dependencies[ d ];
for ( var d = 0; d < variable.dependencies.length; d ++ ) {
if ( depVar.name !== variable.name ) {
var depVar = variable.dependencies[ d ];
// Checks if variable exists
let found = false;
if ( depVar.name !== variable.name ) {
for ( let j = 0; j < this.variables.length; j ++ ) {
// Checks if variable exists
var found = false;
for ( var j = 0; j < this.variables.length; j ++ ) {
if ( depVar.name === this.variables[ j ].name ) {
if ( depVar.name === this.variables[ j ].name ) {
found = true;
break;
found = true;
break;
}
}
}
if ( ! found ) {
if ( ! found ) {
return 'Variable dependency not found. Variable=' + variable.name + ', dependency=' + depVar.name;
return 'Variable dependency not found. Variable=' + variable.name + ', dependency=' + depVar.name;
}
}
}
uniforms[ depVar.name ] = { value: null };
uniforms[ depVar.name ] = { value: null };
material.fragmentShader = '\nuniform sampler2D ' + depVar.name + ';\n' + material.fragmentShader;
material.fragmentShader = '\nuniform sampler2D ' + depVar.name + ';\n' + material.fragmentShader;
}
}
}
}
this.currentTextureIndex = 0;
this.currentTextureIndex = 0;
return null;
return null;
};
};
this.compute = function () {
this.compute = function () {
const currentTextureIndex = this.currentTextureIndex;
const nextTextureIndex = this.currentTextureIndex === 0 ? 1 : 0;
var currentTextureIndex = this.currentTextureIndex;
var nextTextureIndex = this.currentTextureIndex === 0 ? 1 : 0;
for ( let i = 0, il = this.variables.length; i < il; i ++ ) {
for ( var i = 0, il = this.variables.length; i < il; i ++ ) {
const variable = this.variables[ i ];
var variable = this.variables[ i ];
// Sets texture dependencies uniforms
if ( variable.dependencies !== null ) {
// Sets texture dependencies uniforms
if ( variable.dependencies !== null ) {
const uniforms = variable.material.uniforms;
var uniforms = variable.material.uniforms;
for ( var d = 0, dl = variable.dependencies.length; d < dl; d ++ ) {
for ( let d = 0, dl = variable.dependencies.length; d < dl; d ++ ) {
var depVar = variable.dependencies[ d ];
const depVar = variable.dependencies[ d ];
uniforms[ depVar.name ].value = depVar.renderTargets[ currentTextureIndex ].texture;
uniforms[ depVar.name ].value = depVar.renderTargets[ currentTextureIndex ].texture;
}
}
}
// Performs the computation for this variable
this.doRenderTarget( variable.material, variable.renderTargets[ nextTextureIndex ] );
// Performs the computation for this variable
this.doRenderTarget( variable.material, variable.renderTargets[ nextTextureIndex ] );
}
}
this.currentTextureIndex = nextTextureIndex;
this.currentTextureIndex = nextTextureIndex;
};
};
this.getCurrentRenderTarget = function ( variable ) {
this.getCurrentRenderTarget = function ( variable ) {
return variable.renderTargets[ this.currentTextureIndex ];
return variable.renderTargets[ this.currentTextureIndex ];
};
};
this.getAlternateRenderTarget = function ( variable ) {
this.getAlternateRenderTarget = function ( variable ) {
return variable.renderTargets[ this.currentTextureIndex === 0 ? 1 : 0 ];
return variable.renderTargets[ this.currentTextureIndex === 0 ? 1 : 0 ];
};
};
function addResolutionDefine( materialShader ) {
function addResolutionDefine( materialShader ) {
materialShader.defines.resolution = 'vec2( ' + sizeX.toFixed( 1 ) + ', ' + sizeY.toFixed( 1 ) + ' )';
materialShader.defines.resolution = 'vec2( ' + sizeX.toFixed( 1 ) + ', ' + sizeY.toFixed( 1 ) + ' )';
}
}
this.addResolutionDefine = addResolutionDefine;
this.addResolutionDefine = addResolutionDefine;
// The following functions can be used to compute things manually
// The following functions can be used to compute things manually
function createShaderMaterial( computeFragmentShader, uniforms ) {
function createShaderMaterial( computeFragmentShader, uniforms ) {
uniforms = uniforms || {};
uniforms = uniforms || {};
const material = new ShaderMaterial( {
uniforms: uniforms,
vertexShader: getPassThroughVertexShader(),
fragmentShader: computeFragmentShader
} );
var material = new ShaderMaterial( {
uniforms: uniforms,
vertexShader: getPassThroughVertexShader(),
fragmentShader: computeFragmentShader
} );
addResolutionDefine( material );
addResolutionDefine( material );
return material;
return material;
}
}
this.createShaderMaterial = createShaderMaterial;
this.createShaderMaterial = createShaderMaterial;
this.createRenderTarget = function ( sizeXTexture, sizeYTexture, wrapS, wrapT, minFilter, magFilter ) {
this.createRenderTarget = function ( sizeXTexture, sizeYTexture, wrapS, wrapT, minFilter, magFilter ) {
sizeXTexture = sizeXTexture || sizeX;
sizeYTexture = sizeYTexture || sizeY;
sizeXTexture = sizeXTexture || sizeX;
sizeYTexture = sizeYTexture || sizeY;
wrapS = wrapS || ClampToEdgeWrapping;
wrapT = wrapT || ClampToEdgeWrapping;
wrapS = wrapS || ClampToEdgeWrapping;
wrapT = wrapT || ClampToEdgeWrapping;
minFilter = minFilter || NearestFilter;
magFilter = magFilter || NearestFilter;
minFilter = minFilter || NearestFilter;
magFilter = magFilter || NearestFilter;
const renderTarget = new WebGLRenderTarget( sizeXTexture, sizeYTexture, {
wrapS: wrapS,
wrapT: wrapT,
minFilter: minFilter,
magFilter: magFilter,
format: RGBAFormat,
type: dataType,
depthBuffer: false
} );
var renderTarget = new WebGLRenderTarget( sizeXTexture, sizeYTexture, {
wrapS: wrapS,
wrapT: wrapT,
minFilter: minFilter,
magFilter: magFilter,
format: RGBAFormat,
type: dataType,
depthBuffer: false
} );
return renderTarget;
return renderTarget;
};
};
this.createTexture = function () {
this.createTexture = function () {
const data = new Float32Array( sizeX * sizeY * 4 );
return new DataTexture( data, sizeX, sizeY, RGBAFormat, FloatType );
var data = new Float32Array( sizeX * sizeY * 4 );
return new DataTexture( data, sizeX, sizeY, RGBAFormat, FloatType );
};
};
this.renderTexture = function ( input, output ) {
this.renderTexture = function ( input, output ) {
// Takes a texture, and render out in rendertarget
// input = Texture
// output = RenderTarget
// Takes a texture, and render out in rendertarget
// input = Texture
// output = RenderTarget
passThruUniforms.passThruTexture.value = input;
passThruUniforms.passThruTexture.value = input;
this.doRenderTarget( passThruShader, output );
this.doRenderTarget( passThruShader, output );
passThruUniforms.passThruTexture.value = null;
passThruUniforms.passThruTexture.value = null;
};
};
this.doRenderTarget = function ( material, output ) {
this.doRenderTarget = function ( material, output ) {
const currentRenderTarget = renderer.getRenderTarget();
var currentRenderTarget = renderer.getRenderTarget();
mesh.material = material;
renderer.setRenderTarget( output );
renderer.render( scene, camera );
mesh.material = passThruShader;
mesh.material = material;
renderer.setRenderTarget( output );
renderer.render( scene, camera );
mesh.material = passThruShader;
renderer.setRenderTarget( currentRenderTarget );
renderer.setRenderTarget( currentRenderTarget );
};
};
// Shaders
// Shaders
function getPassThroughVertexShader() {
function getPassThroughVertexShader() {
return 'void main() {\n' +
'\n' +
' gl_Position = vec4( position, 1.0 );\n' +
'\n' +
'}\n';
return 'void main() {\n' +
'\n' +
' gl_Position = vec4( position, 1.0 );\n' +
'\n' +
'}\n';
}
}
function getPassThroughFragmentShader() {
function getPassThroughFragmentShader() {
return 'uniform sampler2D passThruTexture;\n' +
'\n' +
'void main() {\n' +
'\n' +
' vec2 uv = gl_FragCoord.xy / resolution.xy;\n' +
'\n' +
' gl_FragColor = texture2D( passThruTexture, uv );\n' +
'\n' +
'}\n';
return 'uniform sampler2D passThruTexture;\n' +
'\n' +
'void main() {\n' +
'\n' +
' vec2 uv = gl_FragCoord.xy / resolution.xy;\n' +
'\n' +
' gl_FragColor = texture2D( passThruTexture, uv );\n' +
'\n' +
'}\n';
}
}
};
}
export { GPUComputationRenderer };
......@@ -4,26 +4,23 @@ import {
Vector3
} from '../../../build/three.module.js';
var Gyroscope = function () {
const _translationObject = new Vector3();
const _quaternionObject = new Quaternion();
const _scaleObject = new Vector3();
Object3D.call( this );
const _translationWorld = new Vector3();
const _quaternionWorld = new Quaternion();
const _scaleWorld = new Vector3();
};
class Gyroscope extends Object3D {
Gyroscope.prototype = Object.create( Object3D.prototype );
Gyroscope.prototype.constructor = Gyroscope;
constructor() {
Gyroscope.prototype.updateMatrixWorld = ( function () {
super();
var translationObject = new Vector3();
var quaternionObject = new Quaternion();
var scaleObject = new Vector3();
}
var translationWorld = new Vector3();
var quaternionWorld = new Quaternion();
var scaleWorld = new Vector3();
return function updateMatrixWorld( force ) {
updateMatrixWorld( force ) {
this.matrixAutoUpdate && this.updateMatrix();
......@@ -35,10 +32,10 @@ Gyroscope.prototype.updateMatrixWorld = ( function () {
this.matrixWorld.multiplyMatrices( this.parent.matrixWorld, this.matrix );
this.matrixWorld.decompose( translationWorld, quaternionWorld, scaleWorld );
this.matrix.decompose( translationObject, quaternionObject, scaleObject );
this.matrixWorld.decompose( _translationWorld, _quaternionWorld, _scaleWorld );
this.matrix.decompose( _translationObject, _quaternionObject, _scaleObject );
this.matrixWorld.compose( translationWorld, quaternionObject, scaleWorld );
this.matrixWorld.compose( _translationWorld, _quaternionObject, _scaleWorld );
} else {
......@@ -56,14 +53,14 @@ Gyroscope.prototype.updateMatrixWorld = ( function () {
// update children
for ( var i = 0, l = this.children.length; i < l; i ++ ) {
for ( let i = 0, l = this.children.length; i < l; i ++ ) {
this.children[ i ].updateMatrixWorld( force );
}
};
}
}() );
}
export { Gyroscope };
......@@ -10,37 +10,89 @@ import {
} from '../../../build/three.module.js';
import { MD2Loader } from '../loaders/MD2Loader.js';
var MD2Character = function () {
class MD2Character {
var scope = this;
constructor() {
this.scale = 1;
this.animationFPS = 6;
this.scale = 1;
this.animationFPS = 6;
this.root = new Object3D();
this.root = new Object3D();
this.meshBody = null;
this.meshWeapon = null;
this.meshBody = null;
this.meshWeapon = null;
this.skinsBody = [];
this.skinsWeapon = [];
this.skinsBody = [];
this.skinsWeapon = [];
this.weapons = [];
this.weapons = [];
this.activeAnimation = null;
this.activeAnimation = null;
this.mixer = null;
this.mixer = null;
this.onLoadComplete = function () {};
this.onLoadComplete = function () {};
this.loadCounter = 0;
this.loadCounter = 0;
this.loadParts = function ( config ) {
}
loadParts( config ) {
const scope = this;
function createPart( geometry, skinMap ) {
const materialWireframe = new MeshLambertMaterial( { color: 0xffaa00, wireframe: true, morphTargets: true, morphNormals: true } );
const materialTexture = new MeshLambertMaterial( { color: 0xffffff, wireframe: false, map: skinMap, morphTargets: true, morphNormals: true } );
//
const mesh = new Mesh( geometry, materialTexture );
mesh.rotation.y = - Math.PI / 2;
mesh.castShadow = true;
mesh.receiveShadow = true;
//
mesh.materialTexture = materialTexture;
mesh.materialWireframe = materialWireframe;
return mesh;
}
function loadTextures( baseUrl, textureUrls ) {
const textureLoader = new TextureLoader();
const textures = [];
for ( let i = 0; i < textureUrls.length; i ++ ) {
textures[ i ] = textureLoader.load( baseUrl + textureUrls[ i ], checkLoadingComplete );
textures[ i ].mapping = UVMapping;
textures[ i ].name = textureUrls[ i ];
textures[ i ].encoding = sRGBEncoding;
}
return textures;
}
function checkLoadingComplete() {
scope.loadCounter -= 1;
if ( scope.loadCounter === 0 ) scope.onLoadComplete();
}
this.loadCounter = config.weapons.length * 2 + config.skins.length + 1;
var weaponsTextures = [];
for ( var i = 0; i < config.weapons.length; i ++ ) weaponsTextures[ i ] = config.weapons[ i ][ 1 ];
const weaponsTextures = [];
for ( let i = 0; i < config.weapons.length; i ++ ) weaponsTextures[ i ] = config.weapons[ i ][ 1 ];
// SKINS
this.skinsBody = loadTextures( config.baseUrl + 'skins/', config.skins );
......@@ -48,16 +100,16 @@ var MD2Character = function () {
// BODY
var loader = new MD2Loader();
const loader = new MD2Loader();
loader.load( config.baseUrl + config.body, function ( geo ) {
var boundingBox = new Box3();
const boundingBox = new Box3();
boundingBox.setFromBufferAttribute( geo.attributes.position );
scope.root.position.y = - scope.scale * boundingBox.min.y;
var mesh = createPart( geo, scope.skinsBody[ 0 ] );
const mesh = createPart( geo, scope.skinsBody[ 0 ] );
mesh.scale.set( scope.scale, scope.scale, scope.scale );
scope.root.add( mesh );
......@@ -75,11 +127,11 @@ var MD2Character = function () {
// WEAPONS
var generateCallback = function ( index, name ) {
const generateCallback = function ( index, name ) {
return function ( geo ) {
var mesh = createPart( geo, scope.skinsWeapon[ index ] );
const mesh = createPart( geo, scope.skinsWeapon[ index ] );
mesh.scale.set( scope.scale, scope.scale, scope.scale );
mesh.visible = false;
......@@ -96,15 +148,15 @@ var MD2Character = function () {
};
for ( var i = 0; i < config.weapons.length; i ++ ) {
for ( let i = 0; i < config.weapons.length; i ++ ) {
loader.load( config.baseUrl + config.weapons[ i ][ 0 ], generateCallback( i, config.weapons[ i ][ 0 ] ) );
}
};
}
this.setPlaybackRate = function ( rate ) {
setPlaybackRate( rate ) {
if ( rate !== 0 ) {
......@@ -116,9 +168,9 @@ var MD2Character = function () {
}
};
}
this.setWireframe = function ( wireframeEnabled ) {
setWireframe( wireframeEnabled ) {
if ( wireframeEnabled ) {
......@@ -132,9 +184,9 @@ var MD2Character = function () {
}
};
}
this.setSkin = function ( index ) {
setSkin( index ) {
if ( this.meshBody && this.meshBody.material.wireframe === false ) {
......@@ -142,26 +194,26 @@ var MD2Character = function () {
}
};
}
this.setWeapon = function ( index ) {
setWeapon( index ) {
for ( var i = 0; i < this.weapons.length; i ++ ) this.weapons[ i ].visible = false;
for ( let i = 0; i < this.weapons.length; i ++ ) this.weapons[ i ].visible = false;
var activeWeapon = this.weapons[ index ];
const activeWeapon = this.weapons[ index ];
if ( activeWeapon ) {
activeWeapon.visible = true;
this.meshWeapon = activeWeapon;
scope.syncWeaponAnimation();
this.syncWeaponAnimation();
}
};
}
this.setAnimation = function ( clipName ) {
setAnimation( clipName ) {
if ( this.meshBody ) {
......@@ -172,7 +224,7 @@ var MD2Character = function () {
}
var action = this.mixer.clipAction( clipName, this.meshBody );
const action = this.mixer.clipAction( clipName, this.meshBody );
if ( action ) {
......@@ -182,17 +234,17 @@ var MD2Character = function () {
}
scope.activeClipName = clipName;
this.activeClipName = clipName;
scope.syncWeaponAnimation();
this.syncWeaponAnimation();
};
}
this.syncWeaponAnimation = function () {
syncWeaponAnimation() {
var clipName = scope.activeClipName;
const clipName = this.activeClipName;
if ( scope.meshWeapon ) {
if ( this.meshWeapon ) {
if ( this.meshWeapon.activeAction ) {
......@@ -201,7 +253,7 @@ var MD2Character = function () {
}
var action = this.mixer.clipAction( clipName, this.meshWeapon );
const action = this.mixer.clipAction( clipName, this.meshWeapon );
if ( action ) {
......@@ -211,62 +263,14 @@ var MD2Character = function () {
}
};
this.update = function ( delta ) {
if ( this.mixer ) this.mixer.update( delta );
};
function loadTextures( baseUrl, textureUrls ) {
var textureLoader = new TextureLoader();
var textures = [];
for ( var i = 0; i < textureUrls.length; i ++ ) {
textures[ i ] = textureLoader.load( baseUrl + textureUrls[ i ], checkLoadingComplete );
textures[ i ].mapping = UVMapping;
textures[ i ].name = textureUrls[ i ];
textures[ i ].encoding = sRGBEncoding;
}
return textures;
}
function createPart( geometry, skinMap ) {
var materialWireframe = new MeshLambertMaterial( { color: 0xffaa00, wireframe: true, morphTargets: true, morphNormals: true } );
var materialTexture = new MeshLambertMaterial( { color: 0xffffff, wireframe: false, map: skinMap, morphTargets: true, morphNormals: true } );
//
var mesh = new Mesh( geometry, materialTexture );
mesh.rotation.y = - Math.PI / 2;
mesh.castShadow = true;
mesh.receiveShadow = true;
//
mesh.materialTexture = materialTexture;
mesh.materialWireframe = materialWireframe;
return mesh;
}
function checkLoadingComplete() {
scope.loadCounter -= 1;
update( delta ) {
if ( scope.loadCounter === 0 ) scope.onLoadComplete();
if ( this.mixer ) this.mixer.update( delta );
}
};
}
export { MD2Character };
......@@ -10,97 +10,98 @@ import {
import { MD2Loader } from '../loaders/MD2Loader.js';
import { MorphBlendMesh } from '../misc/MorphBlendMesh.js';
var MD2CharacterComplex = function () {
class MD2CharacterComplex {
var scope = this;
constructor() {
this.scale = 1;
this.scale = 1;
// animation parameters
// animation parameters
this.animationFPS = 6;
this.transitionFrames = 15;
this.animationFPS = 6;
this.transitionFrames = 15;
// movement model parameters
// movement model parameters
this.maxSpeed = 275;
this.maxReverseSpeed = - 275;
this.maxSpeed = 275;
this.maxReverseSpeed = - 275;
this.frontAcceleration = 600;
this.backAcceleration = 600;
this.frontAcceleration = 600;
this.backAcceleration = 600;
this.frontDecceleration = 600;
this.frontDecceleration = 600;
this.angularSpeed = 2.5;
this.angularSpeed = 2.5;
// rig
// rig
this.root = new Object3D();
this.root = new Object3D();
this.meshBody = null;
this.meshWeapon = null;
this.meshBody = null;
this.meshWeapon = null;
this.controls = null;
this.controls = null;
// skins
// skins
this.skinsBody = [];
this.skinsWeapon = [];
this.skinsBody = [];
this.skinsWeapon = [];
this.weapons = [];
this.weapons = [];
this.currentSkin = undefined;
this.currentSkin = undefined;
//
//
this.onLoadComplete = function () {};
this.onLoadComplete = function () {};
// internals
// internals
this.meshes = [];
this.animations = {};
this.meshes = [];
this.animations = {};
this.loadCounter = 0;
this.loadCounter = 0;
// internal movement control variables
// internal movement control variables
this.speed = 0;
this.bodyOrientation = 0;
this.speed = 0;
this.bodyOrientation = 0;
this.walkSpeed = this.maxSpeed;
this.crouchSpeed = this.maxSpeed * 0.5;
this.walkSpeed = this.maxSpeed;
this.crouchSpeed = this.maxSpeed * 0.5;
// internal animation parameters
// internal animation parameters
this.activeAnimation = null;
this.oldAnimation = null;
this.activeAnimation = null;
this.oldAnimation = null;
// API
// API
}
this.enableShadows = function ( enable ) {
enableShadows( enable ) {
for ( var i = 0; i < this.meshes.length; i ++ ) {
for ( let i = 0; i < this.meshes.length; i ++ ) {
this.meshes[ i ].castShadow = enable;
this.meshes[ i ].receiveShadow = enable;
}
};
}
this.setVisible = function ( enable ) {
setVisible( enable ) {
for ( var i = 0; i < this.meshes.length; i ++ ) {
for ( let i = 0; i < this.meshes.length; i ++ ) {
this.meshes[ i ].visible = enable;
this.meshes[ i ].visible = enable;
}
};
}
this.shareParts = function ( original ) {
shareParts( original ) {
this.animations = original.animations;
this.walkSpeed = original.walkSpeed;
......@@ -111,7 +112,7 @@ var MD2CharacterComplex = function () {
// BODY
var mesh = createPart( original.meshBody.geometry, this.skinsBody[ 0 ] );
const mesh = this._createPart( original.meshBody.geometry, this.skinsBody[ 0 ] );
mesh.scale.set( this.scale, this.scale, this.scale );
this.root.position.y = original.root.position.y;
......@@ -123,9 +124,9 @@ var MD2CharacterComplex = function () {
// WEAPONS
for ( var i = 0; i < original.weapons.length; i ++ ) {
for ( let i = 0; i < original.weapons.length; i ++ ) {
var meshWeapon = createPart( original.weapons[ i ].geometry, this.skinsWeapon[ i ] );
const meshWeapon = this._createPart( original.weapons[ i ].geometry, this.skinsWeapon[ i ] );
meshWeapon.scale.set( this.scale, this.scale, this.scale );
meshWeapon.visible = false;
......@@ -140,9 +141,36 @@ var MD2CharacterComplex = function () {
}
};
}
loadParts( config ) {
const scope = this;
function loadTextures( baseUrl, textureUrls ) {
const textureLoader = new TextureLoader();
const textures = [];
for ( let i = 0; i < textureUrls.length; i ++ ) {
textures[ i ] = textureLoader.load( baseUrl + textureUrls[ i ], checkLoadingComplete );
textures[ i ].mapping = UVMapping;
textures[ i ].name = textureUrls[ i ];
textures[ i ].encoding = sRGBEncoding;
}
return textures;
}
function checkLoadingComplete() {
this.loadParts = function ( config ) {
scope.loadCounter -= 1;
if ( scope.loadCounter === 0 ) scope.onLoadComplete();
}
this.animations = config.animations;
this.walkSpeed = config.walkSpeed;
......@@ -150,8 +178,8 @@ var MD2CharacterComplex = function () {
this.loadCounter = config.weapons.length * 2 + config.skins.length + 1;
var weaponsTextures = [];
for ( var i = 0; i < config.weapons.length; i ++ ) weaponsTextures[ i ] = config.weapons[ i ][ 1 ];
const weaponsTextures = [];
for ( let i = 0; i < config.weapons.length; i ++ ) weaponsTextures[ i ] = config.weapons[ i ][ 1 ];
// SKINS
......@@ -160,16 +188,16 @@ var MD2CharacterComplex = function () {
// BODY
var loader = new MD2Loader();
const loader = new MD2Loader();
loader.load( config.baseUrl + config.body, function ( geo ) {
var boundingBox = new Box3();
const boundingBox = new Box3();
boundingBox.setFromBufferAttribute( geo.attributes.position );
scope.root.position.y = - scope.scale * boundingBox.min.y;
var mesh = createPart( geo, scope.skinsBody[ 0 ] );
const mesh = scope._createPart( geo, scope.skinsBody[ 0 ] );
mesh.scale.set( scope.scale, scope.scale, scope.scale );
scope.root.add( mesh );
......@@ -183,11 +211,11 @@ var MD2CharacterComplex = function () {
// WEAPONS
var generateCallback = function ( index, name ) {
const generateCallback = function ( index, name ) {
return function ( geo ) {
var mesh = createPart( geo, scope.skinsWeapon[ index ] );
const mesh = scope._createPart( geo, scope.skinsWeapon[ index ] );
mesh.scale.set( scope.scale, scope.scale, scope.scale );
mesh.visible = false;
......@@ -205,22 +233,22 @@ var MD2CharacterComplex = function () {
};
for ( var i = 0; i < config.weapons.length; i ++ ) {
for ( let i = 0; i < config.weapons.length; i ++ ) {
loader.load( config.baseUrl + config.weapons[ i ][ 0 ], generateCallback( i, config.weapons[ i ][ 0 ] ) );
}
};
}
this.setPlaybackRate = function ( rate ) {
setPlaybackRate( rate ) {
if ( this.meshBody ) this.meshBody.duration = this.meshBody.baseDuration / rate;
if ( this.meshWeapon ) this.meshWeapon.duration = this.meshWeapon.baseDuration / rate;
};
}
this.setWireframe = function ( wireframeEnabled ) {
setWireframe( wireframeEnabled ) {
if ( wireframeEnabled ) {
......@@ -234,9 +262,9 @@ var MD2CharacterComplex = function () {
}
};
}
this.setSkin = function ( index ) {
setSkin( index ) {
if ( this.meshBody && this.meshBody.material.wireframe === false ) {
......@@ -245,13 +273,13 @@ var MD2CharacterComplex = function () {
}
};
}
this.setWeapon = function ( index ) {
setWeapon( index ) {
for ( var i = 0; i < this.weapons.length; i ++ ) this.weapons[ i ].visible = false;
for ( let i = 0; i < this.weapons.length; i ++ ) this.weapons[ i ].visible = false;
var activeWeapon = this.weapons[ index ];
const activeWeapon = this.weapons[ index ];
if ( activeWeapon ) {
......@@ -267,9 +295,9 @@ var MD2CharacterComplex = function () {
}
};
}
this.setAnimation = function ( animationName ) {
setAnimation( animationName ) {
if ( animationName === this.activeAnimation || ! animationName ) return;
......@@ -293,9 +321,9 @@ var MD2CharacterComplex = function () {
}
};
}
this.update = function ( delta ) {
update( delta ) {
if ( this.controls ) this.updateMovementModel( delta );
......@@ -306,11 +334,11 @@ var MD2CharacterComplex = function () {
}
};
}
this.updateAnimations = function ( delta ) {
updateAnimations( delta ) {
var mix = 1;
let mix = 1;
if ( this.blendCounter > 0 ) {
......@@ -337,14 +365,14 @@ var MD2CharacterComplex = function () {
}
};
}
this.updateBehaviors = function () {
updateBehaviors() {
var controls = this.controls;
var animations = this.animations;
const controls = this.controls;
const animations = this.animations;
var moveAnimation, idleAnimation;
let moveAnimation, idleAnimation;
// crouch vs stand
......@@ -446,11 +474,17 @@ var MD2CharacterComplex = function () {
}
};
}
this.updateMovementModel = function ( delta ) {
updateMovementModel( delta ) {
var controls = this.controls;
function exponentialEaseOut( k ) {
return k === 1 ? 1 : - Math.pow( 2, - 10 * k ) + 1;
}
const controls = this.controls;
// speed based on controls
......@@ -465,7 +499,7 @@ var MD2CharacterComplex = function () {
// orientation based on controls
// (don't just stand while turning)
var dir = 1;
const dir = 1;
if ( controls.moveLeft ) {
......@@ -487,12 +521,12 @@ var MD2CharacterComplex = function () {
if ( this.speed > 0 ) {
var k = exponentialEaseOut( this.speed / this.maxSpeed );
const k = exponentialEaseOut( this.speed / this.maxSpeed );
this.speed = MathUtils.clamp( this.speed - k * delta * this.frontDecceleration, 0, this.maxSpeed );
} else {
var k = exponentialEaseOut( this.speed / this.maxReverseSpeed );
const k = exponentialEaseOut( this.speed / this.maxReverseSpeed );
this.speed = MathUtils.clamp( this.speed + k * delta * this.backAcceleration, this.maxReverseSpeed, 0 );
}
......@@ -501,7 +535,7 @@ var MD2CharacterComplex = function () {
// displacement
var forwardDelta = this.speed * delta;
const forwardDelta = this.speed * delta;
this.root.position.x += Math.sin( this.bodyOrientation ) * forwardDelta;
this.root.position.z += Math.cos( this.bodyOrientation ) * forwardDelta;
......@@ -510,36 +544,18 @@ var MD2CharacterComplex = function () {
this.root.rotation.y = this.bodyOrientation;
};
// internal helpers
function loadTextures( baseUrl, textureUrls ) {
var textureLoader = new TextureLoader();
var textures = [];
for ( var i = 0; i < textureUrls.length; i ++ ) {
textures[ i ] = textureLoader.load( baseUrl + textureUrls[ i ], checkLoadingComplete );
textures[ i ].mapping = UVMapping;
textures[ i ].name = textureUrls[ i ];
textures[ i ].encoding = sRGBEncoding;
}
return textures;
}
function createPart( geometry, skinMap ) {
// internal
var materialWireframe = new MeshLambertMaterial( { color: 0xffaa00, wireframe: true, morphTargets: true, morphNormals: true } );
var materialTexture = new MeshLambertMaterial( { color: 0xffffff, wireframe: false, map: skinMap, morphTargets: true, morphNormals: true } );
_createPart( geometry, skinMap ) {
const materialWireframe = new MeshLambertMaterial( { color: 0xffaa00, wireframe: true, morphTargets: true, morphNormals: true } );
const materialTexture = new MeshLambertMaterial( { color: 0xffffff, wireframe: false, map: skinMap, morphTargets: true, morphNormals: true } );
//
var mesh = new MorphBlendMesh( geometry, materialTexture );
const mesh = new MorphBlendMesh( geometry, materialTexture );
mesh.rotation.y = - Math.PI / 2;
//
......@@ -549,25 +565,12 @@ var MD2CharacterComplex = function () {
//
mesh.autoCreateAnimations( scope.animationFPS );
mesh.autoCreateAnimations( this.animationFPS );
return mesh;
}
function checkLoadingComplete() {
scope.loadCounter -= 1;
if ( scope.loadCounter === 0 ) scope.onLoadComplete();
}
function exponentialEaseOut( k ) {
return k === 1 ? 1 : - Math.pow( 2, - 10 * k ) + 1;
}
};
}
export { MD2CharacterComplex };
......@@ -4,71 +4,72 @@ import {
Mesh
} from '../../../build/three.module.js';
var MorphAnimMesh = function ( geometry, material ) {
class MorphAnimMesh extends Mesh {
Mesh.call( this, geometry, material );
constructor( geometry, material ) {
this.type = 'MorphAnimMesh';
super( geometry, material );
this.mixer = new AnimationMixer( this );
this.activeAction = null;
this.type = 'MorphAnimMesh';
};
this.mixer = new AnimationMixer( this );
this.activeAction = null;
MorphAnimMesh.prototype = Object.create( Mesh.prototype );
MorphAnimMesh.prototype.constructor = MorphAnimMesh;
}
MorphAnimMesh.prototype.setDirectionForward = function () {
setDirectionForward() {
this.mixer.timeScale = 1.0;
this.mixer.timeScale = 1.0;
};
}
MorphAnimMesh.prototype.setDirectionBackward = function () {
setDirectionBackward() {
this.mixer.timeScale = - 1.0;
this.mixer.timeScale = - 1.0;
};
}
MorphAnimMesh.prototype.playAnimation = function ( label, fps ) {
playAnimation( label, fps ) {
if ( this.activeAction ) {
if ( this.activeAction ) {
this.activeAction.stop();
this.activeAction = null;
this.activeAction.stop();
this.activeAction = null;
}
}
const clip = AnimationClip.findByName( this, label );
var clip = AnimationClip.findByName( this, label );
if ( clip ) {
if ( clip ) {
const action = this.mixer.clipAction( clip );
action.timeScale = ( clip.tracks.length * fps ) / clip.duration;
this.activeAction = action.play();
var action = this.mixer.clipAction( clip );
action.timeScale = ( clip.tracks.length * fps ) / clip.duration;
this.activeAction = action.play();
} else {
} else {
throw new Error( 'THREE.MorphAnimMesh: animations[' + label + '] undefined in .playAnimation()' );
throw new Error( 'THREE.MorphAnimMesh: animations[' + label + '] undefined in .playAnimation()' );
}
}
};
updateAnimation( delta ) {
MorphAnimMesh.prototype.updateAnimation = function ( delta ) {
this.mixer.update( delta );
this.mixer.update( delta );
}
};
copy( source ) {
MorphAnimMesh.prototype.copy = function ( source ) {
super.copy( source );
Mesh.prototype.copy.call( this, source );
this.mixer = new AnimationMixer( this );
this.mixer = new AnimationMixer( this );
return this;
return this;
}
};
}
export { MorphAnimMesh };
此差异已折叠。
此差异已折叠。
......@@ -145,7 +145,6 @@
cameraControls = new OrbitControls( camera, renderer.domElement );
cameraControls.target.set( 0, 50, 0 );
cameraControls.enableKeys = false;
cameraControls.update();
// CHARACTER
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册