webvr js meetup initial commit

This commit is contained in:
Senad Uka
2017-03-11 15:22:17 +01:00
commit 3f640b55db
761 changed files with 264174 additions and 0 deletions

13
node_modules/three/examples/fonts/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,13 @@
Copyright <20> 2004 by MAGENTA Ltd. All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy of the fonts accompanying this license ("Fonts") and associated documentation files (the "Font Software"), to reproduce and distribute the Font Software, including without limitation the rights to use, copy, merge, publish, distribute, and/or sell copies of the Font Software, and to permit persons to whom the Font Software is furnished to do so, subject to the following conditions:
The above copyright and this permission notice shall be included in all copies of one or more of the Font Software typefaces.
The Font Software may be modified, altered, or added to, and in particular the designs of glyphs or characters in the Fonts may be modified and additional glyphs or characters may be added to the Fonts, only if the fonts are renamed to names not containing the word "MgOpen", or if the modifications are accepted for inclusion in the Font Software itself by the each appointed Administrator.
This License becomes null and void to the extent applicable to Fonts or Font Software that has been modified and is distributed under the "MgOpen" name.
The Font Software may be sold as part of a larger software package but no copy of one or more of the Font Software typefaces may be sold by itself.
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL MAGENTA OR PERSONS OR BODIES IN CHARGE OF ADMINISTRATION AND MAINTENANCE OF THE FONT SOFTWARE BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE.

2
node_modules/three/examples/fonts/README generated vendored Normal file
View File

@@ -0,0 +1,2 @@
Use Facetype.js to generate typeface.json fonts.
http://gero3.github.io/facetype.js/

190
node_modules/three/examples/fonts/droid/NOTICE generated vendored Normal file
View File

@@ -0,0 +1,190 @@
Copyright (c) 2005-2008, The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS

18
node_modules/three/examples/fonts/droid/README.txt generated vendored Normal file
View File

@@ -0,0 +1,18 @@
Copyright (C) 2008 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
##########
This directory contains the fonts for the platform. They are licensed
under the Apache 2 license.

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

BIN
node_modules/three/examples/fonts/ttf/kenpixel.ttf generated vendored Normal file

Binary file not shown.

115
node_modules/three/examples/js/AnimationClipCreator.js generated vendored Normal file
View File

@@ -0,0 +1,115 @@
/**
*
* Creator of typical test AnimationClips / KeyframeTracks
*
* @author Ben Houston / http://clara.io/
* @author David Sarno / http://lighthaus.us/
*/
THREE.AnimationClipCreator = function() {
};
THREE.AnimationClipCreator.CreateRotationAnimation = function( period, axis ) {
var times = [ 0, period ], values = [ 0, 360 ];
axis = axis || 'x';
var trackName = '.rotation[' + axis + ']';
var track = new THREE.NumberKeyframeTrack( trackName, times, values );
return new THREE.AnimationClip( null, period, [ track ] );
};
THREE.AnimationClipCreator.CreateScaleAxisAnimation = function( period, axis ) {
var times = [ 0, period ], values = [ 0, 1 ];
axis = axis || 'x';
var trackName = '.scale[' + axis + ']';
var track = new THREE.NumberKeyframeTrack( trackName, times, values );
return new THREE.AnimationClip( null, period, [ track ] );
};
THREE.AnimationClipCreator.CreateShakeAnimation = function( duration, shakeScale ) {
var times = [], values = [], tmp = new THREE.Vector3();
for( var i = 0; i < duration * 10; i ++ ) {
times.push( i / 10 );
tmp.set( Math.random() * 2.0 - 1.0, Math.random() * 2.0 - 1.0, Math.random() * 2.0 - 1.0 ).
multiply( shakeScale ).
toArray( values, values.length );
}
var trackName = '.position';
var track = new THREE.VectorKeyframeTrack( trackName, times, values );
return new THREE.AnimationClip( null, duration, [ track ] );
};
THREE.AnimationClipCreator.CreatePulsationAnimation = function( duration, pulseScale ) {
var times = [], values = [], tmp = new THREE.Vector3();
for( var i = 0; i < duration * 10; i ++ ) {
times.push( i / 10 );
var scaleFactor = Math.random() * pulseScale;
tmp.set( scaleFactor, scaleFactor, scaleFactor ).
toArray( values, values.length );
}
var trackName = '.scale';
var track = new THREE.VectorKeyframeTrack( trackName, keys );
return new THREE.AnimationClip( null, duration, [ track ] );
};
THREE.AnimationClipCreator.CreateVisibilityAnimation = function( duration ) {
var times = [ 0, duration / 2, duration ], values = [ true, false, true ];
var trackName = '.visible';
var track = new THREE.BooleanKeyframeTrack( trackName, times, values );
return new THREE.AnimationClip( null, duration, [ track ] );
};
THREE.AnimationClipCreator.CreateMaterialColorAnimation = function( duration, colors, loop ) {
var times = [], values = [],
timeStep = duration / colors.length;
for( var i = 0; i <= colors.length; i ++ ) {
timees.push( i * timeStep );
values.push( colors[ i % colors.length ] );
}
var trackName = '.material[0].color';
var track = new THREE.ColorKeyframeTrack( trackName, times, values );
return new THREE.AnimationClip( null, duration, [ track ] );
};

182
node_modules/three/examples/js/BlendCharacter.js generated vendored Normal file
View File

@@ -0,0 +1,182 @@
/**
* @author Michael Guerrero / http://realitymeltdown.com
*/
THREE.BlendCharacter = function () {
this.weightSchedule = [];
this.warpSchedule = [];
this.load = function ( url, onLoad ) {
var scope = this;
var loader = new THREE.ObjectLoader();
loader.load( url, function( loadedObject ) {
// The exporter does not currently allow exporting a skinned mesh by itself
// so we must fish it out of the hierarchy it is embedded in (scene)
loadedObject.traverse( function( object ) {
if ( object instanceof THREE.SkinnedMesh ) {
scope.skinnedMesh = object;
}
} );
THREE.SkinnedMesh.call( scope, scope.skinnedMesh.geometry, scope.skinnedMesh.material );
// If we didn't successfully find the mesh, bail out
if ( scope.skinnedMesh == undefined ) {
console.log( 'unable to find skinned mesh in ' + url );
return;
}
scope.material.skinning = true;
scope.mixer = new THREE.AnimationMixer( scope );
// Create the animations
for ( var i = 0; i < scope.geometry.animations.length; ++ i ) {
scope.mixer.clipAction( scope.geometry.animations[ i ] );
}
// Loading is complete, fire the callback
if ( onLoad !== undefined ) onLoad();
} );
};
this.loadJSON = function ( url, onLoad ) {
var scope = this;
var loader = new THREE.JSONLoader();
loader.load( url, function( geometry, materials ) {
var originalMaterial = materials[ 0 ];
originalMaterial.skinning = true;
THREE.SkinnedMesh.call( scope, geometry, originalMaterial );
var mixer = new THREE.AnimationMixer( scope );
scope.mixer = mixer;
// Create the animations
for ( var i = 0; i < geometry.animations.length; ++ i ) {
mixer.clipAction( geometry.animations[ i ] );
}
// Loading is complete, fire the callback
if ( onLoad !== undefined ) onLoad();
} );
};
this.update = function( dt ) {
this.mixer.update( dt );
};
this.play = function( animName, weight ) {
//console.log("play('%s', %f)", animName, weight);
return this.mixer.clipAction( animName ).
setEffectiveWeight( weight ).play();
};
this.crossfade = function( fromAnimName, toAnimName, duration ) {
this.mixer.stopAllAction();
var fromAction = this.play( fromAnimName, 1 );
var toAction = this.play( toAnimName, 1 );
fromAction.crossFadeTo( toAction, duration, false );
};
this.warp = function( fromAnimName, toAnimName, duration ) {
this.mixer.stopAllAction();
var fromAction = this.play( fromAnimName, 1 );
var toAction = this.play( toAnimName, 1 );
fromAction.crossFadeTo( toAction, duration, true );
};
this.applyWeight = function( animName, weight ) {
this.mixer.clipAction( animName ).setEffectiveWeight( weight );
};
this.getWeight = function( animName ) {
return this.mixer.clipAction( animName ).getEffectiveWeight();
};
this.pauseAll = function() {
this.mixer.timeScale = 0;
};
this.unPauseAll = function() {
this.mixer.timeScale = 1;
};
this.stopAll = function() {
this.mixer.stopAllAction();
};
this.showModel = function( boolean ) {
this.visible = boolean;
};
};
THREE.BlendCharacter.prototype = Object.create( THREE.SkinnedMesh.prototype );
THREE.BlendCharacter.prototype.constructor = THREE.BlendCharacter;
THREE.BlendCharacter.prototype.getForward = function() {
var forward = new THREE.Vector3();
return function() {
// pull the character's forward basis vector out of the matrix
forward.set(
- this.matrix.elements[ 8 ],
- this.matrix.elements[ 9 ],
- this.matrix.elements[ 10 ]
);
return forward;
}
};

207
node_modules/three/examples/js/BlendCharacterGui.js generated vendored Normal file
View File

@@ -0,0 +1,207 @@
/**
* @author Michael Guerrero / http://realitymeltdown.com
*/
function BlendCharacterGui( blendMesh ) {
var controls = {
gui: null,
"Show Model": true,
"Show Skeleton": false,
"Time Scale": 1.0,
"Step Size": 0.016,
"Crossfade Time": 3.5,
"idle": 0.33,
"walk": 0.33,
"run": 0.33
};
var blendMesh = blendMesh;
this.showModel = function() {
return controls[ 'Show Model' ];
};
this.showSkeleton = function() {
return controls[ 'Show Skeleton' ];
};
this.getTimeScale = function() {
return controls[ 'Time Scale' ];
};
this.update = function( time ) {
controls[ 'idle' ] = blendMesh.getWeight( 'idle' );
controls[ 'walk' ] = blendMesh.getWeight( 'walk' );
controls[ 'run' ] = blendMesh.getWeight( 'run' );
};
var init = function() {
controls.gui = new dat.GUI();
var settings = controls.gui.addFolder( 'Settings' );
var playback = controls.gui.addFolder( 'Playback' );
var blending = controls.gui.addFolder( 'Blend Tuning' );
settings.add( controls, "Show Model" ).onChange( controls.showModelChanged );
settings.add( controls, "Show Skeleton" ).onChange( controls.showSkeletonChanged );
settings.add( controls, "Time Scale", 0, 1, 0.01 );
settings.add( controls, "Step Size", 0.01, 0.1, 0.01 );
settings.add( controls, "Crossfade Time", 0.1, 6.0, 0.05 );
// These controls execute functions
playback.add( controls, "start" );
playback.add( controls, "pause" );
playback.add( controls, "step" );
playback.add( controls, "idle to walk" );
playback.add( controls, "walk to run" );
playback.add( controls, "warp walk to run" );
blending.add( controls, "idle", 0, 1, 0.01 ).listen().onChange( controls.weight );
blending.add( controls, "walk", 0, 1, 0.01 ).listen().onChange( controls.weight );
blending.add( controls, "run", 0, 1, 0.01 ).listen().onChange( controls.weight );
settings.open();
playback.open();
blending.open();
};
var getAnimationData = function() {
return {
detail: {
anims: [ "idle", "walk", "run" ],
weights: [ controls[ 'idle' ],
controls[ 'walk' ],
controls[ 'run' ] ]
}
};
};
controls.start = function() {
var startEvent = new CustomEvent( 'start-animation', getAnimationData() );
window.dispatchEvent( startEvent );
};
controls.stop = function() {
var stopEvent = new CustomEvent( 'stop-animation' );
window.dispatchEvent( stopEvent );
};
controls.pause = function() {
var pauseEvent = new CustomEvent( 'pause-animation' );
window.dispatchEvent( pauseEvent );
};
controls.step = function() {
var stepData = { detail: { stepSize: controls[ 'Step Size' ] } };
window.dispatchEvent( new CustomEvent( 'step-animation', stepData ) );
};
controls.weight = function() {
// renormalize
var sum = controls[ 'idle' ] + controls[ 'walk' ] + controls[ 'run' ];
controls[ 'idle' ] /= sum;
controls[ 'walk' ] /= sum;
controls[ 'run' ] /= sum;
var weightEvent = new CustomEvent( 'weight-animation', getAnimationData() );
window.dispatchEvent( weightEvent );
};
controls.crossfade = function( from, to ) {
var fadeData = getAnimationData();
fadeData.detail.from = from;
fadeData.detail.to = to;
fadeData.detail.time = controls[ "Crossfade Time" ];
window.dispatchEvent( new CustomEvent( 'crossfade', fadeData ) );
};
controls.warp = function( from, to ) {
var warpData = getAnimationData();
warpData.detail.from = 'walk';
warpData.detail.to = 'run';
warpData.detail.time = controls[ "Crossfade Time" ];
window.dispatchEvent( new CustomEvent( 'warp', warpData ) );
};
controls[ 'idle to walk' ] = function() {
controls.crossfade( 'idle', 'walk' );
};
controls[ 'walk to run' ] = function() {
controls.crossfade( 'walk', 'run' );
};
controls[ 'warp walk to run' ] = function() {
controls.warp( 'walk', 'run' );
};
controls.showSkeletonChanged = function() {
var data = {
detail: {
shouldShow: controls[ 'Show Skeleton' ]
}
};
window.dispatchEvent( new CustomEvent( 'toggle-show-skeleton', data ) );
};
controls.showModelChanged = function() {
var data = {
detail: {
shouldShow: controls[ 'Show Model' ]
}
};
window.dispatchEvent( new CustomEvent( 'toggle-show-model', data ) );
};
init.call( this );
}

187
node_modules/three/examples/js/BufferGeometryUtils.js generated vendored Normal file
View File

@@ -0,0 +1,187 @@
/**
* @author mrdoob / http://mrdoob.com/
*/
THREE.BufferGeometryUtils = {
computeTangents: function ( geometry ) {
var index = geometry.index;
var attributes = geometry.attributes;
// based on http://www.terathon.com/code/tangent.html
// (per vertex tangents)
if ( index === null ||
attributes.position === undefined ||
attributes.normal === undefined ||
attributes.uv === undefined ) {
console.warn( 'THREE.BufferGeometry: Missing required attributes (index, position, normal or uv) in BufferGeometry.computeTangents()' );
return;
}
var indices = index.array;
var positions = attributes.position.array;
var normals = attributes.normal.array;
var uvs = attributes.uv.array;
var nVertices = positions.length / 3;
if ( attributes.tangent === undefined ) {
geometry.addAttribute( 'tangent', new THREE.BufferAttribute( new Float32Array( 4 * nVertices ), 4 ) );
}
var tangents = attributes.tangent.array;
var tan1 = [], tan2 = [];
for ( var k = 0; k < nVertices; k ++ ) {
tan1[ k ] = new THREE.Vector3();
tan2[ k ] = new THREE.Vector3();
}
var vA = new THREE.Vector3(),
vB = new THREE.Vector3(),
vC = new THREE.Vector3(),
uvA = new THREE.Vector2(),
uvB = new THREE.Vector2(),
uvC = new THREE.Vector2(),
sdir = new THREE.Vector3(),
tdir = new THREE.Vector3();
function handleTriangle( a, b, c ) {
vA.fromArray( positions, a * 3 );
vB.fromArray( positions, b * 3 );
vC.fromArray( positions, c * 3 );
uvA.fromArray( uvs, a * 2 );
uvB.fromArray( uvs, b * 2 );
uvC.fromArray( uvs, c * 2 );
var x1 = vB.x - vA.x;
var x2 = vC.x - vA.x;
var y1 = vB.y - vA.y;
var y2 = vC.y - vA.y;
var z1 = vB.z - vA.z;
var z2 = vC.z - vA.z;
var s1 = uvB.x - uvA.x;
var s2 = uvC.x - uvA.x;
var t1 = uvB.y - uvA.y;
var t2 = uvC.y - uvA.y;
var r = 1.0 / ( s1 * t2 - s2 * t1 );
sdir.set(
( t2 * x1 - t1 * x2 ) * r,
( t2 * y1 - t1 * y2 ) * r,
( t2 * z1 - t1 * z2 ) * r
);
tdir.set(
( s1 * x2 - s2 * x1 ) * r,
( s1 * y2 - s2 * y1 ) * r,
( s1 * z2 - s2 * z1 ) * r
);
tan1[ a ].add( sdir );
tan1[ b ].add( sdir );
tan1[ c ].add( sdir );
tan2[ a ].add( tdir );
tan2[ b ].add( tdir );
tan2[ c ].add( tdir );
}
var groups = geometry.groups;
if ( groups.length === 0 ) {
groups = [ {
start: 0,
count: indices.length
} ];
}
for ( var j = 0, jl = groups.length; j < jl; ++ j ) {
var group = groups[ j ];
var start = group.start;
var count = group.count;
for ( var i = start, il = start + count; i < il; i += 3 ) {
handleTriangle(
indices[ i + 0 ],
indices[ i + 1 ],
indices[ i + 2 ]
);
}
}
var tmp = new THREE.Vector3(), tmp2 = new THREE.Vector3();
var n = new THREE.Vector3(), n2 = new THREE.Vector3();
var w, t, test;
function handleVertex( v ) {
n.fromArray( normals, v * 3 );
n2.copy( n );
t = tan1[ v ];
// Gram-Schmidt orthogonalize
tmp.copy( t );
tmp.sub( n.multiplyScalar( n.dot( t ) ) ).normalize();
// Calculate handedness
tmp2.crossVectors( n2, t );
test = tmp2.dot( tan2[ v ] );
w = ( test < 0.0 ) ? - 1.0 : 1.0;
tangents[ v * 4 ] = tmp.x;
tangents[ v * 4 + 1 ] = tmp.y;
tangents[ v * 4 + 2 ] = tmp.z;
tangents[ v * 4 + 3 ] = w;
}
for ( var j = 0, jl = groups.length; j < jl; ++ j ) {
var group = groups[ j ];
var start = group.start;
var count = group.count;
for ( var i = start, il = start + count; i < il; i += 3 ) {
handleVertex( indices[ i + 0 ] );
handleVertex( indices[ i + 1 ] );
handleVertex( indices[ i + 2 ] );
}
}
}
};

407
node_modules/three/examples/js/Car.js generated vendored Normal file
View File

@@ -0,0 +1,407 @@
/**
* @author alteredq / http://alteredqualia.com/
*/
THREE.Car = function () {
var scope = this;
// car geometry manual parameters
this.modelScale = 1;
this.backWheelOffset = 2;
this.autoWheelGeometry = true;
// car geometry parameters automatically set from wheel mesh
// - assumes wheel mesh is front left wheel in proper global
// position with respect to body mesh
// - other wheels are mirrored against car root
// - if necessary back wheels can be offset manually
this.wheelOffset = new THREE.Vector3();
this.wheelDiameter = 1;
// car "feel" parameters
this.MAX_SPEED = 2200;
this.MAX_REVERSE_SPEED = - 1500;
this.MAX_WHEEL_ROTATION = 0.6;
this.FRONT_ACCELERATION = 1250;
this.BACK_ACCELERATION = 1500;
this.WHEEL_ANGULAR_ACCELERATION = 1.5;
this.FRONT_DECCELERATION = 750;
this.WHEEL_ANGULAR_DECCELERATION = 1.0;
this.STEERING_RADIUS_RATIO = 0.0023;
this.MAX_TILT_SIDES = 0.05;
this.MAX_TILT_FRONTBACK = 0.015;
// internal control variables
this.speed = 0;
this.acceleration = 0;
this.wheelOrientation = 0;
this.carOrientation = 0;
// car rigging
this.root = new THREE.Object3D();
this.frontLeftWheelRoot = new THREE.Object3D();
this.frontRightWheelRoot = new THREE.Object3D();
this.bodyMesh = null;
this.frontLeftWheelMesh = null;
this.frontRightWheelMesh = null;
this.backLeftWheelMesh = null;
this.backRightWheelMesh = null;
this.bodyGeometry = null;
this.wheelGeometry = null;
this.bodyMaterials = null;
this.wheelMaterials = null;
// internal helper variables
this.loaded = false;
this.meshes = [];
// API
this.enableShadows = function ( enable ) {
for ( var i = 0; i < this.meshes.length; i ++ ) {
this.meshes[ i ].castShadow = enable;
this.meshes[ i ].receiveShadow = enable;
}
};
this.setVisible = function ( enable ) {
for ( var i = 0; i < this.meshes.length; i ++ ) {
this.meshes[ i ].visible = enable;
this.meshes[ i ].visible = enable;
}
};
this.loadPartsJSON = function ( bodyURL, wheelURL ) {
var loader = new THREE.JSONLoader();
loader.load( bodyURL, function( geometry, materials ) {
createBody( geometry, materials )
} );
loader.load( wheelURL, function( geometry, materials ) {
createWheels( geometry, materials )
} );
};
this.loadPartsBinary = function ( bodyURL, wheelURL ) {
var loader = new THREE.BinaryLoader();
loader.load( bodyURL, function( geometry, materials ) {
createBody( geometry, materials )
} );
loader.load( wheelURL, function( geometry, materials ) {
createWheels( geometry, materials )
} );
};
this.updateCarModel = function ( delta, controls ) {
// speed and wheels based on controls
if ( controls.moveForward ) {
this.speed = THREE.Math.clamp( this.speed + delta * this.FRONT_ACCELERATION, this.MAX_REVERSE_SPEED, this.MAX_SPEED );
this.acceleration = THREE.Math.clamp( this.acceleration + delta, - 1, 1 );
}
if ( controls.moveBackward ) {
this.speed = THREE.Math.clamp( this.speed - delta * this.BACK_ACCELERATION, this.MAX_REVERSE_SPEED, this.MAX_SPEED );
this.acceleration = THREE.Math.clamp( this.acceleration - delta, - 1, 1 );
}
if ( controls.moveLeft ) {
this.wheelOrientation = THREE.Math.clamp( this.wheelOrientation + delta * this.WHEEL_ANGULAR_ACCELERATION, - this.MAX_WHEEL_ROTATION, this.MAX_WHEEL_ROTATION );
}
if ( controls.moveRight ) {
this.wheelOrientation = THREE.Math.clamp( this.wheelOrientation - delta * this.WHEEL_ANGULAR_ACCELERATION, - this.MAX_WHEEL_ROTATION, this.MAX_WHEEL_ROTATION );
}
// speed decay
if ( ! ( controls.moveForward || controls.moveBackward ) ) {
if ( this.speed > 0 ) {
var k = exponentialEaseOut( this.speed / this.MAX_SPEED );
this.speed = THREE.Math.clamp( this.speed - k * delta * this.FRONT_DECCELERATION, 0, this.MAX_SPEED );
this.acceleration = THREE.Math.clamp( this.acceleration - k * delta, 0, 1 );
} else {
var k = exponentialEaseOut( this.speed / this.MAX_REVERSE_SPEED );
this.speed = THREE.Math.clamp( this.speed + k * delta * this.BACK_ACCELERATION, this.MAX_REVERSE_SPEED, 0 );
this.acceleration = THREE.Math.clamp( this.acceleration + k * delta, - 1, 0 );
}
}
// steering decay
if ( ! ( controls.moveLeft || controls.moveRight ) ) {
if ( this.wheelOrientation > 0 ) {
this.wheelOrientation = THREE.Math.clamp( this.wheelOrientation - delta * this.WHEEL_ANGULAR_DECCELERATION, 0, this.MAX_WHEEL_ROTATION );
} else {
this.wheelOrientation = THREE.Math.clamp( this.wheelOrientation + delta * this.WHEEL_ANGULAR_DECCELERATION, - this.MAX_WHEEL_ROTATION, 0 );
}
}
// car update
var forwardDelta = this.speed * delta;
this.carOrientation += ( forwardDelta * this.STEERING_RADIUS_RATIO ) * this.wheelOrientation;
// displacement
this.root.position.x += Math.sin( this.carOrientation ) * forwardDelta;
this.root.position.z += Math.cos( this.carOrientation ) * forwardDelta;
// steering
this.root.rotation.y = this.carOrientation;
// tilt
if ( this.loaded ) {
this.bodyMesh.rotation.z = this.MAX_TILT_SIDES * this.wheelOrientation * ( this.speed / this.MAX_SPEED );
this.bodyMesh.rotation.x = - this.MAX_TILT_FRONTBACK * this.acceleration;
}
// wheels rolling
var angularSpeedRatio = 1 / ( this.modelScale * ( this.wheelDiameter / 2 ) );
var wheelDelta = forwardDelta * angularSpeedRatio;
if ( this.loaded ) {
this.frontLeftWheelMesh.rotation.x += wheelDelta;
this.frontRightWheelMesh.rotation.x += wheelDelta;
this.backLeftWheelMesh.rotation.x += wheelDelta;
this.backRightWheelMesh.rotation.x += wheelDelta;
}
// front wheels steering
this.frontLeftWheelRoot.rotation.y = this.wheelOrientation;
this.frontRightWheelRoot.rotation.y = this.wheelOrientation;
};
// internal helper methods
function createBody ( geometry, materials ) {
scope.bodyGeometry = geometry;
scope.bodyMaterials = materials;
createCar();
}
function createWheels ( geometry, materials ) {
scope.wheelGeometry = geometry;
scope.wheelMaterials = materials;
createCar();
}
function createCar () {
if ( scope.bodyGeometry && scope.wheelGeometry ) {
// compute wheel geometry parameters
if ( scope.autoWheelGeometry ) {
scope.wheelGeometry.computeBoundingBox();
var bb = scope.wheelGeometry.boundingBox;
scope.wheelOffset.addVectors( bb.min, bb.max );
scope.wheelOffset.multiplyScalar( 0.5 );
scope.wheelDiameter = bb.max.y - bb.min.y;
scope.wheelGeometry.center();
}
// rig the car
var s = scope.modelScale,
delta = new THREE.Vector3();
var bodyFaceMaterial = new THREE.MultiMaterial( scope.bodyMaterials );
var wheelFaceMaterial = new THREE.MultiMaterial( scope.wheelMaterials );
// body
scope.bodyMesh = new THREE.Mesh( scope.bodyGeometry, bodyFaceMaterial );
scope.bodyMesh.scale.set( s, s, s );
scope.root.add( scope.bodyMesh );
// front left wheel
delta.multiplyVectors( scope.wheelOffset, new THREE.Vector3( s, s, s ) );
scope.frontLeftWheelRoot.position.add( delta );
scope.frontLeftWheelMesh = new THREE.Mesh( scope.wheelGeometry, wheelFaceMaterial );
scope.frontLeftWheelMesh.scale.set( s, s, s );
scope.frontLeftWheelRoot.add( scope.frontLeftWheelMesh );
scope.root.add( scope.frontLeftWheelRoot );
// front right wheel
delta.multiplyVectors( scope.wheelOffset, new THREE.Vector3( - s, s, s ) );
scope.frontRightWheelRoot.position.add( delta );
scope.frontRightWheelMesh = new THREE.Mesh( scope.wheelGeometry, wheelFaceMaterial );
scope.frontRightWheelMesh.scale.set( s, s, s );
scope.frontRightWheelMesh.rotation.z = Math.PI;
scope.frontRightWheelRoot.add( scope.frontRightWheelMesh );
scope.root.add( scope.frontRightWheelRoot );
// back left wheel
delta.multiplyVectors( scope.wheelOffset, new THREE.Vector3( s, s, - s ) );
delta.z -= scope.backWheelOffset;
scope.backLeftWheelMesh = new THREE.Mesh( scope.wheelGeometry, wheelFaceMaterial );
scope.backLeftWheelMesh.position.add( delta );
scope.backLeftWheelMesh.scale.set( s, s, s );
scope.root.add( scope.backLeftWheelMesh );
// back right wheel
delta.multiplyVectors( scope.wheelOffset, new THREE.Vector3( - s, s, - s ) );
delta.z -= scope.backWheelOffset;
scope.backRightWheelMesh = new THREE.Mesh( scope.wheelGeometry, wheelFaceMaterial );
scope.backRightWheelMesh.position.add( delta );
scope.backRightWheelMesh.scale.set( s, s, s );
scope.backRightWheelMesh.rotation.z = Math.PI;
scope.root.add( scope.backRightWheelMesh );
// cache meshes
scope.meshes = [ scope.bodyMesh, scope.frontLeftWheelMesh, scope.frontRightWheelMesh, scope.backLeftWheelMesh, scope.backRightWheelMesh ];
// callback
scope.loaded = true;
if ( scope.callback ) {
scope.callback( scope );
}
}
}
function quadraticEaseOut( k ) {
return - k * ( k - 2 );
}
function cubicEaseOut( k ) {
return -- k * k * k + 1;
}
function circularEaseOut( k ) {
return Math.sqrt( 1 - -- k * k );
}
function sinusoidalEaseOut( k ) {
return Math.sin( k * Math.PI / 2 );
}
function exponentialEaseOut( k ) {
return k === 1 ? 1 : - Math.pow( 2, - 10 * k ) + 1;
}
};

330
node_modules/three/examples/js/Cloth.js generated vendored Normal file
View File

@@ -0,0 +1,330 @@
/*
* Cloth Simulation using a relaxed constraints solver
*/
// Suggested Readings
// Advanced Character Physics by Thomas Jakobsen Character
// http://freespace.virgin.net/hugo.elias/models/m_cloth.htm
// http://en.wikipedia.org/wiki/Cloth_modeling
// http://cg.alexandra.dk/tag/spring-mass-system/
// Real-time Cloth Animation http://www.darwin3d.com/gamedev/articles/col0599.pdf
var DAMPING = 0.03;
var DRAG = 1 - DAMPING;
var MASS = 0.1;
var restDistance = 25;
var xSegs = 10;
var ySegs = 10;
var clothFunction = plane( restDistance * xSegs, restDistance * ySegs );
var cloth = new Cloth( xSegs, ySegs );
var GRAVITY = 981 * 1.4;
var gravity = new THREE.Vector3( 0, - GRAVITY, 0 ).multiplyScalar( MASS );
var TIMESTEP = 18 / 1000;
var TIMESTEP_SQ = TIMESTEP * TIMESTEP;
var pins = [];
var wind = true;
var windStrength = 2;
var windForce = new THREE.Vector3( 0, 0, 0 );
var ballPosition = new THREE.Vector3( 0, - 45, 0 );
var ballSize = 60; //40
var tmpForce = new THREE.Vector3();
var lastTime;
function plane( width, height ) {
return function( u, v ) {
var x = ( u - 0.5 ) * width;
var y = ( v + 0.5 ) * height;
var z = 0;
return new THREE.Vector3( x, y, z );
};
}
function Particle( x, y, z, mass ) {
this.position = clothFunction( x, y ); // position
this.previous = clothFunction( x, y ); // previous
this.original = clothFunction( x, y );
this.a = new THREE.Vector3( 0, 0, 0 ); // acceleration
this.mass = mass;
this.invMass = 1 / mass;
this.tmp = new THREE.Vector3();
this.tmp2 = new THREE.Vector3();
}
// Force -> Acceleration
Particle.prototype.addForce = function( force ) {
this.a.add(
this.tmp2.copy( force ).multiplyScalar( this.invMass )
);
};
// Performs Verlet integration
Particle.prototype.integrate = function( timesq ) {
var newPos = this.tmp.subVectors( this.position, this.previous );
newPos.multiplyScalar( DRAG ).add( this.position );
newPos.add( this.a.multiplyScalar( timesq ) );
this.tmp = this.previous;
this.previous = this.position;
this.position = newPos;
this.a.set( 0, 0, 0 );
};
var diff = new THREE.Vector3();
function satisifyConstraints( p1, p2, distance ) {
diff.subVectors( p2.position, p1.position );
var currentDist = diff.length();
if ( currentDist === 0 ) return; // prevents division by 0
var correction = diff.multiplyScalar( 1 - distance / currentDist );
var correctionHalf = correction.multiplyScalar( 0.5 );
p1.position.add( correctionHalf );
p2.position.sub( correctionHalf );
}
function Cloth( w, h ) {
w = w || 10;
h = h || 10;
this.w = w;
this.h = h;
var particles = [];
var constraints = [];
var u, v;
// Create particles
for ( v = 0; v <= h; v ++ ) {
for ( u = 0; u <= w; u ++ ) {
particles.push(
new Particle( u / w, v / h, 0, MASS )
);
}
}
// Structural
for ( v = 0; v < h; v ++ ) {
for ( u = 0; u < w; u ++ ) {
constraints.push( [
particles[ index( u, v ) ],
particles[ index( u, v + 1 ) ],
restDistance
] );
constraints.push( [
particles[ index( u, v ) ],
particles[ index( u + 1, v ) ],
restDistance
] );
}
}
for ( u = w, v = 0; v < h; v ++ ) {
constraints.push( [
particles[ index( u, v ) ],
particles[ index( u, v + 1 ) ],
restDistance
] );
}
for ( v = h, u = 0; u < w; u ++ ) {
constraints.push( [
particles[ index( u, v ) ],
particles[ index( u + 1, v ) ],
restDistance
] );
}
// While many systems use shear and bend springs,
// the relaxed constraints model seems to be just fine
// using structural springs.
// Shear
// var diagonalDist = Math.sqrt(restDistance * restDistance * 2);
// for (v=0;v<h;v++) {
// for (u=0;u<w;u++) {
// constraints.push([
// particles[index(u, v)],
// particles[index(u+1, v+1)],
// diagonalDist
// ]);
// constraints.push([
// particles[index(u+1, v)],
// particles[index(u, v+1)],
// diagonalDist
// ]);
// }
// }
this.particles = particles;
this.constraints = constraints;
function index( u, v ) {
return u + v * ( w + 1 );
}
this.index = index;
}
function simulate( time ) {
if ( ! lastTime ) {
lastTime = time;
return;
}
var i, il, particles, particle, pt, constraints, constraint;
// Aerodynamics forces
if ( wind ) {
var face, faces = clothGeometry.faces, normal;
particles = cloth.particles;
for ( i = 0, il = faces.length; i < il; i ++ ) {
face = faces[ i ];
normal = face.normal;
tmpForce.copy( normal ).normalize().multiplyScalar( normal.dot( windForce ) );
particles[ face.a ].addForce( tmpForce );
particles[ face.b ].addForce( tmpForce );
particles[ face.c ].addForce( tmpForce );
}
}
for ( particles = cloth.particles, i = 0, il = particles.length; i < il; i ++ ) {
particle = particles[ i ];
particle.addForce( gravity );
particle.integrate( TIMESTEP_SQ );
}
// Start Constraints
constraints = cloth.constraints;
il = constraints.length;
for ( i = 0; i < il; i ++ ) {
constraint = constraints[ i ];
satisifyConstraints( constraint[ 0 ], constraint[ 1 ], constraint[ 2 ] );
}
// Ball Constraints
ballPosition.z = - Math.sin( Date.now() / 600 ) * 90 ; //+ 40;
ballPosition.x = Math.cos( Date.now() / 400 ) * 70;
if ( sphere.visible ) {
for ( particles = cloth.particles, i = 0, il = particles.length; i < il; i ++ ) {
particle = particles[ i ];
pos = particle.position;
diff.subVectors( pos, ballPosition );
if ( diff.length() < ballSize ) {
// collided
diff.normalize().multiplyScalar( ballSize );
pos.copy( ballPosition ).add( diff );
}
}
}
// Floor Constraints
for ( particles = cloth.particles, i = 0, il = particles.length; i < il; i ++ ) {
particle = particles[ i ];
pos = particle.position;
if ( pos.y < - 250 ) {
pos.y = - 250;
}
}
// Pin Constraints
for ( i = 0, il = pins.length; i < il; i ++ ) {
var xy = pins[ i ];
var p = particles[ xy ];
p.position.copy( p.original );
p.previous.copy( p.original );
}
}

489
node_modules/three/examples/js/ConvexObjectBreaker.js generated vendored Normal file
View File

@@ -0,0 +1,489 @@
/**
* @author yomboprime https://github.com/yomboprime
*
* @fileoverview This class can be used to subdivide a convex Geometry object into pieces.
*
* Usage:
*
* Use the function prepareBreakableObject to prepare a Mesh object to be broken.
*
* Then, call the various functions to subdivide the object (subdivideByImpact, cutByPlane)
*
* Sub-objects that are product of subdivision don't need prepareBreakableObject to be called on them.
*
* Requisites for the object:
*
* - Mesh object must have a Geometry (not BufferGeometry) and a Material
*
* - The Geometry must be convex (this is not tested in the library). You can create convex
* Geometries with THREE.ConvexGeometry. The BoxGeometry, SphereGeometry and other convex primitives
* can also be used.
*
* Note: This lib adds member variables to object's userData member and to its vertices.
* (see prepareBreakableObject function)
* Use with caution and read the code when using with other libs.
*
* @param {double} minSizeForBreak Min size a debris can have to break.
* @param {double} smallDelta Max distance to consider that a point belongs to a plane.
*
*/
THREE.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.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.tempResultObjects = { object1: null, object2: null };
this.segments = [];
var n = 30 * 30;
for ( var i = 0; i < n; i++ ) {
this.segments[ i ] = false;
}
};
THREE.ConvexObjectBreaker.prototype = {
constructor: THREE.ConvexObjectBreaker,
prepareBreakableObject: function( object, mass, velocity, angularVelocity, breakable ) {
// object is a THREE.Object3d (normally a Mesh), must have a Geometry, and it must be convex.
// Its material property is propagated to its children (sub-pieces)
// mass must be > 0
// Create vertices mark
var vertices = object.geometry.vertices;
for ( var i = 0, il = vertices.length; i < il; i++ ) {
vertices[ i ].mark = 0;
}
var 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
* @param {double} minSizeForRadialSubdivision Min size a debris can have to break in radial subdivision.
*
* Returns the array of pieces
*/
subdivideByImpact: function( object, pointOfImpact, normal, maxRadialIterations, maxRandomIterations, minSizeForRadialSubdivision ) {
var debris = [];
var tempPlane1 = this.tempPlane1;
var tempPlane2 = this.tempPlane2;
this.tempVector3.addVectors( pointOfImpact, normal );
tempPlane1.setFromCoplanarPoints( pointOfImpact, object.position, this.tempVector3 );
var maxTotalIterations = maxRandomIterations + maxRadialIterations;
var scope = this;
function subdivideRadial( subObject, startAngle, endAngle, numIterations ) {
if ( Math.random() < numIterations * 0.05 || numIterations > maxTotalIterations ) {
debris.push( subObject );
return;
}
var angle = Math.PI;
if ( numIterations === 0 ) {
tempPlane2.normal.copy( tempPlane1.normal );
tempPlane2.constant = tempPlane1.constant;
}
else {
if ( numIterations <= maxRadialIterations ) {
angle = ( endAngle - startAngle ) * ( 0.2 + 0.6 * Math.random() ) + startAngle;
// Rotate tempPlane2 at impact point around normal axis and the angle
scope.tempVector3_2.copy( object.position ).sub( pointOfImpact ).applyAxisAngle( normal, angle ).add( pointOfImpact );
tempPlane2.setFromCoplanarPoints( pointOfImpact, scope.tempVector3, scope.tempVector3_2 );
}
else {
angle = ( ( 0.5 * ( numIterations & 1 ) ) + 0.2 * ( 2 - Math.random() ) ) * Math.PI;
// Rotate tempPlane2 at object position around normal axis and the angle
scope.tempVector3_2.copy( pointOfImpact ).sub( subObject.position ).applyAxisAngle( normal, angle ).add( subObject.position );
scope.tempVector3_3.copy( normal ).add( subObject.position );
tempPlane2.setFromCoplanarPoints( subObject.position, scope.tempVector3_3, scope.tempVector3_2 );
}
}
// Perform the cut
scope.cutByPlane( subObject, tempPlane2, scope.tempResultObjects );
var obj1 = scope.tempResultObjects.object1;
var obj2 = scope.tempResultObjects.object2;
if ( obj1 ) {
subdivideRadial( obj1, startAngle, angle, numIterations + 1 );
}
if ( obj2 ) {
subdivideRadial( obj2, angle, endAngle, numIterations + 1 );
}
}
subdivideRadial( object, 0, 2 * Math.PI, 0 );
return debris;
},
cutByPlane: function( 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 points = geometry.vertices;
var faces = geometry.faces;
var numPoints = points.length;
var points1 = [];
var points2 = [];
var delta = this.smallDelta;
// Reset vertices mark
for ( var i = 0; i < numPoints; i++ ) {
points[ i ].mark = 0;
}
// Reset segments mark
var numPointPairs = numPoints * numPoints;
for ( var i = 0; i < numPointPairs; i++ ) {
this.segments[ i ] = false;
}
// Iterate through the faces to mark edges shared by coplanar faces
for ( var i = 0, il = faces.length - 1; i < il; i++ ) {
var face1 = faces[ i ];
for ( var j = i + 1, jl = faces.length; j < jl; j++ ) {
var face2 = faces[ j ];
var coplanar = 1 - face1.normal.dot( face2.normal ) < delta;
if ( coplanar ) {
var a1 = face1.a;
var b1 = face1.b;
var c1 = face1.c;
var a2 = face2.a;
var b2 = face2.b;
var c2 = face2.c;
if ( a1 === a2 || a1 === b2 || a1 === c2 ) {
if ( b1 === a2 || b1 === b2 || b1 === c2 ) {
this.segments[ a1 * numPoints + b1 ] = true;
this.segments[ b1 * numPoints + a1 ] = true;
}
else {
this.segments[ c1 * numPoints + a1 ] = true;
this.segments[ a1 * numPoints + c1 ] = true;
}
}
else if ( b1 === a2 || b1 === b2 || b1 === c2 ) {
this.segments[ c1 * numPoints + b1 ] = true;
this.segments[ b1 * numPoints + c1 ] = true;
}
}
}
}
// Transform the plane to object local space
var localPlane = this.tempPlane1;
object.updateMatrix();
THREE.ConvexObjectBreaker.transformPlaneToLocalSpace( plane, object.matrix, localPlane );
// Iterate through the faces adding points to both pieces
for ( var i = 0, il = faces.length; i < il; i ++ ) {
var face = faces[ i ];
for ( var segment = 0; segment < 3; segment++ ) {
var i0 = segment === 0 ? face.a : ( segment === 1 ? face.b : face.c );
var i1 = segment === 0 ? face.b : ( segment === 1 ? face.c : face.a );
var segmentState = this.segments[ i0 * numPoints + i1 ];
if ( segmentState ) {
// The segment already has been processed in another face
continue;
}
// Mark segment as processed (also inverted segment)
this.segments[ i0 * numPoints + i1 ] = true;
this.segments[ i1 * numPoints + i0 ] = true;
var p0 = points[ i0 ];
var p1 = points[ i1 ];
if ( p0.mark === 0 ) {
var d = localPlane.distanceToPoint( p0 );
// mark: 1 for negative side, 2 for positive side, 3 for coplanar point
if ( d > delta ) {
p0.mark = 2;
points2.push( p0 );
}
else if ( d < - delta ) {
p0.mark = 1;
points1.push( p0 );
}
else {
p0.mark = 3;
points1.push( p0 );
var p0_2 = p0.clone();
p0_2.mark = 3;
points2.push( p0_2 );
}
}
if ( p1.mark === 0 ) {
var d = localPlane.distanceToPoint( p1 );
// mark: 1 for negative side, 2 for positive side, 3 for coplanar point
if ( d > delta ) {
p1.mark = 2;
points2.push( p1 );
}
else if ( d < - delta ) {
p1.mark = 1;
points1.push( p1 );
}
else {
p1.mark = 3;
points1.push( p1 );
var p1_2 = p1.clone();
p1_2.mark = 3;
points2.push( p1_2 );
}
}
var mark0 = p0.mark;
var mark1 = p1.mark;
if ( ( mark0 === 1 && mark1 === 2 ) || ( mark0 === 2 && mark1 === 1 ) ) {
// Intersection of segment with the plane
this.tempLine1.start.copy( p0 );
this.tempLine1.end.copy( p1 );
var intersection = localPlane.intersectLine( this.tempLine1 );
if ( intersection === undefined ) {
// Shouldn't happen
console.error( "Internal error: segment does not intersect plane." );
output.segmentedObject1 = null;
output.segmentedObject2 = null;
return 0;
}
intersection.mark = 1;
points1.push( intersection );
var intersection_2 = intersection.clone();
intersection_2.mark = 2;
points2.push( intersection_2 );
}
}
}
// Calculate debris mass (very fast and imprecise):
var 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;
if ( numPoints1 > 0 ) {
for ( var i = 0; i < numPoints1; i++ ) {
this.tempCM1.add( points1[ i ] );
}
this.tempCM1.divideScalar( numPoints1 );
for ( var i = 0; i < numPoints1; i++ ) {
var p = points1[ i ];
p.sub( this.tempCM1 );
radius1 = Math.max( radius1, p.x, p.y, p.z );
}
this.tempCM1.add( object.position );
}
this.tempCM2.set( 0, 0, 0 );
var radius2 = 0;
var numPoints2 = points2.length;
if ( numPoints2 > 0 ) {
for ( var i = 0; i < numPoints2; i++ ) {
this.tempCM2.add( points2[ i ] );
}
this.tempCM2.divideScalar( numPoints2 );
for ( var i = 0; i < numPoints2; i++ ) {
var p = points2[ i ];
p.sub( this.tempCM2 );
radius2 = Math.max( radius2, p.x, p.y, p.z );
}
this.tempCM2.add( object.position );
}
var object1 = null;
var object2 = null;
var numObjects = 0;
if ( numPoints1 > 4 ) {
object1 = new THREE.Mesh( new THREE.ConvexGeometry( points1 ), object.material );
object1.position.copy( this.tempCM1 );
object1.quaternion.copy( object.quaternion );
this.prepareBreakableObject( object1, newMass, object.userData.velocity, object.userData.angularVelocity, 2 * radius1 > this.minSizeForBreak );
numObjects++;
}
if ( numPoints2 > 4 ) {
object2 = new THREE.Mesh( new THREE.ConvexGeometry( points2 ), object.material );
object2.position.copy( this.tempCM2 );
object2.quaternion.copy( object.quaternion );
this.prepareBreakableObject( object2, newMass, object.userData.velocity, object.userData.angularVelocity, 2 * radius2 > this.minSizeForBreak );
numObjects++;
}
output.object1 = object1;
output.object2 = object2;
return numObjects;
}
};
THREE.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;
};
THREE.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;
};
THREE.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;
};
THREE.ConvexObjectBreaker.transformPlaneToLocalSpace = function() {
var v1 = new THREE.Vector3();
var m1 = new THREE.Matrix3();
return function transformPlaneToLocalSpace( plane, m, resultPlane ) {
resultPlane.normal.copy( plane.normal );
resultPlane.constant = plane.constant;
var referencePoint = THREE.ConvexObjectBreaker.transformTiedVectorInverse( plane.coplanarPoint( v1 ), m );
THREE.ConvexObjectBreaker.transformFreeVectorInverse( resultPlane.normal, m );
// recalculate constant (like in setFromNormalAndCoplanarPoint)
resultPlane.constant = - referencePoint.dot( resultPlane.normal );
};
}();

363
node_modules/three/examples/js/CurveExtras.js generated vendored Normal file
View File

@@ -0,0 +1,363 @@
/*
* A bunch of parametric curves
* @author zz85
*
* Formulas collected from various sources
* http://mathworld.wolfram.com/HeartCurve.html
* http://mathdl.maa.org/images/upload_library/23/stemkoski/knots/page6.html
* http://en.wikipedia.org/wiki/Viviani%27s_curve
* http://mathdl.maa.org/images/upload_library/23/stemkoski/knots/page4.html
* http://www.mi.sanu.ac.rs/vismath/taylorapril2011/Taylor.pdf
* http://prideout.net/blog/?p=44
*/
( function( Curves ) {
// GrannyKnot
function GrannyKnot() {}
GrannyKnot.prototype = Object.create( THREE.Curve.prototype );
GrannyKnot.prototype.constructor = GrannyKnot;
GrannyKnot.prototype.getPoint = function( t ) {
t = 2 * Math.PI * t;
var x = - 0.22 * Math.cos( t ) - 1.28 * Math.sin( t ) - 0.44 * Math.cos( 3 * t ) - 0.78 * Math.sin( 3 * t );
var y = - 0.1 * Math.cos( 2 * t ) - 0.27 * Math.sin( 2 * t ) + 0.38 * Math.cos( 4 * t ) + 0.46 * Math.sin( 4 * t );
var z = 0.7 * Math.cos( 3 * t ) - 0.4 * Math.sin( 3 * t );
return new THREE.Vector3( x, y, z ).multiplyScalar( 20 );
};
// HeartCurve
function HeartCurve( s ) {
this.scale = ( s === undefined ) ? 5 : s;
}
HeartCurve.prototype = Object.create( THREE.Curve.prototype );
HeartCurve.prototype.constructor = HeartCurve;
HeartCurve.prototype.getPoint = function( t ) {
t *= 2 * Math.PI;
var x = 16 * Math.pow( Math.sin( t ), 3 );
var y = 13 * Math.cos( t ) - 5 * Math.cos( 2 * t ) - 2 * Math.cos( 3 * t ) - Math.cos( 4 * t );
var z = 0;
return new THREE.Vector3( x, y, z ).multiplyScalar( this.scale );
};
// Viviani's Curve
function VivianiCurve( radius ) {
this.radius = radius;
}
VivianiCurve.prototype = Object.create( THREE.Curve.prototype );
VivianiCurve.prototype.constructor = VivianiCurve;
VivianiCurve.prototype.getPoint = function( t ) {
t = t * 4 * Math.PI; // normalized to 0..1
var a = this.radius / 2;
var x = a * ( 1 + Math.cos( t ) );
var y = a * Math.sin( t );
var z = 2 * a * Math.sin( t / 2 );
return new THREE.Vector3( x, y, z );
};
// KnotCurve
function KnotCurve() {}
KnotCurve.prototype = Object.create( THREE.Curve.prototype );
KnotCurve.prototype.constructor = KnotCurve;
KnotCurve.prototype.getPoint = function( t ) {
t *= 2 * Math.PI;
var R = 10;
var s = 50;
var x = s * Math.sin( t );
var y = Math.cos( t ) * ( R + s * Math.cos( t ) );
var z = Math.sin( t ) * ( R + s * Math.cos( t ) );
return new THREE.Vector3( x, y, z );
};
// HelixCurve
function HelixCurve() {}
HelixCurve.prototype = Object.create( THREE.Curve.prototype );
HelixCurve.prototype.constructor = HelixCurve;
HelixCurve.prototype.getPoint = function( t ) {
var a = 30; // radius
var b = 150; // height
var t2 = 2 * Math.PI * t * b / 30;
var x = Math.cos( t2 ) * a;
var y = Math.sin( t2 ) * a;
var z = b * t;
return new THREE.Vector3( x, y, z );
};
// TrefoilKnot
function TrefoilKnot( s ) {
this.scale = ( s === undefined ) ? 10 : s;
}
TrefoilKnot.prototype = Object.create( THREE.Curve.prototype );
TrefoilKnot.prototype.constructor = TrefoilKnot;
TrefoilKnot.prototype.getPoint = function( t ) {
t *= Math.PI * 2;
var x = ( 2 + Math.cos( 3 * t ) ) * Math.cos( 2 * t );
var y = ( 2 + Math.cos( 3 * t ) ) * Math.sin( 2 * t );
var z = Math.sin( 3 * t );
return new THREE.Vector3( x, y, z ).multiplyScalar( this.scale );
};
// TorusKnot
function TorusKnot( s ) {
this.scale = ( s === undefined ) ? 10 : s;
}
TorusKnot.prototype = Object.create( THREE.Curve.prototype );
TorusKnot.prototype.constructor = TorusKnot;
TorusKnot.prototype.getPoint = function( t ) {
var p = 3;
var q = 4;
t *= Math.PI * 2;
var x = ( 2 + Math.cos( q * t ) ) * Math.cos( p * t );
var y = ( 2 + Math.cos( q * t ) ) * Math.sin( p * t );
var z = Math.sin( q * t );
return new THREE.Vector3( x, y, z ).multiplyScalar( this.scale );
};
// CinquefoilKnot
function CinquefoilKnot( s ) {
this.scale = ( s === undefined ) ? 10 : s;
}
CinquefoilKnot.prototype = Object.create( THREE.Curve.prototype );
CinquefoilKnot.prototype.constructor = CinquefoilKnot;
CinquefoilKnot.prototype.getPoint = function( t ) {
var p = 2;
var q = 5;
t *= Math.PI * 2;
var x = ( 2 + Math.cos( q * t ) ) * Math.cos( p * t );
var y = ( 2 + Math.cos( q * t ) ) * Math.sin( p * t );
var z = Math.sin( q * t );
return new THREE.Vector3( x, y, z ).multiplyScalar( this.scale );
};
// TrefoilPolynomialKnot
function TrefoilPolynomialKnot( s ) {
this.scale = ( s === undefined ) ? 10 : s;
}
TrefoilPolynomialKnot.prototype = Object.create( THREE.Curve.prototype );
TrefoilPolynomialKnot.prototype.constructor = TrefoilPolynomialKnot;
TrefoilPolynomialKnot.prototype.getPoint = function( t ) {
t = t * 4 - 2;
var x = Math.pow( t, 3 ) - 3 * t;
var y = Math.pow( t, 4 ) - 4 * t * t;
var z = 1 / 5 * Math.pow( t, 5 ) - 2 * t;
return new THREE.Vector3( x, y, z ).multiplyScalar( this.scale );
};
var scaleTo = function( x, y, t ) {
var r = y - x;
return t * r + x;
};
// FigureEightPolynomialKnot
function FigureEightPolynomialKnot( s ) {
this.scale = ( s === undefined ) ? 1 : s;
}
FigureEightPolynomialKnot.prototype = Object.create( THREE.Curve.prototype );
FigureEightPolynomialKnot.prototype.constructor = FigureEightPolynomialKnot;
FigureEightPolynomialKnot.prototype.getPoint = function( t ) {
t = scaleTo( - 4, 4, t );
var x = 2 / 5 * t * ( t * t - 7 ) * ( t * t - 10 );
var y = Math.pow( t, 4 ) - 13 * t * t;
var z = 1 / 10 * t * ( t * t - 4 ) * ( t * t - 9 ) * ( t * t - 12 );
return new THREE.Vector3( x, y, z ).multiplyScalar( this.scale );
};
// DecoratedTorusKnot4a
function DecoratedTorusKnot4a( s ) {
this.scale = ( s === undefined ) ? 40 : s;
}
DecoratedTorusKnot4a.prototype = Object.create( THREE.Curve.prototype );
DecoratedTorusKnot4a.prototype.constructor = DecoratedTorusKnot4a;
DecoratedTorusKnot4a.prototype.getPoint = function( t ) {
t *= Math.PI * 2;
var x = Math.cos( 2 * t ) * ( 1 + 0.6 * ( Math.cos( 5 * t ) + 0.75 * Math.cos( 10 * t ) ) );
var y = Math.sin( 2 * t ) * ( 1 + 0.6 * ( Math.cos( 5 * t ) + 0.75 * Math.cos( 10 * t ) ) );
var z = 0.35 * Math.sin( 5 * t );
return new THREE.Vector3( x, y, z ).multiplyScalar( this.scale );
};
// DecoratedTorusKnot4b
function DecoratedTorusKnot4b( s ) {
this.scale = ( s === undefined ) ? 40 : s;
}
DecoratedTorusKnot4b.prototype = Object.create( THREE.Curve.prototype );
DecoratedTorusKnot4b.prototype.constructor = DecoratedTorusKnot4b;
DecoratedTorusKnot4b.prototype.getPoint = function( t ) {
var fi = t * Math.PI * 2;
var x = Math.cos( 2 * fi ) * ( 1 + 0.45 * Math.cos( 3 * fi ) + 0.4 * Math.cos( 9 * fi ) );
var y = Math.sin( 2 * fi ) * ( 1 + 0.45 * Math.cos( 3 * fi ) + 0.4 * Math.cos( 9 * fi ) );
var z = 0.2 * Math.sin( 9 * fi );
return new THREE.Vector3( x, y, z ).multiplyScalar( this.scale );
};
// DecoratedTorusKnot5a
function DecoratedTorusKnot5a( s ) {
this.scale = ( s === undefined ) ? 40 : s;
}
DecoratedTorusKnot5a.prototype = Object.create( THREE.Curve.prototype );
DecoratedTorusKnot5a.prototype.constructor = DecoratedTorusKnot5a;
DecoratedTorusKnot5a.prototype.getPoint = function( t ) {
var fi = t * Math.PI * 2;
var x = Math.cos( 3 * fi ) * ( 1 + 0.3 * Math.cos( 5 * fi ) + 0.5 * Math.cos( 10 * fi ) );
var y = Math.sin( 3 * fi ) * ( 1 + 0.3 * Math.cos( 5 * fi ) + 0.5 * Math.cos( 10 * fi ) );
var z = 0.2 * Math.sin( 20 * fi );
return new THREE.Vector3( x, y, z ).multiplyScalar( this.scale );
};
// DecoratedTorusKnot5c
function DecoratedTorusKnot5c( s ) {
this.scale = ( s === undefined ) ? 40 : s;
}
DecoratedTorusKnot5c.prototype = Object.create( THREE.Curve.prototype );
DecoratedTorusKnot5c.prototype.constructor = DecoratedTorusKnot5c;
DecoratedTorusKnot5c.prototype.getPoint = function( t ) {
var fi = t * Math.PI * 2;
var x = Math.cos( 4 * fi ) * ( 1 + 0.5 * ( Math.cos( 5 * fi ) + 0.4 * Math.cos( 20 * fi ) ) );
var y = Math.sin( 4 * fi ) * ( 1 + 0.5 * ( Math.cos( 5 * fi ) + 0.4 * Math.cos( 20 * fi ) ) );
var z = 0.35 * Math.sin( 15 * fi );
return new THREE.Vector3( x, y, z ).multiplyScalar( this.scale );
};
// export
Curves.GrannyKnot = GrannyKnot;
Curves.HeartCurve = HeartCurve;
Curves.VivianiCurve = VivianiCurve;
Curves.KnotCurve = KnotCurve;
Curves.HelixCurve = HelixCurve;
Curves.TrefoilKnot = TrefoilKnot;
Curves.TorusKnot = TorusKnot;
Curves.CinquefoilKnot = CinquefoilKnot;
Curves.TrefoilPolynomialKnot = TrefoilPolynomialKnot;
Curves.FigureEightPolynomialKnot = FigureEightPolynomialKnot;
Curves.DecoratedTorusKnot4a = DecoratedTorusKnot4a;
Curves.DecoratedTorusKnot4b = DecoratedTorusKnot4b;
Curves.DecoratedTorusKnot5a = DecoratedTorusKnot5a;
Curves.DecoratedTorusKnot5c = DecoratedTorusKnot5c;
} ) ( THREE.Curves = THREE.Curves || {} );

78
node_modules/three/examples/js/Detector.js generated vendored Normal file
View File

@@ -0,0 +1,78 @@
/**
* @author alteredq / http://alteredqualia.com/
* @author mr.doob / http://mrdoob.com/
*/
var Detector = {
canvas: !! window.CanvasRenderingContext2D,
webgl: ( function () {
try {
var canvas = document.createElement( 'canvas' ); return !! ( window.WebGLRenderingContext && ( canvas.getContext( 'webgl' ) || canvas.getContext( 'experimental-webgl' ) ) );
} catch ( e ) {
return false;
}
} )(),
workers: !! window.Worker,
fileapi: window.File && window.FileReader && window.FileList && window.Blob,
getWebGLErrorMessage: function () {
var element = document.createElement( 'div' );
element.id = 'webgl-error-message';
element.style.fontFamily = 'monospace';
element.style.fontSize = '13px';
element.style.fontWeight = 'normal';
element.style.textAlign = 'center';
element.style.background = '#fff';
element.style.color = '#000';
element.style.padding = '1.5em';
element.style.width = '400px';
element.style.margin = '5em auto 0';
if ( ! this.webgl ) {
element.innerHTML = window.WebGLRenderingContext ? [
'Your graphics card does not seem to support <a href="http://khronos.org/webgl/wiki/Getting_a_WebGL_Implementation" style="color:#000">WebGL</a>.<br />',
'Find out how to get it <a href="http://get.webgl.org/" style="color:#000">here</a>.'
].join( '\n' ) : [
'Your browser does not seem to support <a href="http://khronos.org/webgl/wiki/Getting_a_WebGL_Implementation" style="color:#000">WebGL</a>.<br/>',
'Find out how to get it <a href="http://get.webgl.org/" style="color:#000">here</a>.'
].join( '\n' );
}
return element;
},
addGetWebGLMessage: function ( parameters ) {
var parent, id, element;
parameters = parameters || {};
parent = parameters.parent !== undefined ? parameters.parent : document.body;
id = parameters.id !== undefined ? parameters.id : 'oldie';
element = Detector.getWebGLErrorMessage();
element.id = id;
parent.appendChild( element );
}
};
// browserify support
if ( typeof module === 'object' ) {
module.exports = Detector;
}

View File

@@ -0,0 +1,370 @@
/**
* @author yomboprime https://github.com/yomboprime
*
* GPUComputationRenderer, based on SimulationRenderer by zz85
*
* The GPUComputationRenderer uses the concept of variables. These variables are RGBA float textures that hold 4 floats
* for each compute element (texel)
*
* Each variable has a fragment shader that defines the computation made to obtain the variable in question.
* You can use as many variables you need, and make dependencies so you can use textures of other variables in the shader
* (the sampler uniforms are added automatically) Most of the variables will need themselves as dependency.
*
* The renderer has actually two render targets per variable, to make ping-pong. Textures from the current frame are used
* as inputs to render the textures of the next frame.
*
* The render targets of the variables can be used as input textures for your visualization shaders.
*
* Variable names should be valid identifiers and should not collide with THREE GLSL used identifiers.
* a common approach could be to use 'texture' prefixing the variable name; i.e texturePosition, textureVelocity...
*
* The size of the computation (sizeX * sizeY) is defined as 'resolution' automatically in the shader. For example:
* #DEFINE resolution vec2( 1024.0, 1024.0 )
*
* -------------
*
* Basic use:
*
* // Initialization...
*
* // Create computation renderer
* var gpuCompute = new GPUComputationRenderer( 1024, 1024, renderer );
*
* // Create initial state float textures
* var pos0 = gpuCompute.createTexture();
* var 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 );
*
* // Add variable dependencies
* gpuCompute.setVariableDependencies( velVar, [ velVar, posVar ] );
* gpuCompute.setVariableDependencies( posVar, [ velVar, posVar ] );
*
* // Add custom uniforms
* velVar.material.uniforms.time = { value: 0.0 };
*
* // Check for completeness
* var error = gpuCompute.init();
* if ( error !== null ) {
* console.error( error );
* }
*
*
* // In each frame...
*
* // Compute!
* gpuCompute.compute();
*
* // Update texture uniforms in your visualization materials with the gpu renderer output
* myMaterial.uniforms.myTexture.value = gpuCompute.getCurrentRenderTarget( posVar ).texture;
*
* // Do your rendering
* renderer.render( myScene, myCamera );
*
* -------------
*
* 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 } } );
*
* var inputTexture = gpuCompute.createTexture();
*
* // Fill in here inputTexture...
*
* myFilter1.uniforms.theTexture.value = inputTexture;
*
* var myRenderTarget = gpuCompute.createRenderTarget();
* myFilter2.uniforms.theTexture.value = myRenderTarget.texture;
*
* var outputRenderTarget = gpuCompute.createRenderTarget();
*
* // Now use the output texture where you want:
* myMaterial.uniforms.map.value = outputRenderTarget.texture;
*
* // And compute each frame, before rendering to screen:
* gpuCompute.doRenderTarget( myFilter1, myRenderTarget );
* gpuCompute.doRenderTarget( myFilter2, outputRenderTarget );
*
*
*
* @param {int} sizeX Computation problem size is always 2d: sizeX * sizeY elements.
* @param {int} sizeY Computation problem size is always 2d: sizeX * sizeY elements.
* @param {WebGLRenderer} renderer The renderer
*/
function GPUComputationRenderer( sizeX, sizeY, renderer ) {
this.variables = [];
this.currentTextureIndex = 0;
var scene = new THREE.Scene();
var camera = new THREE.Camera();
camera.position.z = 1;
var passThruUniforms = {
texture: { value: null }
};
var passThruShader = createShaderMaterial( getPassThroughFragmentShader(), passThruUniforms );
var mesh = new THREE.Mesh( new THREE.PlaneBufferGeometry( 2, 2 ), passThruShader );
scene.add( mesh );
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
};
this.variables.push( variable );
return variable;
};
this.setVariableDependencies = function( variable, dependencies ) {
variable.dependencies = dependencies;
};
this.init = function() {
if ( ! renderer.extensions.get( "OES_texture_float" ) ) {
return "No OES_texture_float support for float textures.";
}
if ( renderer.capabilities.maxVertexTextures === 0 ) {
return "No support for vertex shader textures.";
}
for ( var i = 0; i < this.variables.length; i++ ) {
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 ShaderMaterial
var material = variable.material;
var uniforms = material.uniforms;
if ( variable.dependencies !== null ) {
for ( var d = 0; d < variable.dependencies.length; d++ ) {
var depVar = variable.dependencies[ d ];
if ( depVar.name !== variable.name ) {
// Checks if variable exists
var found = false;
for ( var j = 0; j < this.variables.length; j++ ) {
if ( depVar.name === this.variables[ j ].name ) {
found = true;
break;
}
}
if ( ! found ) {
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;
}
}
}
this.currentTextureIndex = 0;
return null;
};
this.compute = function() {
var currentTextureIndex = this.currentTextureIndex;
var nextTextureIndex = this.currentTextureIndex === 0 ? 1 : 0;
for ( var i = 0, il = this.variables.length; i < il; i++ ) {
var variable = this.variables[ i ];
// Sets texture dependencies uniforms
if ( variable.dependencies !== null ) {
var uniforms = variable.material.uniforms;
for ( var d = 0, dl = variable.dependencies.length; d < dl; d++ ) {
var depVar = variable.dependencies[ d ];
uniforms[ depVar.name ].value = depVar.renderTargets[ currentTextureIndex ].texture;
}
}
// Performs the computation for this variable
this.doRenderTarget( variable.material, variable.renderTargets[ nextTextureIndex ] );
}
this.currentTextureIndex = nextTextureIndex;
};
this.getCurrentRenderTarget = function( variable ) {
return variable.renderTargets[ this.currentTextureIndex ];
};
this.getAlternateRenderTarget = function( variable ) {
return variable.renderTargets[ this.currentTextureIndex === 0 ? 1 : 0 ];
};
function addResolutionDefine( materialShader ) {
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 ) {
uniforms = uniforms || {};
var 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 ) {
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: ( /(iPad|iPhone|iPod)/g.test( navigator.userAgent ) ) ? THREE.HalfFloatType : THREE.FloatType,
stencilBuffer: false
} );
return renderTarget;
};
this.createTexture = function( sizeXTexture, sizeYTexture ) {
sizeXTexture = sizeXTexture || sizeX;
sizeYTexture = sizeYTexture || sizeY;
var a = new Float32Array( sizeXTexture * sizeYTexture * 4 );
var texture = new THREE.DataTexture( a, sizeX, sizeY, THREE.RGBAFormat, THREE.FloatType );
texture.needsUpdate = true;
return texture;
};
this.renderTexture = function( input, output ) {
// Takes a texture, and render out in rendertarget
// input = Texture
// output = RenderTarget
passThruUniforms.texture.value = input;
this.doRenderTarget( passThruShader, output);
passThruUniforms.texture.value = null;
};
this.doRenderTarget = function( material, output ) {
mesh.material = material;
renderer.render( scene, camera, output );
mesh.material = passThruShader;
};
// Shaders
function getPassThroughVertexShader() {
return "void main() {\n" +
"\n" +
" gl_Position = vec4( position, 1.0 );\n" +
"\n" +
"}\n";
}
function getPassThroughFragmentShader() {
return "uniform sampler2D texture;\n" +
"\n" +
"void main() {\n" +
"\n" +
" vec2 uv = gl_FragCoord.xy / resolution.xy;\n" +
"\n" +
" gl_FragColor = texture2D( texture, uv );\n" +
"\n" +
"}\n";
}
}

508
node_modules/three/examples/js/GPUParticleSystem.js generated vendored Normal file
View File

@@ -0,0 +1,508 @@
/*
* GPU Particle System
* @author flimshaw - Charlie Hoey - http://charliehoey.com
*
* A simple to use, general purpose GPU system. Particles are spawn-and-forget with
* several options available, and do not require monitoring or cleanup after spawning.
* Because the paths of all particles are completely deterministic once spawned, the scale
* and direction of time is also variable.
*
* Currently uses a static wrapping perlin noise texture for turbulence, and a small png texture for
* particles, but adding support for a particle texture atlas or changing to a different type of turbulence
* would be a fairly light day's work.
*
* Shader and javascript packing code derrived from several Stack Overflow examples.
*
*/
THREE.GPUParticleSystem = function(options) {
var self = this;
var options = options || {};
// parse options and use defaults
self.PARTICLE_COUNT = options.maxParticles || 1000000;
self.PARTICLE_CONTAINERS = options.containerCount || 1;
self.PARTICLE_NOISE_TEXTURE = options.particleNoiseTex || null;
self.PARTICLE_SPRITE_TEXTURE = options.particleSpriteTex || null;
self.PARTICLES_PER_CONTAINER = Math.ceil(self.PARTICLE_COUNT / self.PARTICLE_CONTAINERS);
self.PARTICLE_CURSOR = 0;
self.time = 0;
// Custom vertex and fragement shader
var GPUParticleShader = {
vertexShader: [
'precision highp float;',
'const vec4 bitSh = vec4(256. * 256. * 256., 256. * 256., 256., 1.);',
'const vec4 bitMsk = vec4(0.,vec3(1./256.0));',
'const vec4 bitShifts = vec4(1.) / bitSh;',
'#define FLOAT_MAX 1.70141184e38',
'#define FLOAT_MIN 1.17549435e-38',
'lowp vec4 encode_float(highp float v) {',
'highp float av = abs(v);',
'//Handle special cases',
'if(av < FLOAT_MIN) {',
'return vec4(0.0, 0.0, 0.0, 0.0);',
'} else if(v > FLOAT_MAX) {',
'return vec4(127.0, 128.0, 0.0, 0.0) / 255.0;',
'} else if(v < -FLOAT_MAX) {',
'return vec4(255.0, 128.0, 0.0, 0.0) / 255.0;',
'}',
'highp vec4 c = vec4(0,0,0,0);',
'//Compute exponent and mantissa',
'highp float e = floor(log2(av));',
'highp float m = av * pow(2.0, -e) - 1.0;',
//Unpack mantissa
'c[1] = floor(128.0 * m);',
'm -= c[1] / 128.0;',
'c[2] = floor(32768.0 * m);',
'm -= c[2] / 32768.0;',
'c[3] = floor(8388608.0 * m);',
'//Unpack exponent',
'highp float ebias = e + 127.0;',
'c[0] = floor(ebias / 2.0);',
'ebias -= c[0] * 2.0;',
'c[1] += floor(ebias) * 128.0;',
'//Unpack sign bit',
'c[0] += 128.0 * step(0.0, -v);',
'//Scale back to range',
'return c / 255.0;',
'}',
'vec4 pack(const in float depth)',
'{',
'const vec4 bit_shift = vec4(256.0*256.0*256.0, 256.0*256.0, 256.0, 1.0);',
'const vec4 bit_mask = vec4(0.0, 1.0/256.0, 1.0/256.0, 1.0/256.0);',
'vec4 res = mod(depth*bit_shift*vec4(255), vec4(256))/vec4(255);',
'res -= res.xxyz * bit_mask;',
'return res;',
'}',
'float unpack(const in vec4 rgba_depth)',
'{',
'const vec4 bit_shift = vec4(1.0/(256.0*256.0*256.0), 1.0/(256.0*256.0), 1.0/256.0, 1.0);',
'float depth = dot(rgba_depth, bit_shift);',
'return depth;',
'}',
'uniform float uTime;',
'uniform float uScale;',
'uniform sampler2D tNoise;',
'attribute vec4 particlePositionsStartTime;',
'attribute vec4 particleVelColSizeLife;',
'varying vec4 vColor;',
'varying float lifeLeft;',
'void main() {',
'// unpack things from our attributes',
'vColor = encode_float( particleVelColSizeLife.y );',
'// convert our velocity back into a value we can use',
'vec4 velTurb = encode_float( particleVelColSizeLife.x );',
'vec3 velocity = vec3( velTurb.xyz );',
'float turbulence = velTurb.w;',
'vec3 newPosition;',
'float timeElapsed = uTime - particlePositionsStartTime.a;',
'lifeLeft = 1. - (timeElapsed / particleVelColSizeLife.w);',
'gl_PointSize = ( uScale * particleVelColSizeLife.z ) * lifeLeft;',
'velocity.x = ( velocity.x - .5 ) * 3.;',
'velocity.y = ( velocity.y - .5 ) * 3.;',
'velocity.z = ( velocity.z - .5 ) * 3.;',
'newPosition = particlePositionsStartTime.xyz + ( velocity * 10. ) * ( uTime - particlePositionsStartTime.a );',
'vec3 noise = texture2D( tNoise, vec2( newPosition.x * .015 + (uTime * .05), newPosition.y * .02 + (uTime * .015) )).rgb;',
'vec3 noiseVel = ( noise.rgb - .5 ) * 30.;',
'newPosition = mix(newPosition, newPosition + vec3(noiseVel * ( turbulence * 5. ) ), (timeElapsed / particleVelColSizeLife.a) );',
'if( velocity.y > 0. && velocity.y < .05 ) {',
'lifeLeft = 0.;',
'}',
'if( velocity.x < -1.45 ) {',
'lifeLeft = 0.;',
'}',
'if( timeElapsed > 0. ) {',
'gl_Position = projectionMatrix * modelViewMatrix * vec4( newPosition, 1.0 );',
'} else {',
'gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );',
'lifeLeft = 0.;',
'gl_PointSize = 0.;',
'}',
'}'
].join("\n"),
fragmentShader: [
'float scaleLinear(float value, vec2 valueDomain) {',
'return (value - valueDomain.x) / (valueDomain.y - valueDomain.x);',
'}',
'float scaleLinear(float value, vec2 valueDomain, vec2 valueRange) {',
'return mix(valueRange.x, valueRange.y, scaleLinear(value, valueDomain));',
'}',
'varying vec4 vColor;',
'varying float lifeLeft;',
'uniform sampler2D tSprite;',
'void main() {',
'float alpha = 0.;',
'if( lifeLeft > .995 ) {',
'alpha = scaleLinear( lifeLeft, vec2(1., .995), vec2(0., 1.));//mix( 0., 1., ( lifeLeft - .95 ) * 100. ) * .75;',
'} else {',
'alpha = lifeLeft * .75;',
'}',
'vec4 tex = texture2D( tSprite, gl_PointCoord );',
'gl_FragColor = vec4( vColor.rgb * tex.a, alpha * tex.a );',
'}'
].join("\n")
};
// preload a million random numbers
self.rand = [];
for (var i = 1e5; i > 0; i--) {
self.rand.push(Math.random() - .5);
}
self.random = function() {
return ++i >= self.rand.length ? self.rand[i = 1] : self.rand[i];
};
var textureLoader = new THREE.TextureLoader();
self.particleNoiseTex = self.PARTICLE_NOISE_TEXTURE || textureLoader.load("textures/perlin-512.png");
self.particleNoiseTex.wrapS = self.particleNoiseTex.wrapT = THREE.RepeatWrapping;
self.particleSpriteTex = self.PARTICLE_SPRITE_TEXTURE || textureLoader.load("textures/particle2.png");
self.particleSpriteTex.wrapS = self.particleSpriteTex.wrapT = THREE.RepeatWrapping;
self.particleShaderMat = new THREE.ShaderMaterial({
transparent: true,
depthWrite: false,
uniforms: {
"uTime": {
value: 0.0
},
"uScale": {
value: 1.0
},
"tNoise": {
value: self.particleNoiseTex
},
"tSprite": {
value: self.particleSpriteTex
}
},
blending: THREE.AdditiveBlending,
vertexShader: GPUParticleShader.vertexShader,
fragmentShader: GPUParticleShader.fragmentShader
});
// define defaults for all values
self.particleShaderMat.defaultAttributeValues.particlePositionsStartTime = [0, 0, 0, 0];
self.particleShaderMat.defaultAttributeValues.particleVelColSizeLife = [0, 0, 0, 0];
self.particleContainers = [];
// extend Object3D
THREE.Object3D.apply(this, arguments);
this.init = function() {
for (var i = 0; i < self.PARTICLE_CONTAINERS; i++) {
var c = new THREE.GPUParticleContainer(self.PARTICLES_PER_CONTAINER, self);
self.particleContainers.push(c);
self.add(c);
}
};
this.spawnParticle = function(options) {
self.PARTICLE_CURSOR++;
if (self.PARTICLE_CURSOR >= self.PARTICLE_COUNT) {
self.PARTICLE_CURSOR = 1;
}
var currentContainer = self.particleContainers[Math.floor(self.PARTICLE_CURSOR / self.PARTICLES_PER_CONTAINER)];
currentContainer.spawnParticle(options);
};
this.update = function(time) {
for (var i = 0; i < self.PARTICLE_CONTAINERS; i++) {
self.particleContainers[i].update(time);
}
};
this.init();
};
THREE.GPUParticleSystem.prototype = Object.create(THREE.Object3D.prototype);
THREE.GPUParticleSystem.prototype.constructor = THREE.GPUParticleSystem;
// Subclass for particle containers, allows for very large arrays to be spread out
THREE.GPUParticleContainer = function(maxParticles, particleSystem) {
var self = this;
self.PARTICLE_COUNT = maxParticles || 100000;
self.PARTICLE_CURSOR = 0;
self.time = 0;
self.DPR = window.devicePixelRatio;
self.GPUParticleSystem = particleSystem;
var particlesPerArray = Math.floor(self.PARTICLE_COUNT / self.MAX_ATTRIBUTES);
// extend Object3D
THREE.Object3D.apply(this, arguments);
// construct a couple small arrays used for packing variables into floats etc
var UINT8_VIEW = new Uint8Array(4);
var FLOAT_VIEW = new Float32Array(UINT8_VIEW.buffer);
function decodeFloat(x, y, z, w) {
UINT8_VIEW[0] = Math.floor(w);
UINT8_VIEW[1] = Math.floor(z);
UINT8_VIEW[2] = Math.floor(y);
UINT8_VIEW[3] = Math.floor(x);
return FLOAT_VIEW[0]
}
function componentToHex(c) {
var hex = c.toString(16);
return hex.length == 1 ? "0" + hex : hex;
}
function rgbToHex(r, g, b) {
return "#" + componentToHex(r) + componentToHex(g) + componentToHex(b);
}
function hexToRgb(hex) {
var r = hex >> 16;
var g = (hex & 0x00FF00) >> 8;
var b = hex & 0x0000FF;
if (r > 0) r--;
if (g > 0) g--;
if (b > 0) b--;
return [r, g, b];
}
self.particles = [];
self.deadParticles = [];
self.particlesAvailableSlot = [];
// create a container for particles
self.particleUpdate = false;
// Shader Based Particle System
self.particleShaderGeo = new THREE.BufferGeometry();
// new hyper compressed attributes
self.particleVertices = new Float32Array(self.PARTICLE_COUNT * 3); // position
self.particlePositionsStartTime = new Float32Array(self.PARTICLE_COUNT * 4); // position
self.particleVelColSizeLife = new Float32Array(self.PARTICLE_COUNT * 4);
for (var i = 0; i < self.PARTICLE_COUNT; i++) {
self.particlePositionsStartTime[i * 4 + 0] = 100; //x
self.particlePositionsStartTime[i * 4 + 1] = 0; //y
self.particlePositionsStartTime[i * 4 + 2] = 0.0; //z
self.particlePositionsStartTime[i * 4 + 3] = 0.0; //startTime
self.particleVertices[i * 3 + 0] = 0; //x
self.particleVertices[i * 3 + 1] = 0; //y
self.particleVertices[i * 3 + 2] = 0.0; //z
self.particleVelColSizeLife[i * 4 + 0] = decodeFloat(128, 128, 0, 0); //vel
self.particleVelColSizeLife[i * 4 + 1] = decodeFloat(0, 254, 0, 254); //color
self.particleVelColSizeLife[i * 4 + 2] = 1.0; //size
self.particleVelColSizeLife[i * 4 + 3] = 0.0; //lifespan
}
self.particleShaderGeo.addAttribute('position', new THREE.BufferAttribute(self.particleVertices, 3));
self.particleShaderGeo.addAttribute('particlePositionsStartTime', new THREE.BufferAttribute(self.particlePositionsStartTime, 4).setDynamic(true));
self.particleShaderGeo.addAttribute('particleVelColSizeLife', new THREE.BufferAttribute(self.particleVelColSizeLife, 4).setDynamic(true));
self.posStart = self.particleShaderGeo.getAttribute('particlePositionsStartTime');
self.velCol = self.particleShaderGeo.getAttribute('particleVelColSizeLife');
self.particleShaderMat = self.GPUParticleSystem.particleShaderMat;
this.init = function() {
self.particleSystem = new THREE.Points(self.particleShaderGeo, self.particleShaderMat);
self.particleSystem.frustumCulled = false;
this.add(self.particleSystem);
};
var options = {},
position = new THREE.Vector3(),
velocity = new THREE.Vector3(),
positionRandomness = 0.,
velocityRandomness = 0.,
color = 0xffffff,
colorRandomness = 0.,
turbulence = 0.,
lifetime = 0.,
size = 0.,
sizeRandomness = 0.,
smoothPosition = false,
i;
var maxVel = 2;
var maxSource = 250;
this.offset = 0;
this.count = 0;
this.spawnParticle = function(options) {
options = options || {};
// setup reasonable default values for all arguments
position = options.position !== undefined ? position.copy(options.position) : position.set(0., 0., 0.);
velocity = options.velocity !== undefined ? velocity.copy(options.velocity) : velocity.set(0., 0., 0.);
positionRandomness = options.positionRandomness !== undefined ? options.positionRandomness : 0.0;
velocityRandomness = options.velocityRandomness !== undefined ? options.velocityRandomness : 0.0;
color = options.color !== undefined ? options.color : 0xffffff;
colorRandomness = options.colorRandomness !== undefined ? options.colorRandomness : 1.0;
turbulence = options.turbulence !== undefined ? options.turbulence : 1.0;
lifetime = options.lifetime !== undefined ? options.lifetime : 5.0;
size = options.size !== undefined ? options.size : 10;
sizeRandomness = options.sizeRandomness !== undefined ? options.sizeRandomness : 0.0;
smoothPosition = options.smoothPosition !== undefined ? options.smoothPosition : false;
if (self.DPR !== undefined) size *= self.DPR;
i = self.PARTICLE_CURSOR;
self.posStart.array[i * 4 + 0] = position.x + ((particleSystem.random()) * positionRandomness); // - ( velocity.x * particleSystem.random() ); //x
self.posStart.array[i * 4 + 1] = position.y + ((particleSystem.random()) * positionRandomness); // - ( velocity.y * particleSystem.random() ); //y
self.posStart.array[i * 4 + 2] = position.z + ((particleSystem.random()) * positionRandomness); // - ( velocity.z * particleSystem.random() ); //z
self.posStart.array[i * 4 + 3] = self.time + (particleSystem.random() * 2e-2); //startTime
if (smoothPosition === true) {
self.posStart.array[i * 4 + 0] += -(velocity.x * particleSystem.random()); //x
self.posStart.array[i * 4 + 1] += -(velocity.y * particleSystem.random()); //y
self.posStart.array[i * 4 + 2] += -(velocity.z * particleSystem.random()); //z
}
var velX = velocity.x + (particleSystem.random()) * velocityRandomness;
var velY = velocity.y + (particleSystem.random()) * velocityRandomness;
var velZ = velocity.z + (particleSystem.random()) * velocityRandomness;
// convert turbulence rating to something we can pack into a vec4
var turbulence = Math.floor(turbulence * 254);
// clamp our value to between 0. and 1.
velX = Math.floor(maxSource * ((velX - -maxVel) / (maxVel - -maxVel)));
velY = Math.floor(maxSource * ((velY - -maxVel) / (maxVel - -maxVel)));
velZ = Math.floor(maxSource * ((velZ - -maxVel) / (maxVel - -maxVel)));
self.velCol.array[i * 4 + 0] = decodeFloat(velX, velY, velZ, turbulence); //vel
var rgb = hexToRgb(color);
for (var c = 0; c < rgb.length; c++) {
rgb[c] = Math.floor(rgb[c] + ((particleSystem.random()) * colorRandomness) * 254);
if (rgb[c] > 254) rgb[c] = 254;
if (rgb[c] < 0) rgb[c] = 0;
}
self.velCol.array[i * 4 + 1] = decodeFloat(rgb[0], rgb[1], rgb[2], 254); //color
self.velCol.array[i * 4 + 2] = size + (particleSystem.random()) * sizeRandomness; //size
self.velCol.array[i * 4 + 3] = lifetime; //lifespan
if (this.offset == 0) {
this.offset = self.PARTICLE_CURSOR;
}
self.count++;
self.PARTICLE_CURSOR++;
if (self.PARTICLE_CURSOR >= self.PARTICLE_COUNT) {
self.PARTICLE_CURSOR = 0;
}
self.particleUpdate = true;
};
this.update = function(time) {
self.time = time;
self.particleShaderMat.uniforms['uTime'].value = time;
this.geometryUpdate();
};
this.geometryUpdate = function() {
if (self.particleUpdate == true) {
self.particleUpdate = false;
// if we can get away with a partial buffer update, do so
if (self.offset + self.count < self.PARTICLE_COUNT) {
self.posStart.updateRange.offset = self.velCol.updateRange.offset = self.offset * 4;
self.posStart.updateRange.count = self.velCol.updateRange.count = self.count * 4;
} else {
self.posStart.updateRange.offset = 0;
self.posStart.updateRange.count = self.velCol.updateRange.count = (self.PARTICLE_COUNT * 4);
}
self.posStart.needsUpdate = true;
self.velCol.needsUpdate = true;
self.offset = 0;
self.count = 0;
}
};
this.init();
};
THREE.GPUParticleContainer.prototype = Object.create(THREE.Object3D.prototype);
THREE.GPUParticleContainer.prototype.constructor = THREE.GPUParticleContainer;

65
node_modules/three/examples/js/Gyroscope.js generated vendored Normal file
View File

@@ -0,0 +1,65 @@
/**
* @author alteredq / http://alteredqualia.com/
*/
THREE.Gyroscope = function () {
THREE.Object3D.call( this );
};
THREE.Gyroscope.prototype = Object.create( THREE.Object3D.prototype );
THREE.Gyroscope.prototype.constructor = THREE.Gyroscope;
THREE.Gyroscope.prototype.updateMatrixWorld = ( function () {
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 ) {
this.matrixAutoUpdate && this.updateMatrix();
// update matrixWorld
if ( this.matrixWorldNeedsUpdate || force ) {
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 );
} else {
this.matrixWorld.copy( this.matrix );
}
this.matrixWorldNeedsUpdate = false;
force = true;
}
// update children
for ( var i = 0, l = this.children.length; i < l; i ++ ) {
this.children[ i ].updateMatrixWorld( force );
}
};
}() );

71
node_modules/three/examples/js/ImprovedNoise.js generated vendored Normal file
View File

@@ -0,0 +1,71 @@
// http://mrl.nyu.edu/~perlin/noise/
var ImprovedNoise = function () {
var p = [ 151,160,137,91,90,15,131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,
23,190,6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33,88,237,149,56,87,
174,20,125,136,171,168,68,175,74,165,71,134,139,48,27,166,77,146,158,231,83,111,229,122,60,211,
133,230,220,105,92,41,55,46,245,40,244,102,143,54,65,25,63,161,1,216,80,73,209,76,132,187,208,
89,18,169,200,196,135,130,116,188,159,86,164,100,109,198,173,186,3,64,52,217,226,250,124,123,5,
202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42,223,183,170,213,119,
248,152,2,44,154,163,70,221,153,101,155,167,43,172,9,129,22,39,253,19,98,108,110,79,113,224,232,
178,185,112,104,218,246,97,228,251,34,242,193,238,210,144,12,191,179,162,241,81,51,145,235,249,
14,239,107,49,192,214,31,181,199,106,157,184,84,204,176,115,121,50,45,127,4,150,254,138,236,205,
93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180 ];
for (var i = 0; i < 256 ; i ++) {
p[256 + i] = p[i];
}
function fade(t) {
return t * t * t * (t * (t * 6 - 15) + 10);
}
function lerp(t, a, b) {
return a + t * (b - a);
}
function grad(hash, x, y, z) {
var h = hash & 15;
var u = h < 8 ? x : y, v = h < 4 ? y : h == 12 || h == 14 ? x : z;
return ((h&1) == 0 ? u : -u) + ((h&2) == 0 ? v : -v);
}
return {
noise: function (x, y, z) {
var floorX = Math.floor(x), floorY = Math.floor(y), floorZ = Math.floor(z);
var X = floorX & 255, Y = floorY & 255, Z = floorZ & 255;
x -= floorX;
y -= floorY;
z -= floorZ;
var xMinus1 = x - 1, yMinus1 = y - 1, zMinus1 = z - 1;
var u = fade(x), v = fade(y), w = fade(z);
var A = p[X] + Y, AA = p[A] + Z, AB = p[A + 1] + Z, B = p[X + 1] + Y, BA = p[B] + Z, BB = p[B + 1] + Z;
return lerp(w, lerp(v, lerp(u, grad(p[AA], x, y, z),
grad(p[BA], xMinus1, y, z)),
lerp(u, grad(p[AB], x, yMinus1, z),
grad(p[BB], xMinus1, yMinus1, z))),
lerp(v, lerp(u, grad(p[AA + 1], x, y, zMinus1),
grad(p[BA + 1], xMinus1, y, z - 1)),
lerp(u, grad(p[AB + 1], x, yMinus1, zMinus1),
grad(p[BB + 1], xMinus1, yMinus1, zMinus1))));
}
}
};

254
node_modules/three/examples/js/MD2Character.js generated vendored Normal file
View File

@@ -0,0 +1,254 @@
/**
* @author alteredq / http://alteredqualia.com/
*/
THREE.MD2Character = function () {
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;
this.onLoadComplete = function () {};
this.loadCounter = 0;
this.loadParts = function ( config ) {
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 ];
// SKINS
this.skinsBody = loadTextures( config.baseUrl + "skins/", config.skins );
this.skinsWeapon = loadTextures( config.baseUrl + "skins/", weaponsTextures );
// BODY
var loader = new THREE.MD2Loader();
loader.load( config.baseUrl + config.body, function( geo ) {
geo.computeBoundingBox();
scope.root.position.y = - scope.scale * geo.boundingBox.min.y;
var mesh = createPart( geo, scope.skinsBody[ 0 ] );
mesh.scale.set( scope.scale, scope.scale, scope.scale );
scope.root.add( mesh );
scope.meshBody = mesh;
scope.meshBody.clipOffset = 0;
scope.activeAnimationClipName = mesh.geometry.animations[0].name;
scope.mixer = new THREE.AnimationMixer( mesh );
checkLoadingComplete();
} );
// WEAPONS
var generateCallback = function ( index, name ) {
return function( geo ) {
var mesh = createPart( geo, scope.skinsWeapon[ index ] );
mesh.scale.set( scope.scale, scope.scale, scope.scale );
mesh.visible = false;
mesh.name = name;
scope.root.add( mesh );
scope.weapons[ index ] = mesh;
scope.meshWeapon = mesh;
checkLoadingComplete();
}
};
for ( var 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 ) {
if( rate !== 0 ) {
this.mixer.timeScale = 1 / rate;
}
else {
this.mixer.timeScale = 0;
}
};
this.setWireframe = function ( wireframeEnabled ) {
if ( wireframeEnabled ) {
if ( this.meshBody ) this.meshBody.material = this.meshBody.materialWireframe;
if ( this.meshWeapon ) this.meshWeapon.material = this.meshWeapon.materialWireframe;
} else {
if ( this.meshBody ) this.meshBody.material = this.meshBody.materialTexture;
if ( this.meshWeapon ) this.meshWeapon.material = this.meshWeapon.materialTexture;
}
};
this.setSkin = function( index ) {
if ( this.meshBody && this.meshBody.material.wireframe === false ) {
this.meshBody.material.map = this.skinsBody[ index ];
}
};
this.setWeapon = function ( index ) {
for ( var i = 0; i < this.weapons.length; i ++ ) this.weapons[ i ].visible = false;
var activeWeapon = this.weapons[ index ];
if ( activeWeapon ) {
activeWeapon.visible = true;
this.meshWeapon = activeWeapon;
scope.syncWeaponAnimation();
}
};
this.setAnimation = function ( clipName ) {
if ( this.meshBody ) {
if( this.meshBody.activeAction ) {
this.meshBody.activeAction.stop();
this.meshBody.activeAction = null;
}
var action = this.mixer.clipAction( clipName, this.meshBody );
if( action ) {
this.meshBody.activeAction = action.play();
}
}
scope.activeClipName = clipName;
scope.syncWeaponAnimation();
};
this.syncWeaponAnimation = function() {
var clipName = scope.activeClipName;
if ( scope.meshWeapon ) {
if( this.meshWeapon.activeAction ) {
this.meshWeapon.activeAction.stop();
this.meshWeapon.activeAction = null;
}
var geometry = this.meshWeapon.geometry,
animations = geometry.animations;
var action = this.mixer.clipAction( clipName, this.meshWeapon );
if( action ) {
this.meshWeapon.activeAction =
action.syncWith( this.meshBody.activeAction ).play();
}
}
}
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 ];
}
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;
}
function checkLoadingComplete() {
scope.loadCounter -= 1;
if ( scope.loadCounter === 0 ) scope.onLoadComplete();
}
};

560
node_modules/three/examples/js/MD2CharacterComplex.js generated vendored Normal file
View File

@@ -0,0 +1,560 @@
/**
* @author alteredq / http://alteredqualia.com/
*/
THREE.MD2CharacterComplex = function () {
var scope = this;
this.scale = 1;
// animation parameters
this.animationFPS = 6;
this.transitionFrames = 15;
// movement model parameters
this.maxSpeed = 275;
this.maxReverseSpeed = - 275;
this.frontAcceleration = 600;
this.backAcceleration = 600;
this.frontDecceleration = 600;
this.angularSpeed = 2.5;
// rig
this.root = new THREE.Object3D();
this.meshBody = null;
this.meshWeapon = null;
this.controls = null;
// skins
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.activeAnimation = null;
this.oldAnimation = null;
// API
this.enableShadows = function ( enable ) {
for ( var i = 0; i < this.meshes.length; i ++ ) {
this.meshes[ i ].castShadow = enable;
this.meshes[ i ].receiveShadow = enable;
}
};
this.setVisible = function ( enable ) {
for ( var i = 0; i < this.meshes.length; i ++ ) {
this.meshes[ i ].visible = enable;
this.meshes[ i ].visible = enable;
}
};
this.shareParts = function ( original ) {
this.animations = original.animations;
this.walkSpeed = original.walkSpeed;
this.crouchSpeed = original.crouchSpeed;
this.skinsBody = original.skinsBody;
this.skinsWeapon = original.skinsWeapon;
// BODY
var mesh = 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 ++ ) {
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;
this.root.add( meshWeapon );
this.weapons[ i ] = meshWeapon;
this.meshWeapon = meshWeapon;
this.meshes.push( meshWeapon );
}
};
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 = [];
for ( var 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();
loader.load( config.baseUrl + config.body, function( geo ) {
geo.computeBoundingBox();
scope.root.position.y = - scope.scale * geo.boundingBox.min.y;
var mesh = createPart( geo, scope.skinsBody[ 0 ] );
mesh.scale.set( scope.scale, scope.scale, scope.scale );
scope.root.add( mesh );
scope.meshBody = mesh;
scope.meshes.push( mesh );
checkLoadingComplete();
} );
// WEAPONS
var generateCallback = function ( index, name ) {
return function( geo ) {
var mesh = createPart( geo, scope.skinsWeapon[ index ] );
mesh.scale.set( scope.scale, scope.scale, scope.scale );
mesh.visible = false;
mesh.name = name;
scope.root.add( mesh );
scope.weapons[ index ] = mesh;
scope.meshWeapon = mesh;
scope.meshes.push( mesh );
checkLoadingComplete();
}
};
for ( var 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 ) {
if ( this.meshBody ) this.meshBody.duration = this.meshBody.baseDuration / rate;
if ( this.meshWeapon ) this.meshWeapon.duration = this.meshWeapon.baseDuration / rate;
};
this.setWireframe = function ( wireframeEnabled ) {
if ( wireframeEnabled ) {
if ( this.meshBody ) this.meshBody.material = this.meshBody.materialWireframe;
if ( this.meshWeapon ) this.meshWeapon.material = this.meshWeapon.materialWireframe;
} else {
if ( this.meshBody ) this.meshBody.material = this.meshBody.materialTexture;
if ( this.meshWeapon ) this.meshWeapon.material = this.meshWeapon.materialTexture;
}
};
this.setSkin = function( index ) {
if ( this.meshBody && this.meshBody.material.wireframe === false ) {
this.meshBody.material.map = this.skinsBody[ index ];
this.currentSkin = index;
}
};
this.setWeapon = function ( index ) {
for ( var i = 0; i < this.weapons.length; i ++ ) this.weapons[ i ].visible = false;
var activeWeapon = this.weapons[ index ];
if ( activeWeapon ) {
activeWeapon.visible = true;
this.meshWeapon = activeWeapon;
if ( this.activeAnimation ) {
activeWeapon.playAnimation( this.activeAnimation );
this.meshWeapon.setAnimationTime( this.activeAnimation, this.meshBody.getAnimationTime( this.activeAnimation ) );
}
}
};
this.setAnimation = function ( animationName ) {
if ( animationName === this.activeAnimation || ! animationName ) return;
if ( this.meshBody ) {
this.meshBody.setAnimationWeight( animationName, 0 );
this.meshBody.playAnimation( animationName );
this.oldAnimation = this.activeAnimation;
this.activeAnimation = animationName;
this.blendCounter = this.transitionFrames;
}
if ( this.meshWeapon ) {
this.meshWeapon.setAnimationWeight( animationName, 0 );
this.meshWeapon.playAnimation( animationName );
}
};
this.update = function ( delta ) {
if ( this.controls ) this.updateMovementModel( delta );
if ( this.animations ) {
this.updateBehaviors( delta );
this.updateAnimations( delta );
}
};
this.updateAnimations = function ( delta ) {
var mix = 1;
if ( this.blendCounter > 0 ) {
mix = ( this.transitionFrames - this.blendCounter ) / this.transitionFrames;
this.blendCounter -= 1;
}
if ( this.meshBody ) {
this.meshBody.update( delta );
this.meshBody.setAnimationWeight( this.activeAnimation, mix );
this.meshBody.setAnimationWeight( this.oldAnimation, 1 - mix );
}
if ( this.meshWeapon ) {
this.meshWeapon.update( delta );
this.meshWeapon.setAnimationWeight( this.activeAnimation, mix );
this.meshWeapon.setAnimationWeight( this.oldAnimation, 1 - mix );
}
};
this.updateBehaviors = function ( delta ) {
var controls = this.controls;
var animations = this.animations;
var moveAnimation, idleAnimation;
// crouch vs stand
if ( controls.crouch ) {
moveAnimation = animations[ "crouchMove" ];
idleAnimation = animations[ "crouchIdle" ];
} else {
moveAnimation = animations[ "move" ];
idleAnimation = animations[ "idle" ];
}
// actions
if ( controls.jump ) {
moveAnimation = animations[ "jump" ];
idleAnimation = animations[ "jump" ];
}
if ( controls.attack ) {
if ( controls.crouch ) {
moveAnimation = animations[ "crouchAttack" ];
idleAnimation = animations[ "crouchAttack" ];
} else {
moveAnimation = animations[ "attack" ];
idleAnimation = animations[ "attack" ];
}
}
// set animations
if ( controls.moveForward || controls.moveBackward || controls.moveLeft || controls.moveRight ) {
if ( this.activeAnimation !== moveAnimation ) {
this.setAnimation( moveAnimation );
}
}
if ( Math.abs( this.speed ) < 0.2 * this.maxSpeed && ! ( controls.moveLeft || controls.moveRight || controls.moveForward || controls.moveBackward ) ) {
if ( this.activeAnimation !== idleAnimation ) {
this.setAnimation( idleAnimation );
}
}
// set animation direction
if ( controls.moveForward ) {
if ( this.meshBody ) {
this.meshBody.setAnimationDirectionForward( this.activeAnimation );
this.meshBody.setAnimationDirectionForward( this.oldAnimation );
}
if ( this.meshWeapon ) {
this.meshWeapon.setAnimationDirectionForward( this.activeAnimation );
this.meshWeapon.setAnimationDirectionForward( this.oldAnimation );
}
}
if ( controls.moveBackward ) {
if ( this.meshBody ) {
this.meshBody.setAnimationDirectionBackward( this.activeAnimation );
this.meshBody.setAnimationDirectionBackward( this.oldAnimation );
}
if ( this.meshWeapon ) {
this.meshWeapon.setAnimationDirectionBackward( this.activeAnimation );
this.meshWeapon.setAnimationDirectionBackward( this.oldAnimation );
}
}
};
this.updateMovementModel = function ( delta ) {
var controls = this.controls;
// speed based on controls
if ( controls.crouch ) this.maxSpeed = this.crouchSpeed;
else this.maxSpeed = this.walkSpeed;
this.maxReverseSpeed = - this.maxSpeed;
if ( controls.moveForward ) this.speed = THREE.Math.clamp( this.speed + delta * this.frontAcceleration, this.maxReverseSpeed, this.maxSpeed );
if ( controls.moveBackward ) this.speed = THREE.Math.clamp( this.speed - delta * this.backAcceleration, this.maxReverseSpeed, this.maxSpeed );
// orientation based on controls
// (don't just stand while turning)
var dir = 1;
if ( controls.moveLeft ) {
this.bodyOrientation += delta * this.angularSpeed;
this.speed = THREE.Math.clamp( this.speed + dir * delta * this.frontAcceleration, this.maxReverseSpeed, this.maxSpeed );
}
if ( controls.moveRight ) {
this.bodyOrientation -= delta * this.angularSpeed;
this.speed = THREE.Math.clamp( this.speed + dir * delta * this.frontAcceleration, this.maxReverseSpeed, this.maxSpeed );
}
// speed decay
if ( ! ( controls.moveForward || controls.moveBackward ) ) {
if ( this.speed > 0 ) {
var k = exponentialEaseOut( this.speed / this.maxSpeed );
this.speed = THREE.Math.clamp( this.speed - k * delta * this.frontDecceleration, 0, this.maxSpeed );
} else {
var k = exponentialEaseOut( this.speed / this.maxReverseSpeed );
this.speed = THREE.Math.clamp( this.speed + k * delta * this.backAcceleration, this.maxReverseSpeed, 0 );
}
}
// displacement
var 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
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 ];
}
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.MorphBlendMesh( geometry, materialTexture );
mesh.rotation.y = - Math.PI / 2;
//
mesh.materialTexture = materialTexture;
mesh.materialWireframe = materialWireframe;
//
mesh.autoCreateAnimations( scope.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;
}
};

1044
node_modules/three/examples/js/MarchingCubes.js generated vendored Normal file

File diff suppressed because it is too large Load Diff

302
node_modules/three/examples/js/Mirror.js generated vendored Normal file
View File

@@ -0,0 +1,302 @@
/**
* @author Slayvin / http://slayvin.net
*/
THREE.ShaderLib[ 'mirror' ] = {
uniforms: {
"mirrorColor": { value: new THREE.Color( 0x7F7F7F ) },
"mirrorSampler": { value: null },
"textureMatrix" : { value: new THREE.Matrix4() }
},
vertexShader: [
"uniform mat4 textureMatrix;",
"varying vec4 mirrorCoord;",
"void main() {",
"vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );",
"vec4 worldPosition = modelMatrix * vec4( position, 1.0 );",
"mirrorCoord = textureMatrix * worldPosition;",
"gl_Position = projectionMatrix * mvPosition;",
"}"
].join( "\n" ),
fragmentShader: [
"uniform vec3 mirrorColor;",
"uniform sampler2D mirrorSampler;",
"varying vec4 mirrorCoord;",
"float blendOverlay(float base, float blend) {",
"return( base < 0.5 ? ( 2.0 * base * blend ) : (1.0 - 2.0 * ( 1.0 - base ) * ( 1.0 - blend ) ) );",
"}",
"void main() {",
"vec4 color = texture2DProj(mirrorSampler, mirrorCoord);",
"color = vec4(blendOverlay(mirrorColor.r, color.r), blendOverlay(mirrorColor.g, color.g), blendOverlay(mirrorColor.b, color.b), 1.0);",
"gl_FragColor = color;",
"}"
].join( "\n" )
};
THREE.Mirror = function ( renderer, camera, options ) {
THREE.Object3D.call( this );
this.name = 'mirror_' + this.id;
options = options || {};
this.matrixNeedsUpdate = true;
var width = options.textureWidth !== undefined ? options.textureWidth : 512;
var height = options.textureHeight !== undefined ? options.textureHeight : 512;
this.clipBias = options.clipBias !== undefined ? options.clipBias : 0.0;
var mirrorColor = options.color !== undefined ? new THREE.Color( options.color ) : new THREE.Color( 0x7F7F7F );
this.renderer = renderer;
this.mirrorPlane = new THREE.Plane();
this.normal = new THREE.Vector3( 0, 0, 1 );
this.mirrorWorldPosition = new THREE.Vector3();
this.cameraWorldPosition = new THREE.Vector3();
this.rotationMatrix = new THREE.Matrix4();
this.lookAtPosition = new THREE.Vector3( 0, 0, - 1 );
this.clipPlane = new THREE.Vector4();
// For debug only, show the normal and plane of the mirror
var debugMode = options.debugMode !== undefined ? options.debugMode : false;
if ( debugMode ) {
var arrow = new THREE.ArrowHelper( new THREE.Vector3( 0, 0, 1 ), new THREE.Vector3( 0, 0, 0 ), 10, 0xffff80 );
var planeGeometry = new THREE.Geometry();
planeGeometry.vertices.push( new THREE.Vector3( - 10, - 10, 0 ) );
planeGeometry.vertices.push( new THREE.Vector3( 10, - 10, 0 ) );
planeGeometry.vertices.push( new THREE.Vector3( 10, 10, 0 ) );
planeGeometry.vertices.push( new THREE.Vector3( - 10, 10, 0 ) );
planeGeometry.vertices.push( planeGeometry.vertices[ 0 ] );
var plane = new THREE.Line( planeGeometry, new THREE.LineBasicMaterial( { color: 0xffff80 } ) );
this.add( arrow );
this.add( plane );
}
if ( camera instanceof THREE.PerspectiveCamera ) {
this.camera = camera;
} else {
this.camera = new THREE.PerspectiveCamera();
console.log( this.name + ': camera is not a Perspective Camera!' );
}
this.textureMatrix = new THREE.Matrix4();
this.mirrorCamera = this.camera.clone();
this.mirrorCamera.matrixAutoUpdate = true;
var parameters = { minFilter: THREE.LinearFilter, magFilter: THREE.LinearFilter, format: THREE.RGBFormat, stencilBuffer: false };
this.renderTarget = new THREE.WebGLRenderTarget( width, height, parameters );
this.renderTarget2 = new THREE.WebGLRenderTarget( width, height, parameters );
var mirrorShader = THREE.ShaderLib[ "mirror" ];
var mirrorUniforms = THREE.UniformsUtils.clone( mirrorShader.uniforms );
this.material = new THREE.ShaderMaterial( {
fragmentShader: mirrorShader.fragmentShader,
vertexShader: mirrorShader.vertexShader,
uniforms: mirrorUniforms
} );
this.material.uniforms.mirrorSampler.value = this.renderTarget.texture;
this.material.uniforms.mirrorColor.value = mirrorColor;
this.material.uniforms.textureMatrix.value = this.textureMatrix;
if ( ! THREE.Math.isPowerOfTwo( width ) || ! THREE.Math.isPowerOfTwo( height ) ) {
this.renderTarget.texture.generateMipmaps = false;
this.renderTarget2.texture.generateMipmaps = false;
}
this.updateTextureMatrix();
this.render();
};
THREE.Mirror.prototype = Object.create( THREE.Object3D.prototype );
THREE.Mirror.prototype.constructor = THREE.Mirror;
THREE.Mirror.prototype.renderWithMirror = function ( otherMirror ) {
// update the mirror matrix to mirror the current view
this.updateTextureMatrix();
this.matrixNeedsUpdate = false;
// set the camera of the other mirror so the mirrored view is the reference view
var tempCamera = otherMirror.camera;
otherMirror.camera = this.mirrorCamera;
// render the other mirror in temp texture
otherMirror.renderTemp();
otherMirror.material.uniforms.mirrorSampler.value = otherMirror.renderTarget2.texture;
// render the current mirror
this.render();
this.matrixNeedsUpdate = true;
// restore material and camera of other mirror
otherMirror.material.uniforms.mirrorSampler.value = otherMirror.renderTarget.texture;
otherMirror.camera = tempCamera;
// restore texture matrix of other mirror
otherMirror.updateTextureMatrix();
};
THREE.Mirror.prototype.updateTextureMatrix = function () {
this.updateMatrixWorld();
this.camera.updateMatrixWorld();
this.mirrorWorldPosition.setFromMatrixPosition( this.matrixWorld );
this.cameraWorldPosition.setFromMatrixPosition( this.camera.matrixWorld );
this.rotationMatrix.extractRotation( this.matrixWorld );
this.normal.set( 0, 0, 1 );
this.normal.applyMatrix4( this.rotationMatrix );
var view = this.mirrorWorldPosition.clone().sub( this.cameraWorldPosition );
view.reflect( this.normal ).negate();
view.add( this.mirrorWorldPosition );
this.rotationMatrix.extractRotation( this.camera.matrixWorld );
this.lookAtPosition.set( 0, 0, - 1 );
this.lookAtPosition.applyMatrix4( this.rotationMatrix );
this.lookAtPosition.add( this.cameraWorldPosition );
var target = this.mirrorWorldPosition.clone().sub( this.lookAtPosition );
target.reflect( this.normal ).negate();
target.add( this.mirrorWorldPosition );
this.up.set( 0, - 1, 0 );
this.up.applyMatrix4( this.rotationMatrix );
this.up.reflect( this.normal ).negate();
this.mirrorCamera.position.copy( view );
this.mirrorCamera.up = this.up;
this.mirrorCamera.lookAt( target );
this.mirrorCamera.updateProjectionMatrix();
this.mirrorCamera.updateMatrixWorld();
this.mirrorCamera.matrixWorldInverse.getInverse( this.mirrorCamera.matrixWorld );
// Update the texture matrix
this.textureMatrix.set( 0.5, 0.0, 0.0, 0.5,
0.0, 0.5, 0.0, 0.5,
0.0, 0.0, 0.5, 0.5,
0.0, 0.0, 0.0, 1.0 );
this.textureMatrix.multiply( this.mirrorCamera.projectionMatrix );
this.textureMatrix.multiply( this.mirrorCamera.matrixWorldInverse );
// Now update projection matrix with new clip plane, implementing code from: http://www.terathon.com/code/oblique.html
// Paper explaining this technique: http://www.terathon.com/lengyel/Lengyel-Oblique.pdf
this.mirrorPlane.setFromNormalAndCoplanarPoint( this.normal, this.mirrorWorldPosition );
this.mirrorPlane.applyMatrix4( this.mirrorCamera.matrixWorldInverse );
this.clipPlane.set( this.mirrorPlane.normal.x, this.mirrorPlane.normal.y, this.mirrorPlane.normal.z, this.mirrorPlane.constant );
var q = new THREE.Vector4();
var projectionMatrix = this.mirrorCamera.projectionMatrix;
q.x = ( Math.sign( this.clipPlane.x ) + projectionMatrix.elements[ 8 ] ) / projectionMatrix.elements[ 0 ];
q.y = ( Math.sign( this.clipPlane.y ) + projectionMatrix.elements[ 9 ] ) / projectionMatrix.elements[ 5 ];
q.z = - 1.0;
q.w = ( 1.0 + projectionMatrix.elements[ 10 ] ) / projectionMatrix.elements[ 14 ];
// Calculate the scaled plane vector
var c = new THREE.Vector4();
c = this.clipPlane.multiplyScalar( 2.0 / this.clipPlane.dot( q ) );
// Replacing the third row of the projection matrix
projectionMatrix.elements[ 2 ] = c.x;
projectionMatrix.elements[ 6 ] = c.y;
projectionMatrix.elements[ 10 ] = c.z + 1.0 - this.clipBias;
projectionMatrix.elements[ 14 ] = c.w;
};
THREE.Mirror.prototype.render = function () {
if ( this.matrixNeedsUpdate ) this.updateTextureMatrix();
this.matrixNeedsUpdate = true;
// Render the mirrored view of the current scene into the target texture
var scene = this;
while ( scene.parent !== null ) {
scene = scene.parent;
}
if ( scene !== undefined && scene instanceof THREE.Scene ) {
// We can't render ourself to ourself
var visible = this.material.visible;
this.material.visible = false;
this.renderer.render( scene, this.mirrorCamera, this.renderTarget, true );
this.material.visible = visible;
}
};
THREE.Mirror.prototype.renderTemp = function () {
if ( this.matrixNeedsUpdate ) this.updateTextureMatrix();
this.matrixNeedsUpdate = true;
// Render the mirrored view of the current scene into the target texture
var scene = this;
while ( scene.parent !== null ) {
scene = scene.parent;
}
if ( scene !== undefined && scene instanceof THREE.Scene ) {
this.renderer.render( scene, this.mirrorCamera, this.renderTarget2, true );
}
};

69
node_modules/three/examples/js/MorphAnimMesh.js generated vendored Normal file
View File

@@ -0,0 +1,69 @@
/**
* @author alteredq / http://alteredqualia.com/
*/
THREE.MorphAnimMesh = function ( geometry, material ) {
THREE.Mesh.call( this, geometry, material );
this.type = 'MorphAnimMesh';
this.mixer = new THREE.AnimationMixer( this );
this.activeAction = null;
};
THREE.MorphAnimMesh.prototype = Object.create( THREE.Mesh.prototype );
THREE.MorphAnimMesh.prototype.constructor = THREE.MorphAnimMesh;
THREE.MorphAnimMesh.prototype.setDirectionForward = function () {
this.mixer.timeScale = 1.0;
};
THREE.MorphAnimMesh.prototype.setDirectionBackward = function () {
this.mixer.timeScale = -1.0;
};
THREE.MorphAnimMesh.prototype.playAnimation = function ( label, fps ) {
if( this.activeAction ) {
this.activeAction.stop();
this.activeAction = null;
}
var clip = THREE.AnimationClip.findByName( this, label );
if ( clip ) {
var action = this.mixer.clipAction( clip );
action.timeScale = ( clip.tracks.length * fps ) / clip.duration;
this.activeAction = action.play();
} else {
throw new Error( 'THREE.MorphAnimMesh: animations[' + label + '] undefined in .playAnimation()' );
}
};
THREE.MorphAnimMesh.prototype.updateAnimation = function ( delta ) {
this.mixer.update( delta );
};
THREE.MorphAnimMesh.prototype.copy = function ( source ) {
THREE.Mesh.prototype.copy.call( this, source );
this.mixer = new THREE.AnimationMixer( this );
return this;
};

73
node_modules/three/examples/js/MorphAnimation.js generated vendored Normal file
View File

@@ -0,0 +1,73 @@
/**
* @author mrdoob / http://mrdoob.com
* @author willy-vvu / http://willy-vvu.github.io
*/
THREE.MorphAnimation = function ( mesh ) {
this.mesh = mesh;
this.frames = mesh.morphTargetInfluences.length;
this.currentTime = 0;
this.duration = 1000;
this.loop = true;
this.lastFrame = 0;
this.currentFrame = 0;
this.isPlaying = false;
};
THREE.MorphAnimation.prototype = {
constructor: THREE.MorphAnimation,
play: function () {
this.isPlaying = true;
},
pause: function () {
this.isPlaying = false;
},
update: function ( delta ) {
if ( this.isPlaying === false ) return;
this.currentTime += delta;
if ( this.loop === true && this.currentTime > this.duration ) {
this.currentTime %= this.duration;
}
this.currentTime = Math.min( this.currentTime, this.duration );
var frameTime = this.duration / this.frames;
var frame = Math.floor( this.currentTime / frameTime );
var influences = this.mesh.morphTargetInfluences;
if ( frame !== this.currentFrame ) {
influences[ this.lastFrame ] = 0;
influences[ this.currentFrame ] = 1;
influences[ frame ] = 0;
this.lastFrame = this.currentFrame;
this.currentFrame = frame;
}
var mix = ( this.currentTime % frameTime ) / frameTime;
influences[ frame ] = mix;
influences[ this.lastFrame ] = 1 - mix;
}
};

359
node_modules/three/examples/js/Ocean.js generated vendored Normal file
View File

@@ -0,0 +1,359 @@
THREE.Ocean = function ( renderer, camera, scene, options ) {
// flag used to trigger parameter changes
this.changed = true;
this.initial = true;
// Assign required parameters as object properties
this.oceanCamera = new THREE.OrthographicCamera(); //camera.clone();
this.oceanCamera.position.z = 1;
this.renderer = renderer;
this.renderer.clearColor( 0xffffff );
this.scene = new THREE.Scene();
// Assign optional parameters as variables and object properties
function optionalParameter( value, defaultValue ) {
return value !== undefined ? value : defaultValue;
}
options = options || {};
this.clearColor = optionalParameter( options.CLEAR_COLOR, [ 1.0, 1.0, 1.0, 0.0 ] );
this.geometryOrigin = optionalParameter( options.GEOMETRY_ORIGIN, [ - 1000.0, - 1000.0 ] );
this.sunDirectionX = optionalParameter( options.SUN_DIRECTION[ 0 ], - 1.0 );
this.sunDirectionY = optionalParameter( options.SUN_DIRECTION[ 1 ], 1.0 );
this.sunDirectionZ = optionalParameter( options.SUN_DIRECTION[ 2 ], 1.0 );
this.oceanColor = optionalParameter( options.OCEAN_COLOR, new THREE.Vector3( 0.004, 0.016, 0.047 ) );
this.skyColor = optionalParameter( options.SKY_COLOR, new THREE.Vector3( 3.2, 9.6, 12.8 ) );
this.exposure = optionalParameter( options.EXPOSURE, 0.35 );
this.geometryResolution = optionalParameter( options.GEOMETRY_RESOLUTION, 32 );
this.geometrySize = optionalParameter( options.GEOMETRY_SIZE, 2000 );
this.resolution = optionalParameter( options.RESOLUTION, 64 );
this.floatSize = optionalParameter( options.SIZE_OF_FLOAT, 4 );
this.windX = optionalParameter( options.INITIAL_WIND[ 0 ], 10.0 );
this.windY = optionalParameter( options.INITIAL_WIND[ 1 ], 10.0 );
this.size = optionalParameter( options.INITIAL_SIZE, 250.0 );
this.choppiness = optionalParameter( options.INITIAL_CHOPPINESS, 1.5 );
//
this.matrixNeedsUpdate = false;
// Setup framebuffer pipeline
var renderTargetType = optionalParameter( options.USE_HALF_FLOAT, false ) ? THREE.HalfFloatType : THREE.FloatType;
var LinearClampParams = {
minFilter: THREE.LinearFilter,
magFilter: THREE.LinearFilter,
wrapS: THREE.ClampToEdgeWrapping,
wrapT: THREE.ClampToEdgeWrapping,
format: THREE.RGBAFormat,
stencilBuffer: false,
depthBuffer: false,
premultiplyAlpha: false,
type: renderTargetType
};
var NearestClampParams = {
minFilter: THREE.NearestFilter,
magFilter: THREE.NearestFilter,
wrapS: THREE.ClampToEdgeWrapping,
wrapT: THREE.ClampToEdgeWrapping,
format: THREE.RGBAFormat,
stencilBuffer: false,
depthBuffer: false,
premultiplyAlpha: false,
type: renderTargetType
};
var NearestRepeatParams = {
minFilter: THREE.NearestFilter,
magFilter: THREE.NearestFilter,
wrapS: THREE.RepeatWrapping,
wrapT: THREE.RepeatWrapping,
format: THREE.RGBAFormat,
stencilBuffer: false,
depthBuffer: false,
premultiplyAlpha: false,
type: renderTargetType
};
this.initialSpectrumFramebuffer = new THREE.WebGLRenderTarget( this.resolution, this.resolution, NearestRepeatParams );
this.spectrumFramebuffer = new THREE.WebGLRenderTarget( this.resolution, this.resolution, NearestClampParams );
this.pingPhaseFramebuffer = new THREE.WebGLRenderTarget( this.resolution, this.resolution, NearestClampParams );
this.pongPhaseFramebuffer = new THREE.WebGLRenderTarget( this.resolution, this.resolution, NearestClampParams );
this.pingTransformFramebuffer = new THREE.WebGLRenderTarget( this.resolution, this.resolution, NearestClampParams );
this.pongTransformFramebuffer = new THREE.WebGLRenderTarget( this.resolution, this.resolution, NearestClampParams );
this.displacementMapFramebuffer = new THREE.WebGLRenderTarget( this.resolution, this.resolution, LinearClampParams );
this.normalMapFramebuffer = new THREE.WebGLRenderTarget( this.resolution, this.resolution, LinearClampParams );
// Define shaders and constant uniforms
////////////////////////////////////////
// 0 - The vertex shader used in all of the simulation steps
var fullscreeenVertexShader = THREE.ShaderLib[ "ocean_sim_vertex" ];
// 1 - Horizontal wave vertices used for FFT
var oceanHorizontalShader = THREE.ShaderLib[ "ocean_subtransform" ];
var oceanHorizontalUniforms = THREE.UniformsUtils.clone( oceanHorizontalShader.uniforms );
this.materialOceanHorizontal = new THREE.ShaderMaterial( {
uniforms: oceanHorizontalUniforms,
vertexShader: fullscreeenVertexShader.vertexShader,
fragmentShader: "#define HORIZONTAL \n" + oceanHorizontalShader.fragmentShader
} );
this.materialOceanHorizontal.uniforms.u_transformSize = { value: this.resolution };
this.materialOceanHorizontal.uniforms.u_subtransformSize = { value: null };
this.materialOceanHorizontal.uniforms.u_input = { value: null };
this.materialOceanHorizontal.depthTest = false;
// 2 - Vertical wave vertices used for FFT
var oceanVerticalShader = THREE.ShaderLib[ "ocean_subtransform" ];
var oceanVerticalUniforms = THREE.UniformsUtils.clone( oceanVerticalShader.uniforms );
this.materialOceanVertical = new THREE.ShaderMaterial( {
uniforms: oceanVerticalUniforms,
vertexShader: fullscreeenVertexShader.vertexShader,
fragmentShader: oceanVerticalShader.fragmentShader
} );
this.materialOceanVertical.uniforms.u_transformSize = { value: this.resolution };
this.materialOceanVertical.uniforms.u_subtransformSize = { value: null };
this.materialOceanVertical.uniforms.u_input = { value: null };
this.materialOceanVertical.depthTest = false;
// 3 - Initial spectrum used to generate height map
var initialSpectrumShader = THREE.ShaderLib[ "ocean_initial_spectrum" ];
var initialSpectrumUniforms = THREE.UniformsUtils.clone( initialSpectrumShader.uniforms );
this.materialInitialSpectrum = new THREE.ShaderMaterial( {
uniforms: initialSpectrumUniforms,
vertexShader: fullscreeenVertexShader.vertexShader,
fragmentShader: initialSpectrumShader.fragmentShader
} );
this.materialInitialSpectrum.uniforms.u_wind = { value: new THREE.Vector2() };
this.materialInitialSpectrum.uniforms.u_resolution = { value: this.resolution };
this.materialInitialSpectrum.depthTest = false;
// 4 - Phases used to animate heightmap
var phaseShader = THREE.ShaderLib[ "ocean_phase" ];
var phaseUniforms = THREE.UniformsUtils.clone( phaseShader.uniforms );
this.materialPhase = new THREE.ShaderMaterial( {
uniforms: phaseUniforms,
vertexShader: fullscreeenVertexShader.vertexShader,
fragmentShader: phaseShader.fragmentShader
} );
this.materialPhase.uniforms.u_resolution = { value: this.resolution };
this.materialPhase.depthTest = false;
// 5 - Shader used to update spectrum
var spectrumShader = THREE.ShaderLib[ "ocean_spectrum" ];
var spectrumUniforms = THREE.UniformsUtils.clone( spectrumShader.uniforms );
this.materialSpectrum = new THREE.ShaderMaterial( {
uniforms: spectrumUniforms,
vertexShader: fullscreeenVertexShader.vertexShader,
fragmentShader: spectrumShader.fragmentShader
} );
this.materialSpectrum.uniforms.u_initialSpectrum = { value: null };
this.materialSpectrum.uniforms.u_resolution = { value: this.resolution };
this.materialSpectrum.depthTest = false;
// 6 - Shader used to update spectrum normals
var normalShader = THREE.ShaderLib[ "ocean_normals" ];
var normalUniforms = THREE.UniformsUtils.clone( normalShader.uniforms );
this.materialNormal = new THREE.ShaderMaterial( {
uniforms: normalUniforms,
vertexShader: fullscreeenVertexShader.vertexShader,
fragmentShader: normalShader.fragmentShader
} );
this.materialNormal.uniforms.u_displacementMap = { value: null };
this.materialNormal.uniforms.u_resolution = { value: this.resolution };
this.materialNormal.depthTest = false;
// 7 - Shader used to update normals
var oceanShader = THREE.ShaderLib[ "ocean_main" ];
var oceanUniforms = THREE.UniformsUtils.clone( oceanShader.uniforms );
this.materialOcean = new THREE.ShaderMaterial( {
uniforms: oceanUniforms,
vertexShader: oceanShader.vertexShader,
fragmentShader: oceanShader.fragmentShader
} );
// this.materialOcean.wireframe = true;
this.materialOcean.uniforms.u_geometrySize = { value: this.resolution };
this.materialOcean.uniforms.u_displacementMap = { value: this.displacementMapFramebuffer.texture };
this.materialOcean.uniforms.u_normalMap = { value: this.normalMapFramebuffer.texture };
this.materialOcean.uniforms.u_oceanColor = { value: this.oceanColor };
this.materialOcean.uniforms.u_skyColor = { value: this.skyColor };
this.materialOcean.uniforms.u_sunDirection = { value: new THREE.Vector3( this.sunDirectionX, this.sunDirectionY, this.sunDirectionZ ) };
this.materialOcean.uniforms.u_exposure = { value: this.exposure };
// Disable blending to prevent default premultiplied alpha values
this.materialOceanHorizontal.blending = 0;
this.materialOceanVertical.blending = 0;
this.materialInitialSpectrum.blending = 0;
this.materialPhase.blending = 0;
this.materialSpectrum.blending = 0;
this.materialNormal.blending = 0;
this.materialOcean.blending = 0;
// Create the simulation plane
this.screenQuad = new THREE.Mesh( new THREE.PlaneBufferGeometry( 2, 2 ) );
this.scene.add( this.screenQuad );
// Initialise spectrum data
this.generateSeedPhaseTexture();
// Generate the ocean mesh
this.generateMesh();
};
THREE.Ocean.prototype.generateMesh = function () {
var geometry = new THREE.PlaneBufferGeometry( this.geometrySize, this.geometrySize, this.geometryResolution, this.geometryResolution );
geometry.rotateX( - Math.PI / 2 );
this.oceanMesh = new THREE.Mesh( geometry, this.materialOcean );
};
THREE.Ocean.prototype.render = function () {
this.scene.overrideMaterial = null;
if ( this.changed )
this.renderInitialSpectrum();
this.renderWavePhase();
this.renderSpectrum();
this.renderSpectrumFFT();
this.renderNormalMap();
this.scene.overrideMaterial = null;
};
THREE.Ocean.prototype.generateSeedPhaseTexture = function() {
// Setup the seed texture
this.pingPhase = true;
var phaseArray = new window.Float32Array( this.resolution * this.resolution * 4 );
for ( var i = 0; i < this.resolution; i ++ ) {
for ( var j = 0; j < this.resolution; j ++ ) {
phaseArray[ i * this.resolution * 4 + j * 4 ] = Math.random() * 2.0 * Math.PI;
phaseArray[ i * this.resolution * 4 + j * 4 + 1 ] = 0.0;
phaseArray[ i * this.resolution * 4 + j * 4 + 2 ] = 0.0;
phaseArray[ i * this.resolution * 4 + j * 4 + 3 ] = 0.0;
}
}
this.pingPhaseTexture = new THREE.DataTexture( phaseArray, this.resolution, this.resolution, THREE.RGBAFormat );
this.pingPhaseTexture.wrapS = THREE.ClampToEdgeWrapping;
this.pingPhaseTexture.wrapT = THREE.ClampToEdgeWrapping;
this.pingPhaseTexture.type = THREE.FloatType;
this.pingPhaseTexture.needsUpdate = true;
};
THREE.Ocean.prototype.renderInitialSpectrum = function () {
this.scene.overrideMaterial = this.materialInitialSpectrum;
this.materialInitialSpectrum.uniforms.u_wind.value.set( this.windX, this.windY );
this.materialInitialSpectrum.uniforms.u_size.value = this.size;
this.renderer.render( this.scene, this.oceanCamera, this.initialSpectrumFramebuffer, true );
};
THREE.Ocean.prototype.renderWavePhase = function () {
this.scene.overrideMaterial = this.materialPhase;
this.screenQuad.material = this.materialPhase;
if ( this.initial ) {
this.materialPhase.uniforms.u_phases.value = this.pingPhaseTexture;
this.initial = false;
}else {
this.materialPhase.uniforms.u_phases.value = this.pingPhase ? this.pingPhaseFramebuffer.texture : this.pongPhaseFramebuffer.texture;
}
this.materialPhase.uniforms.u_deltaTime.value = this.deltaTime;
this.materialPhase.uniforms.u_size.value = this.size;
this.renderer.render( this.scene, this.oceanCamera, this.pingPhase ? this.pongPhaseFramebuffer : this.pingPhaseFramebuffer );
this.pingPhase = ! this.pingPhase;
};
THREE.Ocean.prototype.renderSpectrum = function () {
this.scene.overrideMaterial = this.materialSpectrum;
this.materialSpectrum.uniforms.u_initialSpectrum.value = this.initialSpectrumFramebuffer.texture;
this.materialSpectrum.uniforms.u_phases.value = this.pingPhase ? this.pingPhaseFramebuffer.texture : this.pongPhaseFramebuffer.texture;
this.materialSpectrum.uniforms.u_choppiness.value = this.choppiness;
this.materialSpectrum.uniforms.u_size.value = this.size;
this.renderer.render( this.scene, this.oceanCamera, this.spectrumFramebuffer );
};
THREE.Ocean.prototype.renderSpectrumFFT = function() {
// GPU FFT using Stockham formulation
var iterations = Math.log( this.resolution ) / Math.log( 2 ); // log2
this.scene.overrideMaterial = this.materialOceanHorizontal;
for ( var i = 0; i < iterations; i ++ ) {
if ( i === 0 ) {
this.materialOceanHorizontal.uniforms.u_input.value = this.spectrumFramebuffer.texture;
this.materialOceanHorizontal.uniforms.u_subtransformSize.value = Math.pow( 2, ( i % ( iterations ) ) + 1 );
this.renderer.render( this.scene, this.oceanCamera, this.pingTransformFramebuffer );
} else if ( i % 2 === 1 ) {
this.materialOceanHorizontal.uniforms.u_input.value = this.pingTransformFramebuffer.texture;
this.materialOceanHorizontal.uniforms.u_subtransformSize.value = Math.pow( 2, ( i % ( iterations ) ) + 1 );
this.renderer.render( this.scene, this.oceanCamera, this.pongTransformFramebuffer );
} else {
this.materialOceanHorizontal.uniforms.u_input.value = this.pongTransformFramebuffer.texture;
this.materialOceanHorizontal.uniforms.u_subtransformSize.value = Math.pow( 2, ( i % ( iterations ) ) + 1 );
this.renderer.render( this.scene, this.oceanCamera, this.pingTransformFramebuffer );
}
}
this.scene.overrideMaterial = this.materialOceanVertical;
for ( var i = iterations; i < iterations * 2; i ++ ) {
if ( i === iterations * 2 - 1 ) {
this.materialOceanVertical.uniforms.u_input.value = ( iterations % 2 === 0 ) ? this.pingTransformFramebuffer.texture : this.pongTransformFramebuffer.texture;
this.materialOceanVertical.uniforms.u_subtransformSize.value = Math.pow( 2, ( i % ( iterations ) ) + 1 );
this.renderer.render( this.scene, this.oceanCamera, this.displacementMapFramebuffer );
} else if ( i % 2 === 1 ) {
this.materialOceanVertical.uniforms.u_input.value = this.pingTransformFramebuffer.texture;
this.materialOceanVertical.uniforms.u_subtransformSize.value = Math.pow( 2, ( i % ( iterations ) ) + 1 );
this.renderer.render( this.scene, this.oceanCamera, this.pongTransformFramebuffer );
} else {
this.materialOceanVertical.uniforms.u_input.value = this.pongTransformFramebuffer.texture;
this.materialOceanVertical.uniforms.u_subtransformSize.value = Math.pow( 2, ( i % ( iterations ) ) + 1 );
this.renderer.render( this.scene, this.oceanCamera, this.pingTransformFramebuffer );
}
}
};
THREE.Ocean.prototype.renderNormalMap = function () {
this.scene.overrideMaterial = this.materialNormal;
if ( this.changed ) this.materialNormal.uniforms.u_size.value = this.size;
this.materialNormal.uniforms.u_displacementMap.value = this.displacementMapFramebuffer.texture;
this.renderer.render( this.scene, this.oceanCamera, this.normalMapFramebuffer, true );
};

2137
node_modules/three/examples/js/Octree.js generated vendored Normal file

File diff suppressed because it is too large Load Diff

23
node_modules/three/examples/js/PRNG.js generated vendored Normal file
View File

@@ -0,0 +1,23 @@
// Park-Miller-Carta Pseudo-Random Number Generator
// https://github.com/pnitsch/BitmapData.js/blob/master/js/BitmapData.js
var PRNG = function () {
this.seed = 1;
this.next = function() {
return ( this.gen() / 2147483647 );
};
this.nextRange = function( min, max ) {
return min + ( ( max - min ) * this.next() )
};
this.gen = function() {
return this.seed = ( this.seed * 16807 ) % 2147483647;
};
};

266
node_modules/three/examples/js/ParametricGeometries.js generated vendored Normal file
View File

@@ -0,0 +1,266 @@
/*
* @author zz85
*
* Experimenting of primitive geometry creation using Surface Parametric equations
*
*/
THREE.ParametricGeometries = {
klein: function ( v, u ) {
u *= Math.PI;
v *= 2 * Math.PI;
u = u * 2;
var x, y, z;
if ( u < Math.PI ) {
x = 3 * Math.cos( u ) * ( 1 + Math.sin( u ) ) + ( 2 * ( 1 - Math.cos( u ) / 2 ) ) * Math.cos( u ) * Math.cos( v );
z = - 8 * Math.sin( u ) - 2 * ( 1 - Math.cos( u ) / 2 ) * Math.sin( u ) * Math.cos( v );
} else {
x = 3 * Math.cos( u ) * ( 1 + Math.sin( u ) ) + ( 2 * ( 1 - Math.cos( u ) / 2 ) ) * Math.cos( v + Math.PI );
z = - 8 * Math.sin( u );
}
y = - 2 * ( 1 - Math.cos( u ) / 2 ) * Math.sin( v );
return new THREE.Vector3( x, y, z );
},
plane: function ( width, height ) {
return function( u, v ) {
var x = u * width;
var y = 0;
var z = v * height;
return new THREE.Vector3( x, y, z );
};
},
mobius: function( u, t ) {
// flat mobius strip
// http://www.wolframalpha.com/input/?i=M%C3%B6bius+strip+parametric+equations&lk=1&a=ClashPrefs_*Surface.MoebiusStrip.SurfaceProperty.ParametricEquations-
u = u - 0.5;
var v = 2 * Math.PI * t;
var x, y, z;
var a = 2;
x = Math.cos( v ) * ( a + u * Math.cos( v / 2 ) );
y = Math.sin( v ) * ( a + u * Math.cos( v / 2 ) );
z = u * Math.sin( v / 2 );
return new THREE.Vector3( x, y, z );
},
mobius3d: function( u, t ) {
// volumetric mobius strip
u *= Math.PI;
t *= 2 * Math.PI;
u = u * 2;
var phi = u / 2;
var major = 2.25, a = 0.125, b = 0.65;
var x, y, z;
x = a * Math.cos( t ) * Math.cos( phi ) - b * Math.sin( t ) * Math.sin( phi );
z = a * Math.cos( t ) * Math.sin( phi ) + b * Math.sin( t ) * Math.cos( phi );
y = ( major + x ) * Math.sin( u );
x = ( major + x ) * Math.cos( u );
return new THREE.Vector3( x, y, z );
}
};
/*********************************************
*
* Parametric Replacement for TubeGeometry
*
*********************************************/
THREE.ParametricGeometries.TubeGeometry = function( path, segments, radius, segmentsRadius, closed, debug ) {
this.path = path;
this.segments = segments || 64;
this.radius = radius || 1;
this.segmentsRadius = segmentsRadius || 8;
this.closed = closed || false;
if ( debug ) this.debug = new THREE.Object3D();
var scope = this,
tangent, normal, binormal,
numpoints = this.segments + 1,
x, y, z, tx, ty, tz, u, v,
cx, cy, pos, pos2 = new THREE.Vector3(),
i, j, ip, jp, a, b, c, d, uva, uvb, uvc, uvd;
var frames = path.computeFrenetFrames( segments, closed ),
tangents = frames.tangents,
normals = frames.normals,
binormals = frames.binormals;
// proxy internals
this.tangents = tangents;
this.normals = normals;
this.binormals = binormals;
var ParametricTube = function( u, v ) {
v *= 2 * Math.PI;
i = u * ( numpoints - 1 );
i = Math.floor( i );
pos = path.getPointAt( u );
tangent = tangents[ i ];
normal = normals[ i ];
binormal = binormals[ i ];
if ( scope.debug ) {
scope.debug.add( new THREE.ArrowHelper( tangent, pos, radius, 0x0000ff ) );
scope.debug.add( new THREE.ArrowHelper( normal, pos, radius, 0xff0000 ) );
scope.debug.add( new THREE.ArrowHelper( binormal, pos, radius, 0x00ff00 ) );
}
cx = - scope.radius * Math.cos( v ); // TODO: Hack: Negating it so it faces outside.
cy = scope.radius * Math.sin( v );
pos2.copy( pos );
pos2.x += cx * normal.x + cy * binormal.x;
pos2.y += cx * normal.y + cy * binormal.y;
pos2.z += cx * normal.z + cy * binormal.z;
return pos2.clone();
};
THREE.ParametricGeometry.call( this, ParametricTube, segments, segmentsRadius );
};
THREE.ParametricGeometries.TubeGeometry.prototype = Object.create( THREE.Geometry.prototype );
THREE.ParametricGeometries.TubeGeometry.prototype.constructor = THREE.ParametricGeometries.TubeGeometry;
/*********************************************
*
* Parametric Replacement for TorusKnotGeometry
*
*********************************************/
THREE.ParametricGeometries.TorusKnotGeometry = function ( radius, tube, segmentsT, segmentsR, p, q ) {
var scope = this;
this.radius = radius || 200;
this.tube = tube || 40;
this.segmentsT = segmentsT || 64;
this.segmentsR = segmentsR || 8;
this.p = p || 2;
this.q = q || 3;
function TorusKnotCurve() {}
TorusKnotCurve.prototype = Object.create( THREE.Curve.prototype );
TorusKnotCurve.prototype.constructor = TorusKnotCurve;
TorusKnotCurve.prototype.getPoint = function( t ){
t *= Math.PI * 2;
var r = 0.5;
var x = ( 1 + r * Math.cos( q * t ) ) * Math.cos( p * t );
var y = ( 1 + r * Math.cos( q * t ) ) * Math.sin( p * t );
var z = r * Math.sin( q * t );
return new THREE.Vector3( x, y, z ).multiplyScalar( radius );
};
var segments = segmentsT;
var radiusSegments = segmentsR;
var extrudePath = new TorusKnotCurve();
THREE.ParametricGeometries.TubeGeometry.call( this, extrudePath, segments, tube, radiusSegments, true, false );
};
THREE.ParametricGeometries.TorusKnotGeometry.prototype = Object.create( THREE.Geometry.prototype );
THREE.ParametricGeometries.TorusKnotGeometry.prototype.constructor = THREE.ParametricGeometries.TorusKnotGeometry;
/*********************************************
*
* Parametric Replacement for SphereGeometry
*
*********************************************/
THREE.ParametricGeometries.SphereGeometry = function( size, u, v ) {
function sphere( u, v ) {
u *= Math.PI;
v *= 2 * Math.PI;
var x = size * Math.sin( u ) * Math.cos( v );
var y = size * Math.sin( u ) * Math.sin( v );
var z = size * Math.cos( u );
return new THREE.Vector3( x, y, z );
}
THREE.ParametricGeometry.call( this, sphere, u, v, ! true );
};
THREE.ParametricGeometries.SphereGeometry.prototype = Object.create( THREE.Geometry.prototype );
THREE.ParametricGeometries.SphereGeometry.prototype.constructor = THREE.ParametricGeometries.SphereGeometry;
/*********************************************
*
* Parametric Replacement for PlaneGeometry
*
*********************************************/
THREE.ParametricGeometries.PlaneGeometry = function( width, depth, segmentsWidth, segmentsDepth ) {
function plane( u, v ) {
var x = u * width;
var y = 0;
var z = v * depth;
return new THREE.Vector3( x, y, z );
}
THREE.ParametricGeometry.call( this, plane, segmentsWidth, segmentsDepth );
};
THREE.ParametricGeometries.PlaneGeometry.prototype = Object.create( THREE.Geometry.prototype );
THREE.ParametricGeometries.PlaneGeometry.prototype.constructor = THREE.ParametricGeometries.PlaneGeometry;

544
node_modules/three/examples/js/RollerCoaster.js generated vendored Normal file
View File

@@ -0,0 +1,544 @@
/**
* @author mrdoob / http://mrdoob.com/
*/
var RollerCoasterGeometry = function ( curve, size ) {
THREE.BufferGeometry.call( this );
var vertices = [];
var normals = [];
var colors = [];
var color1 = [ 1, 1, 1 ];
var color2 = [ 1, 1, 0 ];
var up = new THREE.Vector3( 0, 1, 0 );
var forward = new THREE.Vector3();
var right = new THREE.Vector3();
var quaternion = new THREE.Quaternion();
var prevQuaternion = new THREE.Quaternion();
prevQuaternion.setFromAxisAngle( up , Math.PI / 2 );
var point = new THREE.Vector3();
var prevPoint = new THREE.Vector3();
prevPoint.copy( curve.getPointAt( 0 ) );
// shapes
var step = [
new THREE.Vector3( -2.25, 0, 0 ),
new THREE.Vector3( 0, -0.5, 0 ),
new THREE.Vector3( 0, -1.75, 0 ),
new THREE.Vector3( 0, -0.5, 0 ),
new THREE.Vector3( 2.25, 0, 0 ),
new THREE.Vector3( 0, -1.75, 0 )
];
var PI2 = Math.PI * 2;
var sides = 5;
var tube1 = [];
for ( var i = 0; i < sides; i ++ ) {
var angle = ( i / sides ) * PI2;
tube1.push( new THREE.Vector3( Math.sin( angle ) * 0.6, Math.cos( angle ) * 0.6, 0 ) );
}
var sides = 6;
var tube2 = [];
for ( var i = 0; i < sides; i ++ ) {
var angle = ( i / sides ) * PI2;
tube2.push( new THREE.Vector3( Math.sin( angle ) * 0.25, Math.cos( angle ) * 0.25, 0 ) );
}
var vector = new THREE.Vector3();
var normal = new THREE.Vector3();
var drawShape = function ( shape, color ) {
normal.set( 0, 0, -1 ).applyQuaternion( quaternion );
for ( var j = 0; j < shape.length; j ++ ) {
vector.copy( shape[ j ] );
vector.applyQuaternion( quaternion );
vector.add( point );
vertices.push( vector.x, vector.y, vector.z );
normals.push( normal.x, normal.y, normal.z );
colors.push( color[ 0 ], color[ 1 ], color[ 2 ] );
}
normal.set( 0, 0, 1 ).applyQuaternion( quaternion );
for ( var j = shape.length - 1; j >= 0; j -- ) {
vector.copy( shape[ j ] );
vector.applyQuaternion( quaternion );
vector.add( point );
vertices.push( vector.x, vector.y, vector.z );
normals.push( normal.x, normal.y, normal.z );
colors.push( color[ 0 ], color[ 1 ], color[ 2 ] );
}
};
var vector1 = new THREE.Vector3();
var vector2 = new THREE.Vector3();
var vector3 = new THREE.Vector3();
var vector4 = new THREE.Vector3();
var normal1 = new THREE.Vector3();
var normal2 = new THREE.Vector3();
var normal3 = new THREE.Vector3();
var normal4 = new THREE.Vector3();
var extrudeShape = function ( shape, offset, color ) {
for ( var j = 0, jl = shape.length; j < jl; j ++ ) {
var point1 = shape[ j ];
var point2 = shape[ ( j + 1 ) % jl ];
vector1.copy( point1 ).add( offset );
vector1.applyQuaternion( quaternion );
vector1.add( point );
vector2.copy( point2 ).add( offset );
vector2.applyQuaternion( quaternion );
vector2.add( point );
vector3.copy( point2 ).add( offset );
vector3.applyQuaternion( prevQuaternion );
vector3.add( prevPoint );
vector4.copy( point1 ).add( offset );
vector4.applyQuaternion( prevQuaternion );
vector4.add( prevPoint );
vertices.push( vector1.x, vector1.y, vector1.z );
vertices.push( vector2.x, vector2.y, vector2.z );
vertices.push( vector4.x, vector4.y, vector4.z );
vertices.push( vector2.x, vector2.y, vector2.z );
vertices.push( vector3.x, vector3.y, vector3.z );
vertices.push( vector4.x, vector4.y, vector4.z );
//
normal1.copy( point1 );
normal1.applyQuaternion( quaternion );
normal1.normalize();
normal2.copy( point2 );
normal2.applyQuaternion( quaternion );
normal2.normalize();
normal3.copy( point2 );
normal3.applyQuaternion( prevQuaternion );
normal3.normalize();
normal4.copy( point1 );
normal4.applyQuaternion( prevQuaternion );
normal4.normalize();
normals.push( normal1.x, normal1.y, normal1.z );
normals.push( normal2.x, normal2.y, normal2.z );
normals.push( normal4.x, normal4.y, normal4.z );
normals.push( normal2.x, normal2.y, normal2.z );
normals.push( normal3.x, normal3.y, normal3.z );
normals.push( normal4.x, normal4.y, normal4.z );
colors.push( color[ 0 ], color[ 1 ], color[ 2 ] );
colors.push( color[ 0 ], color[ 1 ], color[ 2 ] );
colors.push( color[ 0 ], color[ 1 ], color[ 2 ] );
colors.push( color[ 0 ], color[ 1 ], color[ 2 ] );
colors.push( color[ 0 ], color[ 1 ], color[ 2 ] );
colors.push( color[ 0 ], color[ 1 ], color[ 2 ] );
}
};
var offset = new THREE.Vector3();
for ( var i = 1; i <= size; i ++ ) {
point.copy( curve.getPointAt( i / size ) );
up.set( 0, 1, 0 );
forward.subVectors( point, prevPoint ).normalize();
right.crossVectors( up, forward ).normalize();
up.crossVectors( forward, right );
var angle = Math.atan2( forward.x, forward.z );
quaternion.setFromAxisAngle( up, angle );
if ( i % 2 === 0 ) {
drawShape( step, color2 );
}
extrudeShape( tube1, offset.set( 0, -1.25, 0 ), color2 );
extrudeShape( tube2, offset.set( 2, 0, 0 ), color1 );
extrudeShape( tube2, offset.set( -2, 0, 0 ), color1 );
prevPoint.copy( point );
prevQuaternion.copy( quaternion );
}
// console.log( vertices.length );
this.addAttribute( 'position', new THREE.BufferAttribute( new Float32Array( vertices ), 3 ) );
this.addAttribute( 'normal', new THREE.BufferAttribute( new Float32Array( normals ), 3 ) );
this.addAttribute( 'color', new THREE.BufferAttribute( new Float32Array( colors ), 3 ) );
};
RollerCoasterGeometry.prototype = Object.create( THREE.BufferGeometry.prototype );
var RollerCoasterLiftersGeometry = function ( curve, size ) {
THREE.BufferGeometry.call( this );
var vertices = [];
var normals = [];
var quaternion = new THREE.Quaternion();
var up = new THREE.Vector3( 0, 1, 0 );
var point = new THREE.Vector3();
var tangent = new THREE.Vector3();
// shapes
var tube1 = [
new THREE.Vector3( 0, 0.5, -0.5 ),
new THREE.Vector3( 0, 0.5, 0.5 ),
new THREE.Vector3( 0, -0.5, 0 )
];
var tube2 = [
new THREE.Vector3( -0.5, 0, 0.5 ),
new THREE.Vector3( -0.5, 0, -0.5 ),
new THREE.Vector3( 0.5, 0, 0 )
];
var tube3 = [
new THREE.Vector3( 0.5, 0, -0.5 ),
new THREE.Vector3( 0.5, 0, 0.5 ),
new THREE.Vector3( -0.5, 0, 0 )
];
var vector1 = new THREE.Vector3();
var vector2 = new THREE.Vector3();
var vector3 = new THREE.Vector3();
var vector4 = new THREE.Vector3();
var normal1 = new THREE.Vector3();
var normal2 = new THREE.Vector3();
var normal3 = new THREE.Vector3();
var normal4 = new THREE.Vector3();
var extrudeShape = function ( shape, fromPoint, toPoint ) {
for ( var j = 0, jl = shape.length; j < jl; j ++ ) {
var point1 = shape[ j ];
var point2 = shape[ ( j + 1 ) % jl ];
vector1.copy( point1 );
vector1.applyQuaternion( quaternion );
vector1.add( fromPoint );
vector2.copy( point2 );
vector2.applyQuaternion( quaternion );
vector2.add( fromPoint );
vector3.copy( point2 );
vector3.applyQuaternion( quaternion );
vector3.add( toPoint );
vector4.copy( point1 );
vector4.applyQuaternion( quaternion );
vector4.add( toPoint );
vertices.push( vector1.x, vector1.y, vector1.z );
vertices.push( vector2.x, vector2.y, vector2.z );
vertices.push( vector4.x, vector4.y, vector4.z );
vertices.push( vector2.x, vector2.y, vector2.z );
vertices.push( vector3.x, vector3.y, vector3.z );
vertices.push( vector4.x, vector4.y, vector4.z );
//
normal1.copy( point1 );
normal1.applyQuaternion( quaternion );
normal1.normalize();
normal2.copy( point2 );
normal2.applyQuaternion( quaternion );
normal2.normalize();
normal3.copy( point2 );
normal3.applyQuaternion( quaternion );
normal3.normalize();
normal4.copy( point1 );
normal4.applyQuaternion( quaternion );
normal4.normalize();
normals.push( normal1.x, normal1.y, normal1.z );
normals.push( normal2.x, normal2.y, normal2.z );
normals.push( normal4.x, normal4.y, normal4.z );
normals.push( normal2.x, normal2.y, normal2.z );
normals.push( normal3.x, normal3.y, normal3.z );
normals.push( normal4.x, normal4.y, normal4.z );
}
};
var fromPoint = new THREE.Vector3();
var toPoint = new THREE.Vector3();
for ( var i = 1; i <= size; i ++ ) {
point.copy( curve.getPointAt( i / size ) );
tangent.copy( curve.getTangentAt( i / size ) );
var angle = Math.atan2( tangent.x, tangent.z );
quaternion.setFromAxisAngle( up, angle );
//
if ( point.y > 100 ) {
fromPoint.set( -7.5, -3.5, 0 );
fromPoint.applyQuaternion( quaternion );
fromPoint.add( point );
toPoint.set( 7.5, -3.5, 0 );
toPoint.applyQuaternion( quaternion );
toPoint.add( point );
extrudeShape( tube1, fromPoint, toPoint );
fromPoint.set( -7, -3, 0 );
fromPoint.applyQuaternion( quaternion );
fromPoint.add( point );
toPoint.set( -7, -point.y, 0 );
toPoint.applyQuaternion( quaternion );
toPoint.add( point );
extrudeShape( tube2, fromPoint, toPoint );
fromPoint.set( 7, -3, 0 );
fromPoint.applyQuaternion( quaternion );
fromPoint.add( point );
toPoint.set( 7, -point.y, 0 );
toPoint.applyQuaternion( quaternion );
toPoint.add( point );
extrudeShape( tube3, fromPoint, toPoint );
} else {
fromPoint.set( 0, -2, 0 );
fromPoint.applyQuaternion( quaternion );
fromPoint.add( point );
toPoint.set( 0, -point.y, 0 );
toPoint.applyQuaternion( quaternion );
toPoint.add( point );
extrudeShape( tube3, fromPoint, toPoint );
}
}
this.addAttribute( 'position', new THREE.BufferAttribute( new Float32Array( vertices ), 3 ) );
this.addAttribute( 'normal', new THREE.BufferAttribute( new Float32Array( normals ), 3 ) );
};
RollerCoasterLiftersGeometry.prototype = Object.create( THREE.BufferGeometry.prototype );
var RollerCoasterShadowGeometry = function ( curve, size ) {
THREE.BufferGeometry.call( this );
var vertices = [];
var up = new THREE.Vector3( 0, 1, 0 );
var forward = new THREE.Vector3();
var quaternion = new THREE.Quaternion();
var prevQuaternion = new THREE.Quaternion();
prevQuaternion.setFromAxisAngle( up , Math.PI / 2 );
var point = new THREE.Vector3();
var prevPoint = new THREE.Vector3();
prevPoint.copy( curve.getPointAt( 0 ) );
prevPoint.y = 0;
var vector1 = new THREE.Vector3();
var vector2 = new THREE.Vector3();
var vector3 = new THREE.Vector3();
var vector4 = new THREE.Vector3();
for ( var i = 1; i <= size; i ++ ) {
point.copy( curve.getPointAt( i / size ) );
point.y = 0;
forward.subVectors( point, prevPoint );
var angle = Math.atan2( forward.x, forward.z );
quaternion.setFromAxisAngle( up, angle );
vector1.set( -3, 0, 0 );
vector1.applyQuaternion( quaternion );
vector1.add( point );
vector2.set( 3, 0, 0 );
vector2.applyQuaternion( quaternion );
vector2.add( point );
vector3.set( 3, 0, 0 );
vector3.applyQuaternion( prevQuaternion );
vector3.add( prevPoint );
vector4.set( -3, 0, 0 );
vector4.applyQuaternion( prevQuaternion );
vector4.add( prevPoint );
vertices.push( vector1.x, vector1.y, vector1.z );
vertices.push( vector2.x, vector2.y, vector2.z );
vertices.push( vector4.x, vector4.y, vector4.z );
vertices.push( vector2.x, vector2.y, vector2.z );
vertices.push( vector3.x, vector3.y, vector3.z );
vertices.push( vector4.x, vector4.y, vector4.z );
prevPoint.copy( point );
prevQuaternion.copy( quaternion );
}
this.addAttribute( 'position', new THREE.BufferAttribute( new Float32Array( vertices ), 3 ) );
};
RollerCoasterShadowGeometry.prototype = Object.create( THREE.BufferGeometry.prototype );
var SkyGeometry = function () {
THREE.BufferGeometry.call( this );
var vertices = [];
for ( var i = 0; i < 100; i ++ ) {
var x = Math.random() * 8000 - 4000;
var y = Math.random() * 500 + 500;
var z = Math.random() * 8000 - 4000;
var size = Math.random() * 400 + 200;
vertices.push( x - size, y, z - size );
vertices.push( x + size, y, z - size );
vertices.push( x - size, y, z + size );
vertices.push( x + size, y, z - size );
vertices.push( x + size, y, z + size );
vertices.push( x - size, y, z + size );
}
this.addAttribute( 'position', new THREE.BufferAttribute( new Float32Array( vertices ), 3 ) );
};
SkyGeometry.prototype = Object.create( THREE.BufferGeometry.prototype );
var TreesGeometry = function ( landscape ) {
THREE.BufferGeometry.call( this );
var vertices = [];
var colors = [];
var raycaster = new THREE.Raycaster();
raycaster.ray.direction.set( 0, -1, 0 );
for ( var i = 0; i < 2000; i ++ ) {
var x = Math.random() * 5000 - 2500;
var z = Math.random() * 5000 - 2500;
raycaster.ray.origin.set( x, 500, z );
var intersections = raycaster.intersectObject( landscape );
if ( intersections.length === 0 ) continue;
var y = intersections[ 0 ].point.y;
var height = Math.random() * 50 + 5;
var angle = Math.random() * Math.PI * 2;
vertices.push( x + Math.sin( angle ) * 10, y, z + Math.cos( angle ) * 10 );
vertices.push( x, y + height, z );
vertices.push( x + Math.sin( angle + Math.PI ) * 10, y, z + Math.cos( angle + Math.PI ) * 10 );
angle += Math.PI / 2;
vertices.push( x + Math.sin( angle ) * 10, y, z + Math.cos( angle ) * 10 );
vertices.push( x, y + height, z );
vertices.push( x + Math.sin( angle + Math.PI ) * 10, y, z + Math.cos( angle + Math.PI ) * 10 );
var random = Math.random() * 0.1;
for ( var j = 0; j < 6; j ++ ) {
colors.push( 0.2 + random, 0.4 + random, 0 );
}
}
this.addAttribute( 'position', new THREE.BufferAttribute( new Float32Array( vertices ), 3 ) );
this.addAttribute( 'color', new THREE.BufferAttribute( new Float32Array( colors ), 3 ) );
};
TreesGeometry.prototype = Object.create( THREE.BufferGeometry.prototype );

295
node_modules/three/examples/js/ShaderGodRays.js generated vendored Normal file
View File

@@ -0,0 +1,295 @@
/**
* @author huwb / http://huwbowles.com/
*
* God-rays (crepuscular rays)
*
* Similar implementation to the one used by Crytek for CryEngine 2 [Sousa2008].
* Blurs a mask generated from the depth map along radial lines emanating from the light
* source. The blur repeatedly applies a blur filter of increasing support but constant
* sample count to produce a blur filter with large support.
*
* My implementation performs 3 passes, similar to the implementation from Sousa. I found
* just 6 samples per pass produced acceptible results. The blur is applied three times,
* with decreasing filter support. The result is equivalent to a single pass with
* 6*6*6 = 216 samples.
*
* References:
*
* Sousa2008 - Crysis Next Gen Effects, GDC2008, http://www.crytek.com/sites/default/files/GDC08_SousaT_CrysisEffects.ppt
*/
THREE.ShaderGodRays = {
/**
* The god-ray generation shader.
*
* First pass:
*
* The input is the depth map. I found that the output from the
* THREE.MeshDepthMaterial material was directly suitable without
* requiring any treatment whatsoever.
*
* The depth map is blurred along radial lines towards the "sun". The
* output is written to a temporary render target (I used a 1/4 sized
* target).
*
* Pass two & three:
*
* The results of the previous pass are re-blurred, each time with a
* decreased distance between samples.
*/
'godrays_generate': {
uniforms: {
tInput: {
value: null
},
fStepSize: {
value: 1.0
},
vSunPositionScreenSpace: {
value: new THREE.Vector2( 0.5, 0.5 )
}
},
vertexShader: [
"varying vec2 vUv;",
"void main() {",
"vUv = uv;",
"gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",
"}"
].join( "\n" ),
fragmentShader: [
"#define TAPS_PER_PASS 6.0",
"varying vec2 vUv;",
"uniform sampler2D tInput;",
"uniform vec2 vSunPositionScreenSpace;",
"uniform float fStepSize;", // filter step size
"void main() {",
// delta from current pixel to "sun" position
"vec2 delta = vSunPositionScreenSpace - vUv;",
"float dist = length( delta );",
// Step vector (uv space)
"vec2 stepv = fStepSize * delta / dist;",
// Number of iterations between pixel and sun
"float iters = dist/fStepSize;",
"vec2 uv = vUv.xy;",
"float col = 0.0;",
// This breaks ANGLE in Chrome 22
// - see http://code.google.com/p/chromium/issues/detail?id=153105
/*
// Unrolling didnt do much on my hardware (ATI Mobility Radeon 3450),
// so i've just left the loop
"for ( float i = 0.0; i < TAPS_PER_PASS; i += 1.0 ) {",
// Accumulate samples, making sure we dont walk past the light source.
// The check for uv.y < 1 would not be necessary with "border" UV wrap
// mode, with a black border colour. I don't think this is currently
// exposed by three.js. As a result there might be artifacts when the
// sun is to the left, right or bottom of screen as these cases are
// not specifically handled.
"col += ( i <= iters && uv.y < 1.0 ? texture2D( tInput, uv ).r : 0.0 );",
"uv += stepv;",
"}",
*/
// Unrolling loop manually makes it work in ANGLE
"if ( 0.0 <= iters && uv.y < 1.0 ) col += texture2D( tInput, uv ).r;",
"uv += stepv;",
"if ( 1.0 <= iters && uv.y < 1.0 ) col += texture2D( tInput, uv ).r;",
"uv += stepv;",
"if ( 2.0 <= iters && uv.y < 1.0 ) col += texture2D( tInput, uv ).r;",
"uv += stepv;",
"if ( 3.0 <= iters && uv.y < 1.0 ) col += texture2D( tInput, uv ).r;",
"uv += stepv;",
"if ( 4.0 <= iters && uv.y < 1.0 ) col += texture2D( tInput, uv ).r;",
"uv += stepv;",
"if ( 5.0 <= iters && uv.y < 1.0 ) col += texture2D( tInput, uv ).r;",
"uv += stepv;",
// Should technically be dividing by 'iters', but 'TAPS_PER_PASS' smooths out
// objectionable artifacts, in particular near the sun position. The side
// effect is that the result is darker than it should be around the sun, as
// TAPS_PER_PASS is greater than the number of samples actually accumulated.
// When the result is inverted (in the shader 'godrays_combine', this produces
// a slight bright spot at the position of the sun, even when it is occluded.
"gl_FragColor = vec4( col/TAPS_PER_PASS );",
"gl_FragColor.a = 1.0;",
"}"
].join( "\n" )
},
/**
* Additively applies god rays from texture tGodRays to a background (tColors).
* fGodRayIntensity attenuates the god rays.
*/
'godrays_combine': {
uniforms: {
tColors: {
value: null
},
tGodRays: {
value: null
},
fGodRayIntensity: {
value: 0.69
},
vSunPositionScreenSpace: {
value: new THREE.Vector2( 0.5, 0.5 )
}
},
vertexShader: [
"varying vec2 vUv;",
"void main() {",
"vUv = uv;",
"gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",
"}"
].join( "\n" ),
fragmentShader: [
"varying vec2 vUv;",
"uniform sampler2D tColors;",
"uniform sampler2D tGodRays;",
"uniform vec2 vSunPositionScreenSpace;",
"uniform float fGodRayIntensity;",
"void main() {",
// Since THREE.MeshDepthMaterial renders foreground objects white and background
// objects black, the god-rays will be white streaks. Therefore value is inverted
// before being combined with tColors
"gl_FragColor = texture2D( tColors, vUv ) + fGodRayIntensity * vec4( 1.0 - texture2D( tGodRays, vUv ).r );",
"gl_FragColor.a = 1.0;",
"}"
].join( "\n" )
},
/**
* A dodgy sun/sky shader. Makes a bright spot at the sun location. Would be
* cheaper/faster/simpler to implement this as a simple sun sprite.
*/
'godrays_fake_sun': {
uniforms: {
vSunPositionScreenSpace: {
value: new THREE.Vector2( 0.5, 0.5 )
},
fAspect: {
value: 1.0
},
sunColor: {
value: new THREE.Color( 0xffee00 )
},
bgColor: {
value: new THREE.Color( 0x000000 )
}
},
vertexShader: [
"varying vec2 vUv;",
"void main() {",
"vUv = uv;",
"gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",
"}"
].join( "\n" ),
fragmentShader: [
"varying vec2 vUv;",
"uniform vec2 vSunPositionScreenSpace;",
"uniform float fAspect;",
"uniform vec3 sunColor;",
"uniform vec3 bgColor;",
"void main() {",
"vec2 diff = vUv - vSunPositionScreenSpace;",
// Correct for aspect ratio
"diff.x *= fAspect;",
"float prop = clamp( length( diff ) / 0.5, 0.0, 1.0 );",
"prop = 0.35 * pow( 1.0 - prop, 3.0 );",
"gl_FragColor.xyz = mix( sunColor, bgColor, 1.0 - prop );",
"gl_FragColor.w = 1.0;",
"}"
].join( "\n" )
}
};

698
node_modules/three/examples/js/ShaderSkin.js generated vendored Normal file
View File

@@ -0,0 +1,698 @@
/**
* @author alteredq / http://alteredqualia.com/
*
*/
THREE.ShaderSkin = {
/* ------------------------------------------------------------------------------------------
// Simple skin shader
// - per-pixel Blinn-Phong diffuse term mixed with half-Lambert wrap-around term (per color component)
// - physically based specular term (Kelemen/Szirmay-Kalos specular reflectance)
//
// - diffuse map
// - bump map
// - specular map
// - point, directional and hemisphere lights (use with "lights: true" material option)
// - fog (use with "fog: true" material option)
// - shadow maps
//
// ------------------------------------------------------------------------------------------ */
'skinSimple' : {
uniforms: THREE.UniformsUtils.merge( [
THREE.UniformsLib[ "fog" ],
THREE.UniformsLib[ "lights" ],
{
"enableBump": { value: 0 },
"enableSpecular": { value: 0 },
"tDiffuse": { value: null },
"tBeckmann": { value: null },
"diffuse": { value: new THREE.Color( 0xeeeeee ) },
"specular": { value: new THREE.Color( 0x111111 ) },
"opacity": { value: 1 },
"uRoughness": { value: 0.15 },
"uSpecularBrightness": { value: 0.75 },
"bumpMap": { value: null },
"bumpScale": { value: 1 },
"specularMap": { value: null },
"offsetRepeat": { value: new THREE.Vector4( 0, 0, 1, 1 ) },
"uWrapRGB": { value: new THREE.Vector3( 0.75, 0.375, 0.1875 ) }
}
] ),
fragmentShader: [
"#define USE_BUMPMAP",
"uniform bool enableBump;",
"uniform bool enableSpecular;",
"uniform vec3 diffuse;",
"uniform vec3 specular;",
"uniform float opacity;",
"uniform float uRoughness;",
"uniform float uSpecularBrightness;",
"uniform vec3 uWrapRGB;",
"uniform sampler2D tDiffuse;",
"uniform sampler2D tBeckmann;",
"uniform sampler2D specularMap;",
"varying vec3 vNormal;",
"varying vec2 vUv;",
"varying vec3 vViewPosition;",
THREE.ShaderChunk[ "common" ],
THREE.ShaderChunk[ "bsdfs" ],
THREE.ShaderChunk[ "packing" ],
THREE.ShaderChunk[ "lights_pars" ],
THREE.ShaderChunk[ "shadowmap_pars_fragment" ],
THREE.ShaderChunk[ "fog_pars_fragment" ],
THREE.ShaderChunk[ "bumpmap_pars_fragment" ],
// Fresnel term
"float fresnelReflectance( vec3 H, vec3 V, float F0 ) {",
"float base = 1.0 - dot( V, H );",
"float exponential = pow( base, 5.0 );",
"return exponential + F0 * ( 1.0 - exponential );",
"}",
// Kelemen/Szirmay-Kalos specular BRDF
"float KS_Skin_Specular( vec3 N,", // Bumped surface normal
"vec3 L,", // Points to light
"vec3 V,", // Points to eye
"float m,", // Roughness
"float rho_s", // Specular brightness
") {",
"float result = 0.0;",
"float ndotl = dot( N, L );",
"if( ndotl > 0.0 ) {",
"vec3 h = L + V;", // Unnormalized half-way vector
"vec3 H = normalize( h );",
"float ndoth = dot( N, H );",
"float PH = pow( 2.0 * texture2D( tBeckmann, vec2( ndoth, m ) ).x, 10.0 );",
"float F = fresnelReflectance( H, V, 0.028 );",
"float frSpec = max( PH * F / dot( h, h ), 0.0 );",
"result = ndotl * rho_s * frSpec;", // BRDF * dot(N,L) * rho_s
"}",
"return result;",
"}",
"void main() {",
"vec3 outgoingLight = vec3( 0.0 );", // outgoing light does not have an alpha, the surface does
"vec4 diffuseColor = vec4( diffuse, opacity );",
"vec4 colDiffuse = texture2D( tDiffuse, vUv );",
"colDiffuse.rgb *= colDiffuse.rgb;",
"diffuseColor = diffuseColor * colDiffuse;",
"vec3 normal = normalize( vNormal );",
"vec3 viewerDirection = normalize( vViewPosition );",
"float specularStrength;",
"if ( enableSpecular ) {",
"vec4 texelSpecular = texture2D( specularMap, vUv );",
"specularStrength = texelSpecular.r;",
"} else {",
"specularStrength = 1.0;",
"}",
"#ifdef USE_BUMPMAP",
"if ( enableBump ) normal = perturbNormalArb( -vViewPosition, normal, dHdxy_fwd() );",
"#endif",
// point lights
"vec3 totalSpecularLight = vec3( 0.0 );",
"vec3 totalDiffuseLight = vec3( 0.0 );",
"#if NUM_POINT_LIGHTS > 0",
"for ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {",
"vec3 lVector = pointLights[ i ].position + vViewPosition.xyz;",
"float attenuation = calcLightAttenuation( length( lVector ), pointLights[ i ].distance, pointLights[ i ].decay );",
"lVector = normalize( lVector );",
"float pointDiffuseWeightFull = max( dot( normal, lVector ), 0.0 );",
"float pointDiffuseWeightHalf = max( 0.5 * dot( normal, lVector ) + 0.5, 0.0 );",
"vec3 pointDiffuseWeight = mix( vec3 ( pointDiffuseWeightFull ), vec3( pointDiffuseWeightHalf ), uWrapRGB );",
"float pointSpecularWeight = KS_Skin_Specular( normal, lVector, viewerDirection, uRoughness, uSpecularBrightness );",
"totalDiffuseLight += pointLight[ i ].color * ( pointDiffuseWeight * attenuation );",
"totalSpecularLight += pointLight[ i ].color * specular * ( pointSpecularWeight * specularStrength * attenuation );",
"}",
"#endif",
// directional lights
"#if NUM_DIR_LIGHTS > 0",
"for( int i = 0; i < NUM_DIR_LIGHTS; i++ ) {",
"vec3 dirVector = directionalLights[ i ].direction;",
"float dirDiffuseWeightFull = max( dot( normal, dirVector ), 0.0 );",
"float dirDiffuseWeightHalf = max( 0.5 * dot( normal, dirVector ) + 0.5, 0.0 );",
"vec3 dirDiffuseWeight = mix( vec3 ( dirDiffuseWeightFull ), vec3( dirDiffuseWeightHalf ), uWrapRGB );",
"float dirSpecularWeight = KS_Skin_Specular( normal, dirVector, viewerDirection, uRoughness, uSpecularBrightness );",
"totalDiffuseLight += directionalLights[ i ].color * dirDiffuseWeight;",
"totalSpecularLight += directionalLights[ i ].color * ( dirSpecularWeight * specularStrength );",
"}",
"#endif",
// hemisphere lights
"#if NUM_HEMI_LIGHTS > 0",
"for ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {",
"vec3 lVector = hemisphereLightDirection[ i ];",
"float dotProduct = dot( normal, lVector );",
"float hemiDiffuseWeight = 0.5 * dotProduct + 0.5;",
"totalDiffuseLight += mix( hemisphereLightGroundColor[ i ], hemisphereLightSkyColor[ i ], hemiDiffuseWeight );",
// specular (sky light)
"float hemiSpecularWeight = 0.0;",
"hemiSpecularWeight += KS_Skin_Specular( normal, lVector, viewerDirection, uRoughness, uSpecularBrightness );",
// specular (ground light)
"vec3 lVectorGround = -lVector;",
"hemiSpecularWeight += KS_Skin_Specular( normal, lVectorGround, viewerDirection, uRoughness, uSpecularBrightness );",
"vec3 hemiSpecularColor = mix( hemisphereLightGroundColor[ i ], hemisphereLightSkyColor[ i ], hemiDiffuseWeight );",
"totalSpecularLight += hemiSpecularColor * specular * ( hemiSpecularWeight * specularStrength );",
"}",
"#endif",
"outgoingLight += diffuseColor.xyz * ( totalDiffuseLight + ambientLightColor * diffuse ) + totalSpecularLight;",
"gl_FragColor = linearToOutputTexel( vec4( outgoingLight, diffuseColor.a ) );", // TODO, this should be pre-multiplied to allow for bright highlights on very transparent objects
THREE.ShaderChunk[ "fog_fragment" ],
"}"
].join( "\n" ),
vertexShader: [
"uniform vec4 offsetRepeat;",
"varying vec3 vNormal;",
"varying vec2 vUv;",
"varying vec3 vViewPosition;",
THREE.ShaderChunk[ "common" ],
THREE.ShaderChunk[ "lights_pars" ],
THREE.ShaderChunk[ "shadowmap_pars_vertex" ],
THREE.ShaderChunk[ "fog_pars_vertex" ],
"void main() {",
"vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );",
"vec4 worldPosition = modelMatrix * vec4( position, 1.0 );",
"vViewPosition = -mvPosition.xyz;",
"vNormal = normalize( normalMatrix * normal );",
"vUv = uv * offsetRepeat.zw + offsetRepeat.xy;",
"gl_Position = projectionMatrix * mvPosition;",
THREE.ShaderChunk[ "shadowmap_vertex" ],
THREE.ShaderChunk[ "fog_vertex" ],
"}"
].join( "\n" )
},
/* ------------------------------------------------------------------------------------------
// Skin shader
// - Blinn-Phong diffuse term (using normal + diffuse maps)
// - subsurface scattering approximation by four blur layers
// - physically based specular term (Kelemen/Szirmay-Kalos specular reflectance)
//
// - point and directional lights (use with "lights: true" material option)
//
// - based on Nvidia Advanced Skin Rendering GDC 2007 presentation
// and GPU Gems 3 Chapter 14. Advanced Techniques for Realistic Real-Time Skin Rendering
//
// http://developer.download.nvidia.com/presentations/2007/gdc/Advanced_Skin.pdf
// http://http.developer.nvidia.com/GPUGems3/gpugems3_ch14.html
// ------------------------------------------------------------------------------------------ */
'skin' : {
uniforms: THREE.UniformsUtils.merge( [
THREE.UniformsLib[ "fog" ],
THREE.UniformsLib[ "lights" ],
{
"passID": { value: 0 },
"tDiffuse" : { value: null },
"tNormal" : { value: null },
"tBlur1" : { value: null },
"tBlur2" : { value: null },
"tBlur3" : { value: null },
"tBlur4" : { value: null },
"tBeckmann" : { value: null },
"uNormalScale": { value: 1.0 },
"diffuse": { value: new THREE.Color( 0xeeeeee ) },
"specular": { value: new THREE.Color( 0x111111 ) },
"opacity": { value: 1 },
"uRoughness": { value: 0.15 },
"uSpecularBrightness": { value: 0.75 }
}
] ),
fragmentShader: [
"uniform vec3 diffuse;",
"uniform vec3 specular;",
"uniform float opacity;",
"uniform float uRoughness;",
"uniform float uSpecularBrightness;",
"uniform int passID;",
"uniform sampler2D tDiffuse;",
"uniform sampler2D tNormal;",
"uniform sampler2D tBlur1;",
"uniform sampler2D tBlur2;",
"uniform sampler2D tBlur3;",
"uniform sampler2D tBlur4;",
"uniform sampler2D tBeckmann;",
"uniform float uNormalScale;",
"varying vec3 vNormal;",
"varying vec2 vUv;",
"varying vec3 vViewPosition;",
THREE.ShaderChunk[ "common" ],
THREE.ShaderChunk[ "lights_pars" ],
THREE.ShaderChunk[ "fog_pars_fragment" ],
"float fresnelReflectance( vec3 H, vec3 V, float F0 ) {",
"float base = 1.0 - dot( V, H );",
"float exponential = pow( base, 5.0 );",
"return exponential + F0 * ( 1.0 - exponential );",
"}",
// Kelemen/Szirmay-Kalos specular BRDF
"float KS_Skin_Specular( vec3 N,", // Bumped surface normal
"vec3 L,", // Points to light
"vec3 V,", // Points to eye
"float m,", // Roughness
"float rho_s", // Specular brightness
") {",
"float result = 0.0;",
"float ndotl = dot( N, L );",
"if( ndotl > 0.0 ) {",
"vec3 h = L + V;", // Unnormalized half-way vector
"vec3 H = normalize( h );",
"float ndoth = dot( N, H );",
"float PH = pow( 2.0 * texture2D( tBeckmann, vec2( ndoth, m ) ).x, 10.0 );",
"float F = fresnelReflectance( H, V, 0.028 );",
"float frSpec = max( PH * F / dot( h, h ), 0.0 );",
"result = ndotl * rho_s * frSpec;", // BRDF * dot(N,L) * rho_s
"}",
"return result;",
"}",
"void main() {",
"vec3 outgoingLight = vec3( 0.0 );", // outgoing light does not have an alpha, the surface does
"vec4 diffuseColor = vec4( diffuse, opacity );",
"vec4 mSpecular = vec4( specular, opacity );",
"vec4 colDiffuse = texture2D( tDiffuse, vUv );",
"colDiffuse *= colDiffuse;",
"diffuseColor *= colDiffuse;",
// normal mapping
"vec4 posAndU = vec4( -vViewPosition, vUv.x );",
"vec4 posAndU_dx = dFdx( posAndU ), posAndU_dy = dFdy( posAndU );",
"vec3 tangent = posAndU_dx.w * posAndU_dx.xyz + posAndU_dy.w * posAndU_dy.xyz;",
"vec3 normal = normalize( vNormal );",
"vec3 binormal = normalize( cross( tangent, normal ) );",
"tangent = cross( normal, binormal );", // no normalization required
"mat3 tsb = mat3( tangent, binormal, normal );",
"vec3 normalTex = texture2D( tNormal, vUv ).xyz * 2.0 - 1.0;",
"normalTex.xy *= uNormalScale;",
"normalTex = normalize( normalTex );",
"vec3 finalNormal = tsb * normalTex;",
"normal = normalize( finalNormal );",
"vec3 viewerDirection = normalize( vViewPosition );",
// point lights
"vec3 totalDiffuseLight = vec3( 0.0 );",
"vec3 totalSpecularLight = vec3( 0.0 );",
"#if NUM_POINT_LIGHTS > 0",
"for ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {",
"vec3 pointVector = normalize( pointLights[ i ].direction );",
"float attenuation = calcLightAttenuation( length( lVector ), pointLights[ i ].distance, pointLights[ i ].decay );",
"float pointDiffuseWeight = max( dot( normal, pointVector ), 0.0 );",
"totalDiffuseLight += pointLightColor[ i ] * ( pointDiffuseWeight * attenuation );",
"if ( passID == 1 ) {",
"float pointSpecularWeight = KS_Skin_Specular( normal, pointVector, viewerDirection, uRoughness, uSpecularBrightness );",
"totalSpecularLight += pointLightColor[ i ] * mSpecular.xyz * ( pointSpecularWeight * attenuation );",
"}",
"}",
"#endif",
// directional lights
"#if NUM_DIR_LIGHTS > 0",
"for( int i = 0; i < NUM_DIR_LIGHTS; i++ ) {",
"vec3 dirVector = directionalLights[ i ].direction;",
"float dirDiffuseWeight = max( dot( normal, dirVector ), 0.0 );",
"totalDiffuseLight += directionalLights[ i ].color * dirDiffuseWeight;",
"if ( passID == 1 ) {",
"float dirSpecularWeight = KS_Skin_Specular( normal, dirVector, viewerDirection, uRoughness, uSpecularBrightness );",
"totalSpecularLight += directionalLights[ i ].color * mSpecular.xyz * dirSpecularWeight;",
"}",
"}",
"#endif",
"outgoingLight += diffuseColor.rgb * ( totalDiffuseLight + totalSpecularLight );",
"if ( passID == 0 ) {",
"outgoingLight = sqrt( outgoingLight );",
"} else if ( passID == 1 ) {",
//"#define VERSION1",
"#ifdef VERSION1",
"vec3 nonblurColor = sqrt(outgoingLight );",
"#else",
"vec3 nonblurColor = outgoingLight;",
"#endif",
"vec3 blur1Color = texture2D( tBlur1, vUv ).xyz;",
"vec3 blur2Color = texture2D( tBlur2, vUv ).xyz;",
"vec3 blur3Color = texture2D( tBlur3, vUv ).xyz;",
"vec3 blur4Color = texture2D( tBlur4, vUv ).xyz;",
//"gl_FragColor = vec4( blur1Color, gl_FragColor.w );",
//"gl_FragColor = vec4( vec3( 0.22, 0.5, 0.7 ) * nonblurColor + vec3( 0.2, 0.5, 0.3 ) * blur1Color + vec3( 0.58, 0.0, 0.0 ) * blur2Color, gl_FragColor.w );",
//"gl_FragColor = vec4( vec3( 0.25, 0.6, 0.8 ) * nonblurColor + vec3( 0.15, 0.25, 0.2 ) * blur1Color + vec3( 0.15, 0.15, 0.0 ) * blur2Color + vec3( 0.45, 0.0, 0.0 ) * blur3Color, gl_FragColor.w );",
"outgoingLight = vec3( vec3( 0.22, 0.437, 0.635 ) * nonblurColor + ",
"vec3( 0.101, 0.355, 0.365 ) * blur1Color + ",
"vec3( 0.119, 0.208, 0.0 ) * blur2Color + ",
"vec3( 0.114, 0.0, 0.0 ) * blur3Color + ",
"vec3( 0.444, 0.0, 0.0 ) * blur4Color );",
"outgoingLight *= sqrt( colDiffuse.xyz );",
"outgoingLight += ambientLightColor * diffuse * colDiffuse.xyz + totalSpecularLight;",
"#ifndef VERSION1",
"outgoingLight = sqrt( outgoingLight );",
"#endif",
"}",
"gl_FragColor = vec4( outgoingLight, diffuseColor.a );", // TODO, this should be pre-multiplied to allow for bright highlights on very transparent objects
THREE.ShaderChunk[ "fog_fragment" ],
"}"
].join( "\n" ),
vertexShader: [
"#ifdef VERTEX_TEXTURES",
"uniform sampler2D tDisplacement;",
"uniform float uDisplacementScale;",
"uniform float uDisplacementBias;",
"#endif",
"varying vec3 vNormal;",
"varying vec2 vUv;",
"varying vec3 vViewPosition;",
THREE.ShaderChunk[ "common" ],
THREE.ShaderChunk[ "fog_pars_vertex" ],
"void main() {",
"vec4 worldPosition = modelMatrix * vec4( position, 1.0 );",
"vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );",
"vViewPosition = -mvPosition.xyz;",
"vNormal = normalize( normalMatrix * normal );",
"vUv = uv;",
// displacement mapping
"#ifdef VERTEX_TEXTURES",
"vec3 dv = texture2D( tDisplacement, uv ).xyz;",
"float df = uDisplacementScale * dv.x + uDisplacementBias;",
"vec4 displacedPosition = vec4( vNormal.xyz * df, 0.0 ) + mvPosition;",
"gl_Position = projectionMatrix * displacedPosition;",
"#else",
"gl_Position = projectionMatrix * mvPosition;",
"#endif",
THREE.ShaderChunk[ "fog_vertex" ],
"}",
].join( "\n" ),
vertexShaderUV: [
"varying vec3 vNormal;",
"varying vec2 vUv;",
"varying vec3 vViewPosition;",
THREE.ShaderChunk[ "common" ],
"void main() {",
"vec4 worldPosition = modelMatrix * vec4( position, 1.0 );",
"vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );",
"vViewPosition = -mvPosition.xyz;",
"vNormal = normalize( normalMatrix * normal );",
"vUv = uv;",
"gl_Position = vec4( uv.x * 2.0 - 1.0, uv.y * 2.0 - 1.0, 0.0, 1.0 );",
"}"
].join( "\n" )
},
/* ------------------------------------------------------------------------------------------
// Beckmann distribution function
// - to be used in specular term of skin shader
// - render a screen-aligned quad to precompute a 512 x 512 texture
//
// - from http://developer.nvidia.com/node/171
------------------------------------------------------------------------------------------ */
"beckmann" : {
uniforms: {},
vertexShader: [
"varying vec2 vUv;",
"void main() {",
"vUv = uv;",
"gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",
"}"
].join( "\n" ),
fragmentShader: [
"varying vec2 vUv;",
"float PHBeckmann( float ndoth, float m ) {",
"float alpha = acos( ndoth );",
"float ta = tan( alpha );",
"float val = 1.0 / ( m * m * pow( ndoth, 4.0 ) ) * exp( -( ta * ta ) / ( m * m ) );",
"return val;",
"}",
"float KSTextureCompute( vec2 tex ) {",
// Scale the value to fit within [0,1] invert upon lookup.
"return 0.5 * pow( PHBeckmann( tex.x, tex.y ), 0.1 );",
"}",
"void main() {",
"float x = KSTextureCompute( vUv );",
"gl_FragColor = vec4( x, x, x, 1.0 );",
"}"
].join( "\n" )
}
};

324
node_modules/three/examples/js/ShaderTerrain.js generated vendored Normal file
View File

@@ -0,0 +1,324 @@
/**
* @author alteredq / http://alteredqualia.com/
*
*/
THREE.ShaderTerrain = {
/* -------------------------------------------------------------------------
// Dynamic terrain shader
// - Blinn-Phong
// - height + normal + diffuse1 + diffuse2 + specular + detail maps
// - point, directional and hemisphere lights (use with "lights: true" material option)
// - shadow maps receiving
------------------------------------------------------------------------- */
'terrain' : {
uniforms: THREE.UniformsUtils.merge( [
THREE.UniformsLib[ "fog" ],
THREE.UniformsLib[ "lights" ],
{
"enableDiffuse1": { value: 0 },
"enableDiffuse2": { value: 0 },
"enableSpecular": { value: 0 },
"enableReflection": { value: 0 },
"tDiffuse1": { value: null },
"tDiffuse2": { value: null },
"tDetail": { value: null },
"tNormal": { value: null },
"tSpecular": { value: null },
"tDisplacement": { value: null },
"uNormalScale": { value: 1.0 },
"uDisplacementBias": { value: 0.0 },
"uDisplacementScale": { value: 1.0 },
"diffuse": { value: new THREE.Color( 0xeeeeee ) },
"specular": { value: new THREE.Color( 0x111111 ) },
"shininess": { value: 30 },
"opacity": { value: 1 },
"uRepeatBase": { value: new THREE.Vector2( 1, 1 ) },
"uRepeatOverlay": { value: new THREE.Vector2( 1, 1 ) },
"uOffset": { value: new THREE.Vector2( 0, 0 ) }
}
] ),
fragmentShader: [
"uniform vec3 diffuse;",
"uniform vec3 specular;",
"uniform float shininess;",
"uniform float opacity;",
"uniform bool enableDiffuse1;",
"uniform bool enableDiffuse2;",
"uniform bool enableSpecular;",
"uniform sampler2D tDiffuse1;",
"uniform sampler2D tDiffuse2;",
"uniform sampler2D tDetail;",
"uniform sampler2D tNormal;",
"uniform sampler2D tSpecular;",
"uniform sampler2D tDisplacement;",
"uniform float uNormalScale;",
"uniform vec2 uRepeatOverlay;",
"uniform vec2 uRepeatBase;",
"uniform vec2 uOffset;",
"varying vec3 vTangent;",
"varying vec3 vBinormal;",
"varying vec3 vNormal;",
"varying vec2 vUv;",
"varying vec3 vViewPosition;",
THREE.ShaderChunk[ "common" ],
THREE.ShaderChunk[ "bsdfs" ],
THREE.ShaderChunk[ "lights_pars" ],
THREE.ShaderChunk[ "shadowmap_pars_fragment" ],
THREE.ShaderChunk[ "fog_pars_fragment" ],
"float calcLightAttenuation( float lightDistance, float cutoffDistance, float decayExponent ) {",
"if ( decayExponent > 0.0 ) {",
"return pow( saturate( - lightDistance / cutoffDistance + 1.0 ), decayExponent );",
"}",
"return 1.0;",
"}",
"void main() {",
"vec3 outgoingLight = vec3( 0.0 );", // outgoing light does not have an alpha, the surface does
"vec4 diffuseColor = vec4( diffuse, opacity );",
"vec3 specularTex = vec3( 1.0 );",
"vec2 uvOverlay = uRepeatOverlay * vUv + uOffset;",
"vec2 uvBase = uRepeatBase * vUv;",
"vec3 normalTex = texture2D( tDetail, uvOverlay ).xyz * 2.0 - 1.0;",
"normalTex.xy *= uNormalScale;",
"normalTex = normalize( normalTex );",
"if( enableDiffuse1 && enableDiffuse2 ) {",
"vec4 colDiffuse1 = texture2D( tDiffuse1, uvOverlay );",
"vec4 colDiffuse2 = texture2D( tDiffuse2, uvOverlay );",
"colDiffuse1 = GammaToLinear( colDiffuse1, float( GAMMA_FACTOR ) );",
"colDiffuse2 = GammaToLinear( colDiffuse2, float( GAMMA_FACTOR ) );",
"diffuseColor *= mix ( colDiffuse1, colDiffuse2, 1.0 - texture2D( tDisplacement, uvBase ) );",
" } else if( enableDiffuse1 ) {",
"diffuseColor *= texture2D( tDiffuse1, uvOverlay );",
"} else if( enableDiffuse2 ) {",
"diffuseColor *= texture2D( tDiffuse2, uvOverlay );",
"}",
"if( enableSpecular )",
"specularTex = texture2D( tSpecular, uvOverlay ).xyz;",
"mat3 tsb = mat3( vTangent, vBinormal, vNormal );",
"vec3 finalNormal = tsb * normalTex;",
"vec3 normal = normalize( finalNormal );",
"vec3 viewPosition = normalize( vViewPosition );",
"vec3 totalDiffuseLight = vec3( 0.0 );",
"vec3 totalSpecularLight = vec3( 0.0 );",
// point lights
"#if NUM_POINT_LIGHTS > 0",
"for ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {",
"vec3 lVector = pointLights[ i ].position + vViewPosition.xyz;",
"float attenuation = calcLightAttenuation( length( lVector ), pointLights[ i ].distance, pointLights[ i ].decay );",
"lVector = normalize( lVector );",
"vec3 pointHalfVector = normalize( lVector + viewPosition );",
"float pointDotNormalHalf = max( dot( normal, pointHalfVector ), 0.0 );",
"float pointDiffuseWeight = max( dot( normal, lVector ), 0.0 );",
"float pointSpecularWeight = specularTex.r * max( pow( pointDotNormalHalf, shininess ), 0.0 );",
"totalDiffuseLight += attenuation * pointLights[ i ].color * pointDiffuseWeight;",
"totalSpecularLight += attenuation * pointLights[ i ].color * specular * pointSpecularWeight * pointDiffuseWeight;",
"}",
"#endif",
// directional lights
"#if NUM_DIR_LIGHTS > 0",
"vec3 dirDiffuse = vec3( 0.0 );",
"vec3 dirSpecular = vec3( 0.0 );",
"for( int i = 0; i < NUM_DIR_LIGHTS; i++ ) {",
"vec3 dirVector = directionalLights[ i ].direction;",
"vec3 dirHalfVector = normalize( dirVector + viewPosition );",
"float dirDotNormalHalf = max( dot( normal, dirHalfVector ), 0.0 );",
"float dirDiffuseWeight = max( dot( normal, dirVector ), 0.0 );",
"float dirSpecularWeight = specularTex.r * max( pow( dirDotNormalHalf, shininess ), 0.0 );",
"totalDiffuseLight += directionalLights[ i ].color * dirDiffuseWeight;",
"totalSpecularLight += directionalLights[ i ].color * specular * dirSpecularWeight * dirDiffuseWeight;",
"}",
"#endif",
// hemisphere lights
"#if NUM_HEMI_LIGHTS > 0",
"vec3 hemiDiffuse = vec3( 0.0 );",
"vec3 hemiSpecular = vec3( 0.0 );",
"for( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {",
"vec3 lVector = hemisphereLightDirection[ i ];",
// diffuse
"float dotProduct = dot( normal, lVector );",
"float hemiDiffuseWeight = 0.5 * dotProduct + 0.5;",
"totalDiffuseLight += mix( hemisphereLights[ i ].groundColor, hemisphereLights[ i ].skyColor, hemiDiffuseWeight );",
// specular (sky light)
"float hemiSpecularWeight = 0.0;",
"vec3 hemiHalfVectorSky = normalize( lVector + viewPosition );",
"float hemiDotNormalHalfSky = 0.5 * dot( normal, hemiHalfVectorSky ) + 0.5;",
"hemiSpecularWeight += specularTex.r * max( pow( hemiDotNormalHalfSky, shininess ), 0.0 );",
// specular (ground light)
"vec3 lVectorGround = -lVector;",
"vec3 hemiHalfVectorGround = normalize( lVectorGround + viewPosition );",
"float hemiDotNormalHalfGround = 0.5 * dot( normal, hemiHalfVectorGround ) + 0.5;",
"hemiSpecularWeight += specularTex.r * max( pow( hemiDotNormalHalfGround, shininess ), 0.0 );",
"totalSpecularLight += specular * mix( hemisphereLights[ i ].groundColor, hemisphereLights[ i ].skyColor, hemiDiffuseWeight ) * hemiSpecularWeight * hemiDiffuseWeight;",
"}",
"#endif",
"outgoingLight += diffuseColor.xyz * ( totalDiffuseLight + ambientLightColor + totalSpecularLight );",
"gl_FragColor = vec4( outgoingLight, diffuseColor.a );", // TODO, this should be pre-multiplied to allow for bright highlights on very transparent objects
THREE.ShaderChunk[ "fog_fragment" ],
"}"
].join( "\n" ),
vertexShader: [
"attribute vec4 tangent;",
"uniform vec2 uRepeatBase;",
"uniform sampler2D tNormal;",
"#ifdef VERTEX_TEXTURES",
"uniform sampler2D tDisplacement;",
"uniform float uDisplacementScale;",
"uniform float uDisplacementBias;",
"#endif",
"varying vec3 vTangent;",
"varying vec3 vBinormal;",
"varying vec3 vNormal;",
"varying vec2 vUv;",
"varying vec3 vViewPosition;",
THREE.ShaderChunk[ "shadowmap_pars_vertex" ],
THREE.ShaderChunk[ "fog_pars_vertex" ],
"void main() {",
"vNormal = normalize( normalMatrix * normal );",
// tangent and binormal vectors
"vTangent = normalize( normalMatrix * tangent.xyz );",
"vBinormal = cross( vNormal, vTangent ) * tangent.w;",
"vBinormal = normalize( vBinormal );",
// texture coordinates
"vUv = uv;",
"vec2 uvBase = uv * uRepeatBase;",
// displacement mapping
"#ifdef VERTEX_TEXTURES",
"vec3 dv = texture2D( tDisplacement, uvBase ).xyz;",
"float df = uDisplacementScale * dv.x + uDisplacementBias;",
"vec3 displacedPosition = normal * df + position;",
"vec4 worldPosition = modelMatrix * vec4( displacedPosition, 1.0 );",
"vec4 mvPosition = modelViewMatrix * vec4( displacedPosition, 1.0 );",
"#else",
"vec4 worldPosition = modelMatrix * vec4( position, 1.0 );",
"vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );",
"#endif",
"gl_Position = projectionMatrix * mvPosition;",
"vViewPosition = -mvPosition.xyz;",
"vec3 normalTex = texture2D( tNormal, uvBase ).xyz * 2.0 - 1.0;",
"vNormal = normalMatrix * normalTex;",
THREE.ShaderChunk[ "shadowmap_vertex" ],
THREE.ShaderChunk[ "fog_vertex" ],
"}"
].join( "\n" )
}
};

331
node_modules/three/examples/js/ShaderToon.js generated vendored Normal file
View File

@@ -0,0 +1,331 @@
/**
* @author mrdoob / http://mrdoob.com/
* @author alteredq / http://alteredqualia.com/
*
* ShaderToon currently contains:
*
* toon1
* toon2
* hatching
* dotted
*/
THREE.ShaderToon = {
'toon1' : {
uniforms: {
"uDirLightPos": { value: new THREE.Vector3() },
"uDirLightColor": { value: new THREE.Color( 0xeeeeee ) },
"uAmbientLightColor": { value: new THREE.Color( 0x050505 ) },
"uBaseColor": { value: new THREE.Color( 0xffffff ) }
},
vertexShader: [
"varying vec3 vNormal;",
"varying vec3 vRefract;",
"void main() {",
"vec4 worldPosition = modelMatrix * vec4( position, 1.0 );",
"vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );",
"vec3 worldNormal = normalize ( mat3( modelMatrix[0].xyz, modelMatrix[1].xyz, modelMatrix[2].xyz ) * normal );",
"vNormal = normalize( normalMatrix * normal );",
"vec3 I = worldPosition.xyz - cameraPosition;",
"vRefract = refract( normalize( I ), worldNormal, 1.02 );",
"gl_Position = projectionMatrix * mvPosition;",
"}"
].join( "\n" ),
fragmentShader: [
"uniform vec3 uBaseColor;",
"uniform vec3 uDirLightPos;",
"uniform vec3 uDirLightColor;",
"uniform vec3 uAmbientLightColor;",
"varying vec3 vNormal;",
"varying vec3 vRefract;",
"void main() {",
"float directionalLightWeighting = max( dot( normalize( vNormal ), uDirLightPos ), 0.0);",
"vec3 lightWeighting = uAmbientLightColor + uDirLightColor * directionalLightWeighting;",
"float intensity = smoothstep( - 0.5, 1.0, pow( length(lightWeighting), 20.0 ) );",
"intensity += length(lightWeighting) * 0.2;",
"float cameraWeighting = dot( normalize( vNormal ), vRefract );",
"intensity += pow( 1.0 - length( cameraWeighting ), 6.0 );",
"intensity = intensity * 0.2 + 0.3;",
"if ( intensity < 0.50 ) {",
"gl_FragColor = vec4( 2.0 * intensity * uBaseColor, 1.0 );",
"} else {",
"gl_FragColor = vec4( 1.0 - 2.0 * ( 1.0 - intensity ) * ( 1.0 - uBaseColor ), 1.0 );",
"}",
"}"
].join( "\n" )
},
'toon2' : {
uniforms: {
"uDirLightPos": { value: new THREE.Vector3() },
"uDirLightColor": { value: new THREE.Color( 0xeeeeee ) },
"uAmbientLightColor": { value: new THREE.Color( 0x050505 ) },
"uBaseColor": { value: new THREE.Color( 0xeeeeee ) },
"uLineColor1": { value: new THREE.Color( 0x808080 ) },
"uLineColor2": { value: new THREE.Color( 0x000000 ) },
"uLineColor3": { value: new THREE.Color( 0x000000 ) },
"uLineColor4": { value: new THREE.Color( 0x000000 ) }
},
vertexShader: [
"varying vec3 vNormal;",
"void main() {",
"gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",
"vNormal = normalize( normalMatrix * normal );",
"}"
].join( "\n" ),
fragmentShader: [
"uniform vec3 uBaseColor;",
"uniform vec3 uLineColor1;",
"uniform vec3 uLineColor2;",
"uniform vec3 uLineColor3;",
"uniform vec3 uLineColor4;",
"uniform vec3 uDirLightPos;",
"uniform vec3 uDirLightColor;",
"uniform vec3 uAmbientLightColor;",
"varying vec3 vNormal;",
"void main() {",
"float camera = max( dot( normalize( vNormal ), vec3( 0.0, 0.0, 1.0 ) ), 0.4);",
"float light = max( dot( normalize( vNormal ), uDirLightPos ), 0.0);",
"gl_FragColor = vec4( uBaseColor, 1.0 );",
"if ( length(uAmbientLightColor + uDirLightColor * light) < 1.00 ) {",
"gl_FragColor *= vec4( uLineColor1, 1.0 );",
"}",
"if ( length(uAmbientLightColor + uDirLightColor * camera) < 0.50 ) {",
"gl_FragColor *= vec4( uLineColor2, 1.0 );",
"}",
"}"
].join( "\n" )
},
'hatching' : {
uniforms: {
"uDirLightPos": { value: new THREE.Vector3() },
"uDirLightColor": { value: new THREE.Color( 0xeeeeee ) },
"uAmbientLightColor": { value: new THREE.Color( 0x050505 ) },
"uBaseColor": { value: new THREE.Color( 0xffffff ) },
"uLineColor1": { value: new THREE.Color( 0x000000 ) },
"uLineColor2": { value: new THREE.Color( 0x000000 ) },
"uLineColor3": { value: new THREE.Color( 0x000000 ) },
"uLineColor4": { value: new THREE.Color( 0x000000 ) }
},
vertexShader: [
"varying vec3 vNormal;",
"void main() {",
"gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",
"vNormal = normalize( normalMatrix * normal );",
"}"
].join( "\n" ),
fragmentShader: [
"uniform vec3 uBaseColor;",
"uniform vec3 uLineColor1;",
"uniform vec3 uLineColor2;",
"uniform vec3 uLineColor3;",
"uniform vec3 uLineColor4;",
"uniform vec3 uDirLightPos;",
"uniform vec3 uDirLightColor;",
"uniform vec3 uAmbientLightColor;",
"varying vec3 vNormal;",
"void main() {",
"float directionalLightWeighting = max( dot( normalize(vNormal), uDirLightPos ), 0.0);",
"vec3 lightWeighting = uAmbientLightColor + uDirLightColor * directionalLightWeighting;",
"gl_FragColor = vec4( uBaseColor, 1.0 );",
"if ( length(lightWeighting) < 1.00 ) {",
"if ( mod(gl_FragCoord.x + gl_FragCoord.y, 10.0) == 0.0) {",
"gl_FragColor = vec4( uLineColor1, 1.0 );",
"}",
"}",
"if ( length(lightWeighting) < 0.75 ) {",
"if (mod(gl_FragCoord.x - gl_FragCoord.y, 10.0) == 0.0) {",
"gl_FragColor = vec4( uLineColor2, 1.0 );",
"}",
"}",
"if ( length(lightWeighting) < 0.50 ) {",
"if (mod(gl_FragCoord.x + gl_FragCoord.y - 5.0, 10.0) == 0.0) {",
"gl_FragColor = vec4( uLineColor3, 1.0 );",
"}",
"}",
"if ( length(lightWeighting) < 0.3465 ) {",
"if (mod(gl_FragCoord.x - gl_FragCoord.y - 5.0, 10.0) == 0.0) {",
"gl_FragColor = vec4( uLineColor4, 1.0 );",
"}",
"}",
"}"
].join( "\n" )
},
'dotted' : {
uniforms: {
"uDirLightPos": { value: new THREE.Vector3() },
"uDirLightColor": { value: new THREE.Color( 0xeeeeee ) },
"uAmbientLightColor": { value: new THREE.Color( 0x050505 ) },
"uBaseColor": { value: new THREE.Color( 0xffffff ) },
"uLineColor1": { value: new THREE.Color( 0x000000 ) }
},
vertexShader: [
"varying vec3 vNormal;",
"void main() {",
"gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",
"vNormal = normalize( normalMatrix * normal );",
"}"
].join( "\n" ),
fragmentShader: [
"uniform vec3 uBaseColor;",
"uniform vec3 uLineColor1;",
"uniform vec3 uLineColor2;",
"uniform vec3 uLineColor3;",
"uniform vec3 uLineColor4;",
"uniform vec3 uDirLightPos;",
"uniform vec3 uDirLightColor;",
"uniform vec3 uAmbientLightColor;",
"varying vec3 vNormal;",
"void main() {",
"float directionalLightWeighting = max( dot( normalize(vNormal), uDirLightPos ), 0.0);",
"vec3 lightWeighting = uAmbientLightColor + uDirLightColor * directionalLightWeighting;",
"gl_FragColor = vec4( uBaseColor, 1.0 );",
"if ( length(lightWeighting) < 1.00 ) {",
"if ( ( mod(gl_FragCoord.x, 4.001) + mod(gl_FragCoord.y, 4.0) ) > 6.00 ) {",
"gl_FragColor = vec4( uLineColor1, 1.0 );",
"}",
"}",
"if ( length(lightWeighting) < 0.50 ) {",
"if ( ( mod(gl_FragCoord.x + 2.0, 4.001) + mod(gl_FragCoord.y + 2.0, 4.0) ) > 6.00 ) {",
"gl_FragColor = vec4( uLineColor1, 1.0 );",
"}",
"}",
"}"
].join( "\n" )
}
};

324
node_modules/three/examples/js/SimplexNoise.js generated vendored Normal file
View File

@@ -0,0 +1,324 @@
// Ported from Stefan Gustavson's java implementation
// http://staffwww.itn.liu.se/~stegu/simplexnoise/simplexnoise.pdf
// Read Stefan's excellent paper for details on how this code works.
//
// Sean McCullough banksean@gmail.com
//
// Added 4D noise
// Joshua Koo zz85nus@gmail.com
/**
* You can pass in a random number generator object if you like.
* It is assumed to have a random() method.
*/
var SimplexNoise = function(r) {
if (r == undefined) r = Math;
this.grad3 = [[ 1,1,0 ],[ -1,1,0 ],[ 1,-1,0 ],[ -1,-1,0 ],
[ 1,0,1 ],[ -1,0,1 ],[ 1,0,-1 ],[ -1,0,-1 ],
[ 0,1,1 ],[ 0,-1,1 ],[ 0,1,-1 ],[ 0,-1,-1 ]];
this.grad4 = [[ 0,1,1,1 ], [ 0,1,1,-1 ], [ 0,1,-1,1 ], [ 0,1,-1,-1 ],
[ 0,-1,1,1 ], [ 0,-1,1,-1 ], [ 0,-1,-1,1 ], [ 0,-1,-1,-1 ],
[ 1,0,1,1 ], [ 1,0,1,-1 ], [ 1,0,-1,1 ], [ 1,0,-1,-1 ],
[ -1,0,1,1 ], [ -1,0,1,-1 ], [ -1,0,-1,1 ], [ -1,0,-1,-1 ],
[ 1,1,0,1 ], [ 1,1,0,-1 ], [ 1,-1,0,1 ], [ 1,-1,0,-1 ],
[ -1,1,0,1 ], [ -1,1,0,-1 ], [ -1,-1,0,1 ], [ -1,-1,0,-1 ],
[ 1,1,1,0 ], [ 1,1,-1,0 ], [ 1,-1,1,0 ], [ 1,-1,-1,0 ],
[ -1,1,1,0 ], [ -1,1,-1,0 ], [ -1,-1,1,0 ], [ -1,-1,-1,0 ]];
this.p = [];
for (var i = 0; i < 256; i ++) {
this.p[i] = Math.floor(r.random() * 256);
}
// To remove the need for index wrapping, double the permutation table length
this.perm = [];
for (var i = 0; i < 512; i ++) {
this.perm[i] = this.p[i & 255];
}
// A lookup table to traverse the simplex around a given point in 4D.
// Details can be found where this table is used, in the 4D noise method.
this.simplex = [
[ 0,1,2,3 ],[ 0,1,3,2 ],[ 0,0,0,0 ],[ 0,2,3,1 ],[ 0,0,0,0 ],[ 0,0,0,0 ],[ 0,0,0,0 ],[ 1,2,3,0 ],
[ 0,2,1,3 ],[ 0,0,0,0 ],[ 0,3,1,2 ],[ 0,3,2,1 ],[ 0,0,0,0 ],[ 0,0,0,0 ],[ 0,0,0,0 ],[ 1,3,2,0 ],
[ 0,0,0,0 ],[ 0,0,0,0 ],[ 0,0,0,0 ],[ 0,0,0,0 ],[ 0,0,0,0 ],[ 0,0,0,0 ],[ 0,0,0,0 ],[ 0,0,0,0 ],
[ 1,2,0,3 ],[ 0,0,0,0 ],[ 1,3,0,2 ],[ 0,0,0,0 ],[ 0,0,0,0 ],[ 0,0,0,0 ],[ 2,3,0,1 ],[ 2,3,1,0 ],
[ 1,0,2,3 ],[ 1,0,3,2 ],[ 0,0,0,0 ],[ 0,0,0,0 ],[ 0,0,0,0 ],[ 2,0,3,1 ],[ 0,0,0,0 ],[ 2,1,3,0 ],
[ 0,0,0,0 ],[ 0,0,0,0 ],[ 0,0,0,0 ],[ 0,0,0,0 ],[ 0,0,0,0 ],[ 0,0,0,0 ],[ 0,0,0,0 ],[ 0,0,0,0 ],
[ 2,0,1,3 ],[ 0,0,0,0 ],[ 0,0,0,0 ],[ 0,0,0,0 ],[ 3,0,1,2 ],[ 3,0,2,1 ],[ 0,0,0,0 ],[ 3,1,2,0 ],
[ 2,1,0,3 ],[ 0,0,0,0 ],[ 0,0,0,0 ],[ 0,0,0,0 ],[ 3,1,0,2 ],[ 0,0,0,0 ],[ 3,2,0,1 ],[ 3,2,1,0 ]];
};
SimplexNoise.prototype.dot = function(g, x, y) {
return g[0] * x + g[1] * y;
};
SimplexNoise.prototype.dot3 = function(g, x, y, z) {
return g[0] * x + g[1] * y + g[2] * z;
};
SimplexNoise.prototype.dot4 = function(g, x, y, z, w) {
return g[0] * x + g[1] * y + g[2] * z + g[3] * w;
};
SimplexNoise.prototype.noise = function(xin, yin) {
var n0, n1, n2; // Noise contributions from the three corners
// Skew the input space to determine which simplex cell we're in
var F2 = 0.5 * (Math.sqrt(3.0) - 1.0);
var s = (xin + yin) * F2; // Hairy factor for 2D
var i = Math.floor(xin + s);
var j = Math.floor(yin + s);
var G2 = (3.0 - Math.sqrt(3.0)) / 6.0;
var t = (i + j) * G2;
var X0 = i - t; // Unskew the cell origin back to (x,y) space
var Y0 = j - t;
var x0 = xin - X0; // The x,y distances from the cell origin
var y0 = yin - Y0;
// For the 2D case, the simplex shape is an equilateral triangle.
// Determine which simplex we are in.
var i1, j1; // Offsets for second (middle) corner of simplex in (i,j) coords
if (x0 > y0) {i1 = 1; j1 = 0;} // lower triangle, XY order: (0,0)->(1,0)->(1,1)
else {i1 = 0; j1 = 1;} // upper triangle, YX order: (0,0)->(0,1)->(1,1)
// A step of (1,0) in (i,j) means a step of (1-c,-c) in (x,y), and
// a step of (0,1) in (i,j) means a step of (-c,1-c) in (x,y), where
// c = (3-sqrt(3))/6
var x1 = x0 - i1 + G2; // Offsets for middle corner in (x,y) unskewed coords
var y1 = y0 - j1 + G2;
var x2 = x0 - 1.0 + 2.0 * G2; // Offsets for last corner in (x,y) unskewed coords
var y2 = y0 - 1.0 + 2.0 * G2;
// Work out the hashed gradient indices of the three simplex corners
var ii = i & 255;
var jj = j & 255;
var gi0 = this.perm[ii + this.perm[jj]] % 12;
var gi1 = this.perm[ii + i1 + this.perm[jj + j1]] % 12;
var gi2 = this.perm[ii + 1 + this.perm[jj + 1]] % 12;
// Calculate the contribution from the three corners
var t0 = 0.5 - x0 * x0 - y0 * y0;
if (t0 < 0) n0 = 0.0;
else {
t0 *= t0;
n0 = t0 * t0 * this.dot(this.grad3[gi0], x0, y0); // (x,y) of grad3 used for 2D gradient
}
var t1 = 0.5 - x1 * x1 - y1 * y1;
if (t1 < 0) n1 = 0.0;
else {
t1 *= t1;
n1 = t1 * t1 * this.dot(this.grad3[gi1], x1, y1);
}
var t2 = 0.5 - x2 * x2 - y2 * y2;
if (t2 < 0) n2 = 0.0;
else {
t2 *= t2;
n2 = t2 * t2 * this.dot(this.grad3[gi2], x2, y2);
}
// Add contributions from each corner to get the final noise value.
// The result is scaled to return values in the interval [-1,1].
return 70.0 * (n0 + n1 + n2);
};
// 3D simplex noise
SimplexNoise.prototype.noise3d = function(xin, yin, zin) {
var n0, n1, n2, n3; // Noise contributions from the four corners
// Skew the input space to determine which simplex cell we're in
var F3 = 1.0 / 3.0;
var s = (xin + yin + zin) * F3; // Very nice and simple skew factor for 3D
var i = Math.floor(xin + s);
var j = Math.floor(yin + s);
var k = Math.floor(zin + s);
var G3 = 1.0 / 6.0; // Very nice and simple unskew factor, too
var t = (i + j + k) * G3;
var X0 = i - t; // Unskew the cell origin back to (x,y,z) space
var Y0 = j - t;
var Z0 = k - t;
var x0 = xin - X0; // The x,y,z distances from the cell origin
var y0 = yin - Y0;
var z0 = zin - Z0;
// For the 3D case, the simplex shape is a slightly irregular tetrahedron.
// Determine which simplex we are in.
var i1, j1, k1; // Offsets for second corner of simplex in (i,j,k) coords
var i2, j2, k2; // Offsets for third corner of simplex in (i,j,k) coords
if (x0 >= y0) {
if (y0 >= z0)
{ i1 = 1; j1 = 0; k1 = 0; i2 = 1; j2 = 1; k2 = 0; } // X Y Z order
else if (x0 >= z0) { i1 = 1; j1 = 0; k1 = 0; i2 = 1; j2 = 0; k2 = 1; } // X Z Y order
else { i1 = 0; j1 = 0; k1 = 1; i2 = 1; j2 = 0; k2 = 1; } // Z X Y order
}
else { // x0<y0
if (y0 < z0) { i1 = 0; j1 = 0; k1 = 1; i2 = 0; j2 = 1; k2 = 1; } // Z Y X order
else if (x0 < z0) { i1 = 0; j1 = 1; k1 = 0; i2 = 0; j2 = 1; k2 = 1; } // Y Z X order
else { i1 = 0; j1 = 1; k1 = 0; i2 = 1; j2 = 1; k2 = 0; } // Y X Z order
}
// A step of (1,0,0) in (i,j,k) means a step of (1-c,-c,-c) in (x,y,z),
// a step of (0,1,0) in (i,j,k) means a step of (-c,1-c,-c) in (x,y,z), and
// a step of (0,0,1) in (i,j,k) means a step of (-c,-c,1-c) in (x,y,z), where
// c = 1/6.
var x1 = x0 - i1 + G3; // Offsets for second corner in (x,y,z) coords
var y1 = y0 - j1 + G3;
var z1 = z0 - k1 + G3;
var x2 = x0 - i2 + 2.0 * G3; // Offsets for third corner in (x,y,z) coords
var y2 = y0 - j2 + 2.0 * G3;
var z2 = z0 - k2 + 2.0 * G3;
var x3 = x0 - 1.0 + 3.0 * G3; // Offsets for last corner in (x,y,z) coords
var y3 = y0 - 1.0 + 3.0 * G3;
var z3 = z0 - 1.0 + 3.0 * G3;
// Work out the hashed gradient indices of the four simplex corners
var ii = i & 255;
var jj = j & 255;
var kk = k & 255;
var gi0 = this.perm[ii + this.perm[jj + this.perm[kk]]] % 12;
var gi1 = this.perm[ii + i1 + this.perm[jj + j1 + this.perm[kk + k1]]] % 12;
var gi2 = this.perm[ii + i2 + this.perm[jj + j2 + this.perm[kk + k2]]] % 12;
var gi3 = this.perm[ii + 1 + this.perm[jj + 1 + this.perm[kk + 1]]] % 12;
// Calculate the contribution from the four corners
var t0 = 0.6 - x0 * x0 - y0 * y0 - z0 * z0;
if (t0 < 0) n0 = 0.0;
else {
t0 *= t0;
n0 = t0 * t0 * this.dot3(this.grad3[gi0], x0, y0, z0);
}
var t1 = 0.6 - x1 * x1 - y1 * y1 - z1 * z1;
if (t1 < 0) n1 = 0.0;
else {
t1 *= t1;
n1 = t1 * t1 * this.dot3(this.grad3[gi1], x1, y1, z1);
}
var t2 = 0.6 - x2 * x2 - y2 * y2 - z2 * z2;
if (t2 < 0) n2 = 0.0;
else {
t2 *= t2;
n2 = t2 * t2 * this.dot3(this.grad3[gi2], x2, y2, z2);
}
var t3 = 0.6 - x3 * x3 - y3 * y3 - z3 * z3;
if (t3 < 0) n3 = 0.0;
else {
t3 *= t3;
n3 = t3 * t3 * this.dot3(this.grad3[gi3], x3, y3, z3);
}
// Add contributions from each corner to get the final noise value.
// The result is scaled to stay just inside [-1,1]
return 32.0 * (n0 + n1 + n2 + n3);
};
// 4D simplex noise
SimplexNoise.prototype.noise4d = function( x, y, z, w ) {
// For faster and easier lookups
var grad4 = this.grad4;
var simplex = this.simplex;
var perm = this.perm;
// The skewing and unskewing factors are hairy again for the 4D case
var F4 = (Math.sqrt(5.0) - 1.0) / 4.0;
var G4 = (5.0 - Math.sqrt(5.0)) / 20.0;
var n0, n1, n2, n3, n4; // Noise contributions from the five corners
// Skew the (x,y,z,w) space to determine which cell of 24 simplices we're in
var s = (x + y + z + w) * F4; // Factor for 4D skewing
var i = Math.floor(x + s);
var j = Math.floor(y + s);
var k = Math.floor(z + s);
var l = Math.floor(w + s);
var t = (i + j + k + l) * G4; // Factor for 4D unskewing
var X0 = i - t; // Unskew the cell origin back to (x,y,z,w) space
var Y0 = j - t;
var Z0 = k - t;
var W0 = l - t;
var x0 = x - X0; // The x,y,z,w distances from the cell origin
var y0 = y - Y0;
var z0 = z - Z0;
var w0 = w - W0;
// For the 4D case, the simplex is a 4D shape I won't even try to describe.
// To find out which of the 24 possible simplices we're in, we need to
// determine the magnitude ordering of x0, y0, z0 and w0.
// The method below is a good way of finding the ordering of x,y,z,w and
// then find the correct traversal order for the simplex were in.
// First, six pair-wise comparisons are performed between each possible pair
// of the four coordinates, and the results are used to add up binary bits
// for an integer index.
var c1 = (x0 > y0) ? 32 : 0;
var c2 = (x0 > z0) ? 16 : 0;
var c3 = (y0 > z0) ? 8 : 0;
var c4 = (x0 > w0) ? 4 : 0;
var c5 = (y0 > w0) ? 2 : 0;
var c6 = (z0 > w0) ? 1 : 0;
var c = c1 + c2 + c3 + c4 + c5 + c6;
var i1, j1, k1, l1; // The integer offsets for the second simplex corner
var i2, j2, k2, l2; // The integer offsets for the third simplex corner
var i3, j3, k3, l3; // The integer offsets for the fourth simplex corner
// simplex[c] is a 4-vector with the numbers 0, 1, 2 and 3 in some order.
// Many values of c will never occur, since e.g. x>y>z>w makes x<z, y<w and x<w
// impossible. Only the 24 indices which have non-zero entries make any sense.
// We use a thresholding to set the coordinates in turn from the largest magnitude.
// The number 3 in the "simplex" array is at the position of the largest coordinate.
i1 = simplex[c][0] >= 3 ? 1 : 0;
j1 = simplex[c][1] >= 3 ? 1 : 0;
k1 = simplex[c][2] >= 3 ? 1 : 0;
l1 = simplex[c][3] >= 3 ? 1 : 0;
// The number 2 in the "simplex" array is at the second largest coordinate.
i2 = simplex[c][0] >= 2 ? 1 : 0;
j2 = simplex[c][1] >= 2 ? 1 : 0; k2 = simplex[c][2] >= 2 ? 1 : 0;
l2 = simplex[c][3] >= 2 ? 1 : 0;
// The number 1 in the "simplex" array is at the second smallest coordinate.
i3 = simplex[c][0] >= 1 ? 1 : 0;
j3 = simplex[c][1] >= 1 ? 1 : 0;
k3 = simplex[c][2] >= 1 ? 1 : 0;
l3 = simplex[c][3] >= 1 ? 1 : 0;
// The fifth corner has all coordinate offsets = 1, so no need to look that up.
var x1 = x0 - i1 + G4; // Offsets for second corner in (x,y,z,w) coords
var y1 = y0 - j1 + G4;
var z1 = z0 - k1 + G4;
var w1 = w0 - l1 + G4;
var x2 = x0 - i2 + 2.0 * G4; // Offsets for third corner in (x,y,z,w) coords
var y2 = y0 - j2 + 2.0 * G4;
var z2 = z0 - k2 + 2.0 * G4;
var w2 = w0 - l2 + 2.0 * G4;
var x3 = x0 - i3 + 3.0 * G4; // Offsets for fourth corner in (x,y,z,w) coords
var y3 = y0 - j3 + 3.0 * G4;
var z3 = z0 - k3 + 3.0 * G4;
var w3 = w0 - l3 + 3.0 * G4;
var x4 = x0 - 1.0 + 4.0 * G4; // Offsets for last corner in (x,y,z,w) coords
var y4 = y0 - 1.0 + 4.0 * G4;
var z4 = z0 - 1.0 + 4.0 * G4;
var w4 = w0 - 1.0 + 4.0 * G4;
// Work out the hashed gradient indices of the five simplex corners
var ii = i & 255;
var jj = j & 255;
var kk = k & 255;
var ll = l & 255;
var gi0 = perm[ii + perm[jj + perm[kk + perm[ll]]]] % 32;
var gi1 = perm[ii + i1 + perm[jj + j1 + perm[kk + k1 + perm[ll + l1]]]] % 32;
var gi2 = perm[ii + i2 + perm[jj + j2 + perm[kk + k2 + perm[ll + l2]]]] % 32;
var gi3 = perm[ii + i3 + perm[jj + j3 + perm[kk + k3 + perm[ll + l3]]]] % 32;
var gi4 = perm[ii + 1 + perm[jj + 1 + perm[kk + 1 + perm[ll + 1]]]] % 32;
// Calculate the contribution from the five corners
var t0 = 0.6 - x0 * x0 - y0 * y0 - z0 * z0 - w0 * w0;
if (t0 < 0) n0 = 0.0;
else {
t0 *= t0;
n0 = t0 * t0 * this.dot4(grad4[gi0], x0, y0, z0, w0);
}
var t1 = 0.6 - x1 * x1 - y1 * y1 - z1 * z1 - w1 * w1;
if (t1 < 0) n1 = 0.0;
else {
t1 *= t1;
n1 = t1 * t1 * this.dot4(grad4[gi1], x1, y1, z1, w1);
}
var t2 = 0.6 - x2 * x2 - y2 * y2 - z2 * z2 - w2 * w2;
if (t2 < 0) n2 = 0.0;
else {
t2 *= t2;
n2 = t2 * t2 * this.dot4(grad4[gi2], x2, y2, z2, w2);
} var t3 = 0.6 - x3 * x3 - y3 * y3 - z3 * z3 - w3 * w3;
if (t3 < 0) n3 = 0.0;
else {
t3 *= t3;
n3 = t3 * t3 * this.dot4(grad4[gi3], x3, y3, z3, w3);
}
var t4 = 0.6 - x4 * x4 - y4 * y4 - z4 * z4 - w4 * w4;
if (t4 < 0) n4 = 0.0;
else {
t4 *= t4;
n4 = t4 * t4 * this.dot4(grad4[gi4], x4, y4, z4, w4);
}
// Sum up and scale the result to cover the range [-1,1]
return 27.0 * (n0 + n1 + n2 + n3 + n4);
};

238
node_modules/three/examples/js/SkyShader.js generated vendored Normal file
View File

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

280
node_modules/three/examples/js/TimelinerController.js generated vendored Normal file
View File

@@ -0,0 +1,280 @@
/**
* Controller class for the Timeliner GUI.
*
* Timeliner GUI library (required to use this class):
*
* ./libs/timeliner_gui.min.js
*
* Source code:
*
* https://github.com/tschw/timeliner_gui
* https://github.com/zz85/timeliner (fork's origin)
*
* @author tschw
*
*/
THREE.TimelinerController = function TimelinerController( scene, trackInfo, onUpdate ) {
this._scene = scene;
this._trackInfo = trackInfo;
this._onUpdate = onUpdate;
this._mixer = new THREE.AnimationMixer( scene );
this._clip = null;
this._action = null;
this._tracks = {};
this._propRefs = {};
this._channelNames = [];
};
THREE.TimelinerController.prototype = {
constructor: THREE.TimelinerController,
init: function( timeliner ) {
var tracks = [],
trackInfo = this._trackInfo;
for ( var i = 0, n = trackInfo.length; i !== n; ++ i ) {
var spec = trackInfo[ i ];
tracks.push( this._addTrack(
spec.type, spec.propertyPath,
spec.initialValue, spec.interpolation ) );
}
this._clip = new THREE.AnimationClip( 'editclip', 0, tracks );
this._action = this._mixer.clipAction( this._clip ).play();
},
setDisplayTime: function( time ) {
this._action.time = time;
this._mixer.update( 0 );
this._onUpdate();
},
setDuration: function( duration ) {
this._clip.duration = duration;
},
getChannelNames: function() {
return this._channelNames;
},
getChannelKeyTimes: function( channelName ) {
return this._tracks[ channelName ].times;
},
setKeyframe: function( channelName, time ) {
var track = this._tracks[ channelName ],
times = track.times,
index = Timeliner.binarySearch( times, time ),
values = track.values,
stride = track.getValueSize(),
offset = index * stride;
if ( index < 0 ) {
// insert new keyframe
index = ~ index;
offset = index * stride;
var nTimes = times.length + 1,
nValues = values.length + stride;
for ( var i = nTimes - 1; i !== index; -- i ) {
times[ i ] = times[ i - 1 ];
}
for ( var i = nValues - 1,
e = offset + stride - 1; i !== e; -- i ) {
values[ i ] = values[ i - stride ];
}
}
times[ index ] = time;
this._propRefs[ channelName ].getValue( values, offset );
},
delKeyframe: function( channelName, time ) {
var track = this._tracks[ channelName ],
times = track.times,
index = Timeliner.binarySearch( times, time );
// we disallow to remove the keyframe when it is the last one we have,
// since the animation system is designed to always produce a defined
// state
if ( times.length > 1 && index >= 0 ) {
var nTimes = times.length - 1,
values = track.values,
stride = track.getValueSize(),
nValues = values.length - stride;
// note: no track.getValueSize when array sizes are out of sync
for ( var i = index; i !== nTimes; ++ i ) {
times[ i ] = times[ i + 1 ];
}
times.pop();
for ( var offset = index * stride; offset !== nValues; ++ offset ) {
values[ offset ] = values[ offset + stride ];
}
values.length = nValues;
}
},
moveKeyframe: function( channelName, time, delta, moveRemaining ) {
var track = this._tracks[ channelName ],
times = track.times,
index = Timeliner.binarySearch( times, time );
if ( index >= 0 ) {
var endAt = moveRemaining ? times.length : index + 1,
needsSort = times[ index - 1 ] <= time ||
! moveRemaining && time >= times[ index + 1 ];
while ( index !== endAt ) times[ index ++ ] += delta;
if ( needsSort ) this._sort( track );
}
},
serialize: function() {
var result = {
duration: this._clip.duration,
channels: {}
},
names = this._channelNames,
tracks = this._tracks,
channels = result.channels;
for ( var i = 0, n = names.length; i !== n; ++ i ) {
var name = names[ i ],
track = tracks[ name ];
channels[ name ] = {
times: track.times,
values: track.values
};
}
return result;
},
deserialize: function( structs ) {
var names = this._channelNames,
tracks = this._tracks,
channels = structs.channels;
this.setDuration( structs.duration );
for ( var i = 0, n = names.length; i !== n; ++ i ) {
var name = names[ i ],
track = tracks[ name ];
data = channels[ name ];
this._setArray( track.times, data.times );
this._setArray( track.values, data.values );
}
// update display
this.setDisplayTime( this._mixer.time );
},
_sort: function( track ) {
var times = track.times,
order = THREE.AnimationUtils.getKeyframeOrder( times );
this._setArray( times,
THREE.AnimationUtils.sortedArray( times, 1, order ) );
var values = track.values,
stride = track.getValueSize();
this._setArray( values,
THREE.AnimationUtils.sortedArray( values, stride, order ) );
},
_setArray: function( dst, src ) {
dst.length = 0;
dst.push.apply( dst, src );
},
_addTrack: function( type, prop, initialValue, interpolation ) {
var track = new type(
prop, [ 0 ], initialValue, interpolation );
// data must be in JS arrays so it can be resized
track.times = Array.prototype.slice.call( track.times );
track.values = Array.prototype.slice.call( track.values );
this._channelNames.push( prop );
this._tracks[ prop ] = track;
// for recording the state:
this._propRefs[ prop ] =
new THREE.PropertyBinding( this._scene, prop );
return track;
}
};

602
node_modules/three/examples/js/TypedArrayUtils.js generated vendored Normal file
View File

@@ -0,0 +1,602 @@
THREE.TypedArrayUtils = {};
/**
* In-place quicksort for typed arrays (e.g. for Float32Array)
* provides fast sorting
* useful e.g. for a custom shader and/or BufferGeometry
*
* @author Roman Bolzern <roman.bolzern@fhnw.ch>, 2013
* @author I4DS http://www.fhnw.ch/i4ds, 2013
* @license MIT License <http://www.opensource.org/licenses/mit-license.php>
*
* Complexity: http://bigocheatsheet.com/ see Quicksort
*
* Example:
* points: [x, y, z, x, y, z, x, y, z, ...]
* eleSize: 3 //because of (x, y, z)
* orderElement: 0 //order according to x
*/
THREE.TypedArrayUtils.quicksortIP = function ( arr, eleSize, orderElement ) {
var stack = [];
var sp = - 1;
var left = 0;
var right = arr.length / eleSize - 1;
var tmp = 0.0, x = 0, y = 0;
var swapF = function ( a, b ) {
a *= eleSize; b *= eleSize;
for ( y = 0; y < eleSize; y ++ ) {
tmp = arr[ a + y ];
arr[ a + y ] = arr[ b + y ];
arr[ b + y ] = tmp;
}
};
var i, j, swap = new Float32Array( eleSize ), temp = new Float32Array( eleSize );
while ( true ) {
if ( right - left <= 25 ) {
for ( j = left + 1; j <= right; j ++ ) {
for ( x = 0; x < eleSize; x ++ ) {
swap[ x ] = arr[ j * eleSize + x ];
}
i = j - 1;
while ( i >= left && arr[ i * eleSize + orderElement ] > swap[ orderElement ] ) {
for ( x = 0; x < eleSize; x ++ ) {
arr[ ( i + 1 ) * eleSize + x ] = arr[ i * eleSize + x ];
}
i --;
}
for ( x = 0; x < eleSize; x ++ ) {
arr[ ( i + 1 ) * eleSize + x ] = swap[ x ];
}
}
if ( sp == - 1 ) break;
right = stack[ sp -- ]; //?
left = stack[ sp -- ];
} else {
var median = ( left + right ) >> 1;
i = left + 1;
j = right;
swapF( median, i );
if ( arr[ left * eleSize + orderElement ] > arr[ right * eleSize + orderElement ] ) {
swapF( left, right );
}
if ( arr[ i * eleSize + orderElement ] > arr[ right * eleSize + orderElement ] ) {
swapF( i, right );
}
if ( arr[ left * eleSize + orderElement ] > arr[ i * eleSize + orderElement ] ) {
swapF( left, i );
}
for ( x = 0; x < eleSize; x ++ ) {
temp[ x ] = arr[ i * eleSize + x ];
}
while ( true ) {
do i ++; while ( arr[ i * eleSize + orderElement ] < temp[ orderElement ] );
do j --; while ( arr[ j * eleSize + orderElement ] > temp[ orderElement ] );
if ( j < i ) break;
swapF( i, j );
}
for ( x = 0; x < eleSize; x ++ ) {
arr[ ( left + 1 ) * eleSize + x ] = arr[ j * eleSize + x ];
arr[ j * eleSize + x ] = temp[ x ];
}
if ( right - i + 1 >= j - left ) {
stack[ ++ sp ] = i;
stack[ ++ sp ] = right;
right = j - 1;
} else {
stack[ ++ sp ] = left;
stack[ ++ sp ] = j - 1;
left = i;
}
}
}
return arr;
};
/**
* k-d Tree for typed arrays (e.g. for Float32Array), in-place
* provides fast nearest neighbour search
* useful e.g. for a custom shader and/or BufferGeometry, saves tons of memory
* has no insert and remove, only buildup and neares neighbour search
*
* Based on https://github.com/ubilabs/kd-tree-javascript by Ubilabs
*
* @author Roman Bolzern <roman.bolzern@fhnw.ch>, 2013
* @author I4DS http://www.fhnw.ch/i4ds, 2013
* @license MIT License <http://www.opensource.org/licenses/mit-license.php>
*
* Requires typed array quicksort
*
* Example:
* points: [x, y, z, x, y, z, x, y, z, ...]
* metric: function(a, b){ return Math.pow(a[0] - b[0], 2) + Math.pow(a[1] - b[1], 2) + Math.pow(a[2] - b[2], 2); } //Manhatten distance
* eleSize: 3 //because of (x, y, z)
*
* Further information (including mathematical properties)
* http://en.wikipedia.org/wiki/Binary_tree
* http://en.wikipedia.org/wiki/K-d_tree
*
* If you want to further minimize memory usage, remove Node.depth and replace in search algorithm with a traversal to root node (see comments at THREE.TypedArrayUtils.Kdtree.prototype.Node)
*/
THREE.TypedArrayUtils.Kdtree = function ( points, metric, eleSize ) {
var self = this;
var maxDepth = 0;
var getPointSet = function ( points, pos ) {
return points.subarray( pos * eleSize, pos * eleSize + eleSize );
};
function buildTree( points, depth, parent, pos ) {
var dim = depth % eleSize,
median,
node,
plength = points.length / eleSize;
if ( depth > maxDepth ) maxDepth = depth;
if ( plength === 0 ) return null;
if ( plength === 1 ) {
return new self.Node( getPointSet( points, 0 ), depth, parent, pos );
}
THREE.TypedArrayUtils.quicksortIP( points, eleSize, dim );
median = Math.floor( plength / 2 );
node = new self.Node( getPointSet( points, median ), depth, parent, median + pos );
node.left = buildTree( points.subarray( 0, median * eleSize ), depth + 1, node, pos );
node.right = buildTree( points.subarray( ( median + 1 ) * eleSize, points.length ), depth + 1, node, pos + median + 1 );
return node;
}
this.root = buildTree( points, 0, null, 0 );
this.getMaxDepth = function () {
return maxDepth;
};
this.nearest = function ( point, maxNodes, maxDistance ) {
/* point: array of size eleSize
maxNodes: max amount of nodes to return
maxDistance: maximum distance to point result nodes should have
condition (not implemented): function to test node before it's added to the result list, e.g. test for view frustum
*/
var i,
result,
bestNodes;
bestNodes = new THREE.TypedArrayUtils.Kdtree.BinaryHeap(
function ( e ) {
return - e[ 1 ];
}
);
function nearestSearch( node ) {
var bestChild,
dimension = node.depth % eleSize,
ownDistance = metric( point, node.obj ),
linearDistance = 0,
otherChild,
i,
linearPoint = [];
function saveNode( node, distance ) {
bestNodes.push( [ node, distance ] );
if ( bestNodes.size() > maxNodes ) {
bestNodes.pop();
}
}
for ( i = 0; i < eleSize; i += 1 ) {
if ( i === node.depth % eleSize ) {
linearPoint[ i ] = point[ i ];
} else {
linearPoint[ i ] = node.obj[ i ];
}
}
linearDistance = metric( linearPoint, node.obj );
// if it's a leaf
if ( node.right === null && node.left === null ) {
if ( bestNodes.size() < maxNodes || ownDistance < bestNodes.peek()[ 1 ] ) {
saveNode( node, ownDistance );
}
return;
}
if ( node.right === null ) {
bestChild = node.left;
} else if ( node.left === null ) {
bestChild = node.right;
} else {
if ( point[ dimension ] < node.obj[ dimension ] ) {
bestChild = node.left;
} else {
bestChild = node.right;
}
}
// recursive search
nearestSearch( bestChild );
if ( bestNodes.size() < maxNodes || ownDistance < bestNodes.peek()[ 1 ] ) {
saveNode( node, ownDistance );
}
// if there's still room or the current distance is nearer than the best distance
if ( bestNodes.size() < maxNodes || Math.abs( linearDistance ) < bestNodes.peek()[ 1 ] ) {
if ( bestChild === node.left ) {
otherChild = node.right;
} else {
otherChild = node.left;
}
if ( otherChild !== null ) {
nearestSearch( otherChild );
}
}
}
if ( maxDistance ) {
for ( i = 0; i < maxNodes; i += 1 ) {
bestNodes.push( [ null, maxDistance ] );
}
}
nearestSearch( self.root );
result = [];
for ( i = 0; i < maxNodes; i += 1 ) {
if ( bestNodes.content[ i ][ 0 ] ) {
result.push( [ bestNodes.content[ i ][ 0 ], bestNodes.content[ i ][ 1 ] ] );
}
}
return result;
};
};
/**
* If you need to free up additional memory and agree with an additional O( log n ) traversal time you can get rid of "depth" and "pos" in Node:
* Depth can be easily done by adding 1 for every parent (care: root node has depth 0, not 1)
* Pos is a bit tricky: Assuming the tree is balanced (which is the case when after we built it up), perform the following steps:
* By traversing to the root store the path e.g. in a bit pattern (01001011, 0 is left, 1 is right)
* From buildTree we know that "median = Math.floor( plength / 2 );", therefore for each bit...
* 0: amountOfNodesRelevantForUs = Math.floor( (pamountOfNodesRelevantForUs - 1) / 2 );
* 1: amountOfNodesRelevantForUs = Math.ceil( (pamountOfNodesRelevantForUs - 1) / 2 );
* pos += Math.floor( (pamountOfNodesRelevantForUs - 1) / 2 );
* when recursion done, we still need to add all left children of target node:
* pos += Math.floor( (pamountOfNodesRelevantForUs - 1) / 2 );
* and I think you need to +1 for the current position, not sure.. depends, try it out ^^
*
* I experienced that for 200'000 nodes you can get rid of 4 MB memory each, leading to 8 MB memory saved.
*/
THREE.TypedArrayUtils.Kdtree.prototype.Node = function ( obj, depth, parent, pos ) {
this.obj = obj;
this.left = null;
this.right = null;
this.parent = parent;
this.depth = depth;
this.pos = pos;
};
/**
* Binary heap implementation
* @author http://eloquentjavascript.net/appendix2.htm
*/
THREE.TypedArrayUtils.Kdtree.BinaryHeap = function ( scoreFunction ) {
this.content = [];
this.scoreFunction = scoreFunction;
};
THREE.TypedArrayUtils.Kdtree.BinaryHeap.prototype = {
push: function ( element ) {
// Add the new element to the end of the array.
this.content.push( element );
// Allow it to bubble up.
this.bubbleUp( this.content.length - 1 );
},
pop: function () {
// Store the first element so we can return it later.
var result = this.content[ 0 ];
// Get the element at the end of the array.
var end = this.content.pop();
// If there are any elements left, put the end element at the
// start, and let it sink down.
if ( this.content.length > 0 ) {
this.content[ 0 ] = end;
this.sinkDown( 0 );
}
return result;
},
peek: function () {
return this.content[ 0 ];
},
remove: function ( node ) {
var len = this.content.length;
// To remove a value, we must search through the array to find it.
for ( var i = 0; i < len; i ++ ) {
if ( this.content[ i ] == node ) {
// When it is found, the process seen in 'pop' is repeated
// to fill up the hole.
var end = this.content.pop();
if ( i != len - 1 ) {
this.content[ i ] = end;
if ( this.scoreFunction( end ) < this.scoreFunction( node ) ) {
this.bubbleUp( i );
} else {
this.sinkDown( i );
}
}
return;
}
}
throw new Error( "Node not found." );
},
size: function () {
return this.content.length;
},
bubbleUp: function ( n ) {
// Fetch the element that has to be moved.
var element = this.content[ n ];
// When at 0, an element can not go up any further.
while ( n > 0 ) {
// Compute the parent element's index, and fetch it.
var parentN = Math.floor( ( n + 1 ) / 2 ) - 1,
parent = this.content[ parentN ];
// Swap the elements if the parent is greater.
if ( this.scoreFunction( element ) < this.scoreFunction( parent ) ) {
this.content[ parentN ] = element;
this.content[ n ] = parent;
// Update 'n' to continue at the new position.
n = parentN;
} else {
// Found a parent that is less, no need to move it further.
break;
}
}
},
sinkDown: function ( n ) {
// Look up the target element and its score.
var length = this.content.length,
element = this.content[ n ],
elemScore = this.scoreFunction( element );
while ( true ) {
// Compute the indices of the child elements.
var child2N = ( n + 1 ) * 2, child1N = child2N - 1;
// This is used to store the new position of the element, if any.
var swap = null;
// If the first child exists (is inside the array)...
if ( child1N < length ) {
// Look it up and compute its score.
var child1 = this.content[ child1N ],
child1Score = this.scoreFunction( child1 );
// If the score is less than our element's, we need to swap.
if ( child1Score < elemScore ) swap = child1N;
}
// Do the same checks for the other child.
if ( child2N < length ) {
var child2 = this.content[ child2N ],
child2Score = this.scoreFunction( child2 );
if ( child2Score < ( swap === null ? elemScore : child1Score ) ) swap = child2N;
}
// If the element needs to be moved, swap it, and continue.
if ( swap !== null ) {
this.content[ n ] = this.content[ swap ];
this.content[ swap ] = element;
n = swap;
} else {
// Otherwise, we are done.
break;
}
}
}
};

141
node_modules/three/examples/js/UCSCharacter.js generated vendored Normal file
View File

@@ -0,0 +1,141 @@
THREE.UCSCharacter = function() {
var scope = this;
var mesh;
this.scale = 1;
this.root = new THREE.Object3D();
this.numSkins = undefined;
this.numMorphs = undefined;
this.skins = [];
this.materials = [];
this.morphs = [];
this.mixer = new THREE.AnimationMixer( this.root );
this.onLoadComplete = function () {};
this.loadCounter = 0;
this.loadParts = function ( config ) {
this.numSkins = config.skins.length;
this.numMorphs = config.morphs.length;
// Character geometry + number of skins
this.loadCounter = 1 + config.skins.length;
// SKINS
this.skins = loadTextures( config.baseUrl + "skins/", config.skins );
this.materials = createMaterials( this.skins );
// MORPHS
this.morphs = config.morphs;
// CHARACTER
var loader = new THREE.JSONLoader();
console.log( config.baseUrl + config.character );
loader.load( config.baseUrl + config.character, function( geometry ) {
geometry.computeBoundingBox();
geometry.computeVertexNormals();
mesh = new THREE.SkinnedMesh( geometry, new THREE.MultiMaterial() );
mesh.name = config.character;
scope.root.add( mesh );
var bb = geometry.boundingBox;
scope.root.scale.set( config.s, config.s, config.s );
scope.root.position.set( config.x, config.y - bb.min.y * config.s, config.z );
mesh.castShadow = true;
mesh.receiveShadow = true;
scope.mixer.clipAction( geometry.animations[0], mesh ).play();
scope.setSkin( 0 );
scope.checkLoadComplete();
} );
};
this.setSkin = function( index ) {
if ( mesh && scope.materials ) {
mesh.material = scope.materials[ index ];
}
};
this.updateMorphs = function( influences ) {
if ( mesh ) {
for ( var i = 0; i < scope.numMorphs; i ++ ) {
mesh.morphTargetInfluences[ i ] = influences[ scope.morphs[ i ] ] / 100;
}
}
};
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 ], scope.checkLoadComplete );
textures[ i ].mapping = THREE.UVMapping;
textures[ i ].name = textureUrls[ i ];
}
return textures;
}
function createMaterials( skins ) {
var materials = [];
for ( var i = 0; i < skins.length; i ++ ) {
materials[ i ] = new THREE.MeshLambertMaterial( {
color: 0xeeeeee,
specular: 10.0,
map: skins[ i ],
skinning: true,
morphTargets: true
} );
}
return materials;
}
this.checkLoadComplete = function () {
scope.loadCounter -= 1;
if ( scope.loadCounter === 0 ) {
scope.onLoadComplete();
}
}
};

447
node_modules/three/examples/js/Volume.js generated vendored Normal file
View File

@@ -0,0 +1,447 @@
/**
* This class had been written to handle the output of the NRRD loader.
* It contains a volume of data and informations about it.
* For now it only handles 3 dimensional data.
* See the webgl_loader_nrrd.html example and the loaderNRRD.js file to see how to use this class.
* @class
* @author Valentin Demeusy / https://github.com/stity
* @param {number} xLength Width of the volume
* @param {number} yLength Length of the volume
* @param {number} zLength Depth of the volume
* @param {string} type The type of data (uint8, uint16, ...)
* @param {ArrayBuffer} arrayBuffer The buffer with volume data
*/
THREE.Volume = function( xLength, yLength, zLength, type, arrayBuffer ) {
if ( arguments.length > 0 ) {
/**
* @member {number} xLength Width of the volume in the IJK coordinate system
*/
this.xLength = Number( xLength ) || 1;
/**
* @member {number} yLength Height of the volume in the IJK coordinate system
*/
this.yLength = Number( yLength ) || 1;
/**
* @member {number} zLength Depth of the volume in the IJK coordinate system
*/
this.zLength = Number( zLength ) || 1;
/**
* @member {TypedArray} data Data of the volume
*/
switch ( type ) {
case 'Uint8' :
case 'uint8' :
case 'uchar' :
case 'unsigned char' :
case 'uint8_t' :
this.data = new Uint8Array( arrayBuffer );
break;
case 'Int8' :
case 'int8' :
case 'signed char' :
case 'int8_t' :
this.data = new Int8Array( arrayBuffer );
break;
case 'Int16' :
case 'int16' :
case 'short' :
case 'short int' :
case 'signed short' :
case 'signed short int' :
case 'int16_t' :
this.data = new Int16Array( arrayBuffer );
break;
case 'Uint16' :
case 'uint16' :
case 'ushort' :
case 'unsigned short' :
case 'unsigned short int' :
case 'uint16_t' :
this.data = new Uint16Array( arrayBuffer );
break;
case 'Int32' :
case 'int32' :
case 'int' :
case 'signed int' :
case 'int32_t' :
this.data = new Int32Array( arrayBuffer );
break;
case 'Uint32' :
case 'uint32' :
case 'uint' :
case 'unsigned int' :
case 'uint32_t' :
this.data = new Uint32Array( arrayBuffer );
break;
case 'longlong' :
case 'long long' :
case 'long long int' :
case 'signed long long' :
case 'signed long long int' :
case 'int64' :
case 'int64_t' :
case 'ulonglong' :
case 'unsigned long long' :
case 'unsigned long long int' :
case 'uint64' :
case 'uint64_t' :
throw 'Error in THREE.Volume constructor : this type is not supported in JavaScript';
break;
case 'Float32' :
case 'float32' :
case 'float' :
this.data = new Float32Array( arrayBuffer );
break;
case 'Float64' :
case 'float64' :
case 'double' :
this.data = new Float64Array( arrayBuffer );
break;
default :
this.data = new Uint8Array( arrayBuffer );
}
if ( this.data.length !== this.xLength * this.yLength * this.zLength ) {
throw 'Error in THREE.Volume constructor, lengths are not matching arrayBuffer size';
}
}
/**
* @member {Array} spacing Spacing to apply to the volume from IJK to RAS coordinate system
*/
this.spacing = [ 1, 1, 1 ];
/**
* @member {Array} offset Offset of the volume in the RAS coordinate system
*/
this.offset = [ 0, 0, 0 ];
/**
* @member {THREE.Martrix3} matrix The IJK to RAS matrix
*/
this.matrix = new THREE.Matrix3();
this.matrix.identity();
/**
* @member {THREE.Martrix3} inverseMatrix The RAS to IJK matrix
*/
/**
* @member {number} lowerThreshold The voxels with values under this threshold won't appear in the slices.
* If changed, geometryNeedsUpdate is automatically set to true on all the slices associated to this volume
*/
var lowerThreshold = - Infinity;
Object.defineProperty( this, 'lowerThreshold', {
get : function() {
return lowerThreshold;
},
set : function( value ) {
lowerThreshold = value;
this.sliceList.forEach( function( slice ) {
slice.geometryNeedsUpdate = true
} );
}
} );
/**
* @member {number} upperThreshold The voxels with values over this threshold won't appear in the slices.
* If changed, geometryNeedsUpdate is automatically set to true on all the slices associated to this volume
*/
var upperThreshold = Infinity;
Object.defineProperty( this, 'upperThreshold', {
get : function() {
return upperThreshold;
},
set : function( value ) {
upperThreshold = value;
this.sliceList.forEach( function( slice ) {
slice.geometryNeedsUpdate = true;
} );
}
} );
/**
* @member {Array} sliceList The list of all the slices associated to this volume
*/
this.sliceList = [];
/**
* @member {Array} RASDimensions This array holds the dimensions of the volume in the RAS space
*/
};
THREE.Volume.prototype = {
constructor : THREE.Volume,
/**
* @member {Function} getData Shortcut for data[access(i,j,k)]
* @memberof THREE.Volume
* @param {number} i First coordinate
* @param {number} j Second coordinate
* @param {number} k Third coordinate
* @returns {number} value in the data array
*/
getData : function( i, j, k ) {
return this.data[ k * this.xLength * this.yLength + j * this.xLength + i ];
},
/**
* @member {Function} access compute the index in the data array corresponding to the given coordinates in IJK system
* @memberof THREE.Volume
* @param {number} i First coordinate
* @param {number} j Second coordinate
* @param {number} k Third coordinate
* @returns {number} index
*/
access : function( i, j, k ) {
return k * this.xLength * this.yLength + j * this.xLength + i;
},
/**
* @member {Function} reverseAccess Retrieve the IJK coordinates of the voxel corresponding of the given index in the data
* @memberof THREE.Volume
* @param {number} index index of the voxel
* @returns {Array} [x,y,z]
*/
reverseAccess : function( index ) {
var z = Math.floor( index / ( this.yLength * this.xLength ) );
var y = Math.floor( ( index - z * this.yLength * this.xLength ) / this.xLength );
var x = index - z * this.yLength * this.xLength - y * this.xLength;
return [ x, y, z ];
},
/**
* @member {Function} map Apply a function to all the voxels, be careful, the value will be replaced
* @memberof THREE.Volume
* @param {Function} functionToMap A function to apply to every voxel, will be called with the following parameters :
* value of the voxel
* index of the voxel
* the data (TypedArray)
* @param {Object} context You can specify a context in which call the function, default if this Volume
* @returns {THREE.Volume} this
*/
map : function( functionToMap, context ) {
var length = this.data.length;
context = context || this;
for ( var i = 0; i < length; i ++ ) {
this.data[ i ] = functionToMap.call( context, this.data[ i ], i, this.data );
}
return this;
},
/**
* @member {Function} extractPerpendicularPlane Compute the orientation of the slice and returns all the information relative to the geometry such as sliceAccess, the plane matrix (orientation and position in RAS coordinate) and the dimensions of the plane in both coordinate system.
* @memberof THREE.Volume
* @param {string} axis the normal axis to the slice 'x' 'y' or 'z'
* @param {number} index the index of the slice
* @returns {Object} an object containing all the usefull information on the geometry of the slice
*/
extractPerpendicularPlane : function( axis, RASIndex ) {
var iLength,
jLength,
sliceAccess,
planeMatrix = ( new THREE.Matrix4() ).identity(),
volume = this,
planeWidth,
planeHeight,
firstSpacing,
secondSpacing,
positionOffset,
IJKIndex;
var axisInIJK = new THREE.Vector3(),
firstDirection = new THREE.Vector3(),
secondDirection = new THREE.Vector3();
var dimensions = new THREE.Vector3( this.xLength, this.yLength, this.zLength );
switch ( axis ) {
case 'x' :
axisInIJK.set( 1, 0, 0 );
firstDirection.set( 0, 0, - 1 );
secondDirection.set( 0, - 1, 0 );
firstSpacing = this.spacing[ 2 ];
secondSpacing = this.spacing[ 1 ];
IJKIndex = new THREE.Vector3( RASIndex, 0, 0 );
planeMatrix.multiply( ( new THREE.Matrix4() ).makeRotationY( Math.PI / 2 ) );
positionOffset = ( volume.RASDimensions[ 0 ] - 1 ) / 2;
planeMatrix.setPosition( new THREE.Vector3( RASIndex - positionOffset, 0, 0 ) );
break;
case 'y' :
axisInIJK.set( 0, 1, 0 );
firstDirection.set( 1, 0, 0 );
secondDirection.set( 0, 0, 1 );
firstSpacing = this.spacing[ 0 ];
secondSpacing = this.spacing[ 2 ];
IJKIndex = new THREE.Vector3( 0, RASIndex, 0 );
planeMatrix.multiply( ( new THREE.Matrix4() ).makeRotationX( - Math.PI / 2 ) );
positionOffset = ( volume.RASDimensions[ 1 ] - 1 ) / 2;
planeMatrix.setPosition( new THREE.Vector3( 0, RASIndex - positionOffset, 0 ) );
break;
case 'z' :
default :
axisInIJK.set( 0, 0, 1 );
firstDirection.set( 1, 0, 0 );
secondDirection.set( 0, - 1, 0 );
firstSpacing = this.spacing[ 0 ];
secondSpacing = this.spacing[ 1 ];
IJKIndex = new THREE.Vector3( 0, 0, RASIndex );
positionOffset = ( volume.RASDimensions[ 2 ] - 1 ) / 2;
planeMatrix.setPosition( new THREE.Vector3( 0, 0, RASIndex - positionOffset ) );
break;
}
firstDirection.applyMatrix4( volume.inverseMatrix ).normalize();
firstDirection.argVar = 'i';
secondDirection.applyMatrix4( volume.inverseMatrix ).normalize();
secondDirection.argVar = 'j';
axisInIJK.applyMatrix4( volume.inverseMatrix ).normalize();
iLength = Math.floor( Math.abs( firstDirection.dot( dimensions ) ) );
jLength = Math.floor( Math.abs( secondDirection.dot( dimensions ) ) );
planeWidth = Math.abs( iLength * firstSpacing );
planeHeight = Math.abs( jLength * secondSpacing );
IJKIndex = Math.abs( Math.round( IJKIndex.applyMatrix4( volume.inverseMatrix ).dot( axisInIJK ) ) );
var base = [ new THREE.Vector3( 1, 0, 0 ), new THREE.Vector3( 0, 1, 0 ), new THREE.Vector3( 0, 0, 1 ) ];
var iDirection = [ firstDirection, secondDirection, axisInIJK ].find( function( x ) {
return Math.abs( x.dot( base[ 0 ] ) ) > 0.9;
} );
var jDirection = [ firstDirection, secondDirection, axisInIJK ].find( function( x ) {
return Math.abs( x.dot( base[ 1 ] ) ) > 0.9;
} );
var kDirection = [ firstDirection, secondDirection, axisInIJK ].find( function( x ) {
return Math.abs( x.dot( base[ 2 ] ) ) > 0.9;
} );
var argumentsWithInversion = [ 'volume.xLength-1-', 'volume.yLength-1-', 'volume.zLength-1-' ];
var arguments = [ 'i', 'j', 'k' ];
var argArray = [ iDirection, jDirection, kDirection ].map( function( direction, n ) {
return ( direction.dot( base[ n ] ) > 0 ? '' : argumentsWithInversion[ n ] ) + ( direction === axisInIJK ? 'IJKIndex' : direction.argVar )
} );
var argString = argArray.join( ',' );
sliceAccess = eval( '(function sliceAccess (i,j) {return volume.access( ' + argString + ');})' );
return {
iLength : iLength,
jLength : jLength,
sliceAccess : sliceAccess,
matrix : planeMatrix,
planeWidth : planeWidth,
planeHeight : planeHeight
}
},
/**
* @member {Function} extractSlice Returns a slice corresponding to the given axis and index
* The coordinate are given in the Right Anterior Superior coordinate format
* @memberof THREE.Volume
* @param {string} axis the normal axis to the slice 'x' 'y' or 'z'
* @param {number} index the index of the slice
* @returns {THREE.VolumeSlice} the extracted slice
*/
extractSlice : function( axis, index ) {
var slice = new THREE.VolumeSlice( this, index, axis );
this.sliceList.push( slice );
return slice;
},
/**
* @member {Function} repaintAllSlices Call repaint on all the slices extracted from this volume
* @see THREE.VolumeSlice.repaint
* @memberof THREE.Volume
* @returns {THREE.Volume} this
*/
repaintAllSlices : function() {
this.sliceList.forEach( function( slice ) {
slice.repaint();
} );
return this;
},
/**
* @member {Function} computeMinMax Compute the minimum and the maximum of the data in the volume
* @memberof THREE.Volume
* @returns {Array} [min,max]
*/
computeMinMax : function() {
var min = Infinity;
var max = - Infinity;
// buffer the length
var datasize = this.data.length;
var i = 0;
for ( i = 0; i < datasize; i ++ ) {
if ( ! isNaN( this.data[ i ] ) ) {
var value = this.data[ i ];
min = Math.min( min, value );
max = Math.max( max, value );
}
}
this.min = min;
this.max = max;
return [ min, max ];
}
};

217
node_modules/three/examples/js/VolumeSlice.js generated vendored Normal file
View File

@@ -0,0 +1,217 @@
/**
* This class has been made to hold a slice of a volume data
* @class
* @author Valentin Demeusy / https://github.com/stity
* @param {THREE.Volume} volume The associated volume
* @param {number} [index=0] The index of the slice
* @param {string} [axis='z'] For now only 'x', 'y' or 'z' but later it will change to a normal vector
* @see THREE.Volume
*/
THREE.VolumeSlice = function( volume, index, axis ) {
var slice = this;
/**
* @member {THREE.Volume} volume The associated volume
*/
this.volume = volume;
/**
* @member {Number} index The index of the slice, if changed, will automatically call updateGeometry at the next repaint
*/
index = index || 0;
Object.defineProperty( this, 'index', {
get : function() {
return index;
},
set : function( value ) {
index = value;
slice.geometryNeedsUpdate = true;
return index;
}
} );
/**
* @member {String} axis The normal axis
*/
this.axis = axis || 'z';
/**
* @member {HTMLCanvasElement} canvas The final canvas used for the texture
*/
/**
* @member {CanvasRenderingContext2D} ctx Context of the canvas
*/
this.canvas = document.createElement( 'canvas' );
/**
* @member {HTMLCanvasElement} canvasBuffer The intermediary canvas used to paint the data
*/
/**
* @member {CanvasRenderingContext2D} ctxBuffer Context of the canvas buffer
*/
this.canvasBuffer = document.createElement( 'canvas' );
this.updateGeometry();
var canvasMap = new THREE.Texture( this.canvas );
canvasMap.minFilter = THREE.LinearFilter;
canvasMap.wrapS = canvasMap.wrapT = THREE.ClampToEdgeWrapping;
var material = new THREE.MeshBasicMaterial( { map: canvasMap, side: THREE.DoubleSide, transparent : true } );
/**
* @member {THREE.Mesh} mesh The mesh ready to get used in the scene
*/
this.mesh = new THREE.Mesh( this.geometry, material );
/**
* @member {Boolean} geometryNeedsUpdate If set to true, updateGeometry will be triggered at the next repaint
*/
this.geometryNeedsUpdate = true;
this.repaint();
/**
* @member {Number} iLength Width of slice in the original coordinate system, corresponds to the width of the buffer canvas
*/
/**
* @member {Number} jLength Height of slice in the original coordinate system, corresponds to the height of the buffer canvas
*/
/**
* @member {Function} sliceAccess Function that allow the slice to access right data
* @see THREE.Volume.extractPerpendicularPlane
* @param {Number} i The first coordinate
* @param {Number} j The second coordinate
* @returns {Number} the index corresponding to the voxel in volume.data of the given position in the slice
*/
};
THREE.VolumeSlice.prototype = {
constructor : THREE.VolumeSlice,
/**
* @member {Function} repaint Refresh the texture and the geometry if geometryNeedsUpdate is set to true
* @memberof THREE.VolumeSlice
*/
repaint : function() {
if ( this.geometryNeedsUpdate ) {
this.updateGeometry();
}
var iLength = this.iLength,
jLength = this.jLength,
sliceAccess = this.sliceAccess,
volume = this.volume,
axis = this.axis,
index = this.index,
canvas = this.canvasBuffer,
ctx = this.ctxBuffer;
// get the imageData and pixel array from the canvas
var imgData = ctx.getImageData( 0, 0, iLength, jLength );
var data = imgData.data;
var volumeData = volume.data;
var upperThreshold = volume.upperThreshold;
var lowerThreshold = volume.lowerThreshold;
var windowLow = volume.windowLow;
var windowHigh = volume.windowHigh;
// manipulate some pixel elements
var pixelCount = 0;
if ( volume.dataType === 'label' ) {
//this part is currently useless but will be used when colortables will be handled
for ( var j = 0; j < jLength; j ++ ) {
for ( var i = 0; i < iLength; i ++ ) {
var label = volumeData[ sliceAccess( i, j ) ];
label = label >= this.colorMap.length ? ( label % this.colorMap.length ) + 1 : label;
var color = this.colorMap[ label ];
data[ 4 * pixelCount ] = ( color >> 24 ) & 0xff;
data[ 4 * pixelCount + 1 ] = ( color >> 16 ) & 0xff;
data[ 4 * pixelCount + 2 ] = ( color >> 8 ) & 0xff;
data[ 4 * pixelCount + 3 ] = color & 0xff;
pixelCount ++;
}
}
}
else {
for ( var j = 0; j < jLength; j ++ ) {
for ( var i = 0; i < iLength; i ++ ) {
var value = volumeData[ sliceAccess( i, j ) ];
var alpha = 0xff;
//apply threshold
alpha = upperThreshold >= value ? ( lowerThreshold <= value ? alpha : 0 ) : 0;
//apply window level
value = Math.floor( 255 * ( value - windowLow ) / ( windowHigh - windowLow ) );
value = value > 255 ? 255 : ( value < 0 ? 0 : value | 0 );
data[ 4 * pixelCount ] = value;
data[ 4 * pixelCount + 1 ] = value;
data[ 4 * pixelCount + 2 ] = value;
data[ 4 * pixelCount + 3 ] = alpha;
pixelCount ++;
}
}
}
ctx.putImageData( imgData, 0, 0 );
this.ctx.drawImage( canvas, 0, 0, iLength, jLength, 0, 0, this.canvas.width, this.canvas.height );
this.mesh.material.map.needsUpdate = true;
},
/**
* @member {Function} Refresh the geometry according to axis and index
* @see THREE.Volume.extractPerpendicularPlane
* @memberof THREE.VolumeSlice
*/
updateGeometry : function() {
var extracted = this.volume.extractPerpendicularPlane( this.axis, this.index );
this.sliceAccess = extracted.sliceAccess;
this.jLength = extracted.jLength;
this.iLength = extracted.iLength;
this.matrix = extracted.matrix;
this.canvas.width = extracted.planeWidth;
this.canvas.height = extracted.planeHeight;
this.canvasBuffer.width = this.iLength;
this.canvasBuffer.height = this.jLength;
this.ctx = this.canvas.getContext( '2d' );
this.ctxBuffer = this.canvasBuffer.getContext( '2d' );
this.geometry = new THREE.PlaneGeometry( extracted.planeWidth, extracted.planeHeight );
if ( this.mesh ) {
this.mesh.geometry = this.geometry;
//reset mesh matrix
this.mesh.matrix = ( new THREE.Matrix4() ).identity();
this.mesh.applyMatrix( this.matrix );
}
this.geometryNeedsUpdate = false;
}
};

302
node_modules/three/examples/js/WaterShader.js generated vendored Normal file
View File

@@ -0,0 +1,302 @@
/**
* @author jbouny / https://github.com/jbouny
*
* Work based on :
* @author Slayvin / http://slayvin.net : Flat mirror for three.js
* @author Stemkoski / http://www.adelphi.edu/~stemkoski : An implementation of water shader based on the flat mirror
* @author Jonas Wagner / http://29a.ch/ && http://29a.ch/slides/2012/webglwater/ : Water shader explanations in WebGL
*/
THREE.ShaderLib[ 'water' ] = {
uniforms: THREE.UniformsUtils.merge( [
THREE.UniformsLib[ "fog" ], {
"normalSampler": { value: null },
"mirrorSampler": { value: null },
"alpha": { value: 1.0 },
"time": { value: 0.0 },
"distortionScale": { value: 20.0 },
"noiseScale": { value: 1.0 },
"textureMatrix" : { value: new THREE.Matrix4() },
"sunColor": { value: new THREE.Color( 0x7F7F7F ) },
"sunDirection": { value: new THREE.Vector3( 0.70707, 0.70707, 0 ) },
"eye": { value: new THREE.Vector3() },
"waterColor": { value: new THREE.Color( 0x555555 ) }
}
] ),
vertexShader: [
'uniform mat4 textureMatrix;',
'uniform float time;',
'varying vec4 mirrorCoord;',
'varying vec3 worldPosition;',
THREE.ShaderChunk[ "fog_pars_vertex"],
'void main()',
'{',
' mirrorCoord = modelMatrix * vec4( position, 1.0 );',
' worldPosition = mirrorCoord.xyz;',
' mirrorCoord = textureMatrix * mirrorCoord;',
' gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );',
THREE.ShaderChunk[ "fog_vertex"],
'}'
].join( '\n' ),
fragmentShader: [
'precision highp float;',
'uniform sampler2D mirrorSampler;',
'uniform float alpha;',
'uniform float time;',
'uniform float distortionScale;',
'uniform sampler2D normalSampler;',
'uniform vec3 sunColor;',
'uniform vec3 sunDirection;',
'uniform vec3 eye;',
'uniform vec3 waterColor;',
'varying vec4 mirrorCoord;',
'varying vec3 worldPosition;',
'vec4 getNoise( vec2 uv )',
'{',
' vec2 uv0 = ( uv / 103.0 ) + vec2(time / 17.0, time / 29.0);',
' vec2 uv1 = uv / 107.0-vec2( time / -19.0, time / 31.0 );',
' vec2 uv2 = uv / vec2( 8907.0, 9803.0 ) + vec2( time / 101.0, time / 97.0 );',
' vec2 uv3 = uv / vec2( 1091.0, 1027.0 ) - vec2( time / 109.0, time / -113.0 );',
' vec4 noise = texture2D( normalSampler, uv0 ) +',
' texture2D( normalSampler, uv1 ) +',
' texture2D( normalSampler, uv2 ) +',
' texture2D( normalSampler, uv3 );',
' return noise * 0.5 - 1.0;',
'}',
'void sunLight( const vec3 surfaceNormal, const vec3 eyeDirection, float shiny, float spec, float diffuse, inout vec3 diffuseColor, inout vec3 specularColor )',
'{',
' vec3 reflection = normalize( reflect( -sunDirection, surfaceNormal ) );',
' float direction = max( 0.0, dot( eyeDirection, reflection ) );',
' specularColor += pow( direction, shiny ) * sunColor * spec;',
' diffuseColor += max( dot( sunDirection, surfaceNormal ), 0.0 ) * sunColor * diffuse;',
'}',
THREE.ShaderChunk[ "common" ],
THREE.ShaderChunk[ "fog_pars_fragment" ],
'void main()',
'{',
' vec4 noise = getNoise( worldPosition.xz );',
' vec3 surfaceNormal = normalize( noise.xzy * vec3( 1.5, 1.0, 1.5 ) );',
' vec3 diffuseLight = vec3(0.0);',
' vec3 specularLight = vec3(0.0);',
' vec3 worldToEye = eye-worldPosition;',
' vec3 eyeDirection = normalize( worldToEye );',
' sunLight( surfaceNormal, eyeDirection, 100.0, 2.0, 0.5, diffuseLight, specularLight );',
' float distance = length(worldToEye);',
' vec2 distortion = surfaceNormal.xz * ( 0.001 + 1.0 / distance ) * distortionScale;',
' vec3 reflectionSample = vec3( texture2D( mirrorSampler, mirrorCoord.xy / mirrorCoord.z + distortion ) );',
' float theta = max( dot( eyeDirection, surfaceNormal ), 0.0 );',
' float rf0 = 0.3;',
' float reflectance = rf0 + ( 1.0 - rf0 ) * pow( ( 1.0 - theta ), 5.0 );',
' vec3 scatter = max( 0.0, dot( surfaceNormal, eyeDirection ) ) * waterColor;',
' vec3 albedo = mix( sunColor * diffuseLight * 0.3 + scatter, ( vec3( 0.1 ) + reflectionSample * 0.9 + reflectionSample * specularLight ), reflectance );',
' vec3 outgoingLight = albedo;',
THREE.ShaderChunk[ "fog_fragment" ],
' gl_FragColor = vec4( outgoingLight, alpha );',
'}'
].join( '\n' )
};
THREE.Water = function ( renderer, camera, scene, options ) {
THREE.Object3D.call( this );
this.name = 'water_' + this.id;
function optionalParameter ( value, defaultValue ) {
return value !== undefined ? value : defaultValue;
}
options = options || {};
this.matrixNeedsUpdate = true;
var width = optionalParameter( options.textureWidth, 512 );
var height = optionalParameter( options.textureHeight, 512 );
this.clipBias = optionalParameter( options.clipBias, 0.0 );
this.alpha = optionalParameter( options.alpha, 1.0 );
this.time = optionalParameter( options.time, 0.0 );
this.normalSampler = optionalParameter( options.waterNormals, null );
this.sunDirection = optionalParameter( options.sunDirection, new THREE.Vector3( 0.70707, 0.70707, 0.0 ) );
this.sunColor = new THREE.Color( optionalParameter( options.sunColor, 0xffffff ) );
this.waterColor = new THREE.Color( optionalParameter( options.waterColor, 0x7F7F7F ) );
this.eye = optionalParameter( options.eye, new THREE.Vector3( 0, 0, 0 ) );
this.distortionScale = optionalParameter( options.distortionScale, 20.0 );
this.side = optionalParameter( options.side, THREE.FrontSide );
this.fog = optionalParameter( options.fog, false );
this.renderer = renderer;
this.scene = scene;
this.mirrorPlane = new THREE.Plane();
this.normal = new THREE.Vector3( 0, 0, 1 );
this.mirrorWorldPosition = new THREE.Vector3();
this.cameraWorldPosition = new THREE.Vector3();
this.rotationMatrix = new THREE.Matrix4();
this.lookAtPosition = new THREE.Vector3( 0, 0, - 1 );
this.clipPlane = new THREE.Vector4();
if ( camera instanceof THREE.PerspectiveCamera ) {
this.camera = camera;
} else {
this.camera = new THREE.PerspectiveCamera();
console.log( this.name + ': camera is not a Perspective Camera!' );
}
this.textureMatrix = new THREE.Matrix4();
this.mirrorCamera = this.camera.clone();
this.renderTarget = new THREE.WebGLRenderTarget( width, height );
this.renderTarget2 = new THREE.WebGLRenderTarget( width, height );
var mirrorShader = THREE.ShaderLib[ "water" ];
var mirrorUniforms = THREE.UniformsUtils.clone( mirrorShader.uniforms );
this.material = new THREE.ShaderMaterial( {
fragmentShader: mirrorShader.fragmentShader,
vertexShader: mirrorShader.vertexShader,
uniforms: mirrorUniforms,
transparent: true,
side: this.side,
fog: this.fog
} );
this.material.uniforms.mirrorSampler.value = this.renderTarget.texture;
this.material.uniforms.textureMatrix.value = this.textureMatrix;
this.material.uniforms.alpha.value = this.alpha;
this.material.uniforms.time.value = this.time;
this.material.uniforms.normalSampler.value = this.normalSampler;
this.material.uniforms.sunColor.value = this.sunColor;
this.material.uniforms.waterColor.value = this.waterColor;
this.material.uniforms.sunDirection.value = this.sunDirection;
this.material.uniforms.distortionScale.value = this.distortionScale;
this.material.uniforms.eye.value = this.eye;
if ( ! THREE.Math.isPowerOfTwo( width ) || ! THREE.Math.isPowerOfTwo( height ) ) {
this.renderTarget.texture.generateMipmaps = false;
this.renderTarget.texture.minFilter = THREE.LinearFilter;
this.renderTarget2.texture.generateMipmaps = false;
this.renderTarget2.texture.minFilter = THREE.LinearFilter;
}
this.updateTextureMatrix();
this.render();
};
THREE.Water.prototype = Object.create( THREE.Mirror.prototype );
THREE.Water.prototype.constructor = THREE.Water;
THREE.Water.prototype.updateTextureMatrix = function () {
function sign( x ) {
return x ? x < 0 ? - 1 : 1 : 0;
}
this.updateMatrixWorld();
this.camera.updateMatrixWorld();
this.mirrorWorldPosition.setFromMatrixPosition( this.matrixWorld );
this.cameraWorldPosition.setFromMatrixPosition( this.camera.matrixWorld );
this.rotationMatrix.extractRotation( this.matrixWorld );
this.normal.set( 0, 0, 1 );
this.normal.applyMatrix4( this.rotationMatrix );
var view = this.mirrorWorldPosition.clone().sub( this.cameraWorldPosition );
view.reflect( this.normal ).negate();
view.add( this.mirrorWorldPosition );
this.rotationMatrix.extractRotation( this.camera.matrixWorld );
this.lookAtPosition.set( 0, 0, - 1 );
this.lookAtPosition.applyMatrix4( this.rotationMatrix );
this.lookAtPosition.add( this.cameraWorldPosition );
var target = this.mirrorWorldPosition.clone().sub( this.lookAtPosition );
target.reflect( this.normal ).negate();
target.add( this.mirrorWorldPosition );
this.up.set( 0, - 1, 0 );
this.up.applyMatrix4( this.rotationMatrix );
this.up.reflect( this.normal ).negate();
this.mirrorCamera.position.copy( view );
this.mirrorCamera.up = this.up;
this.mirrorCamera.lookAt( target );
this.mirrorCamera.aspect = this.camera.aspect;
this.mirrorCamera.updateProjectionMatrix();
this.mirrorCamera.updateMatrixWorld();
this.mirrorCamera.matrixWorldInverse.getInverse( this.mirrorCamera.matrixWorld );
// Update the texture matrix
this.textureMatrix.set( 0.5, 0.0, 0.0, 0.5,
0.0, 0.5, 0.0, 0.5,
0.0, 0.0, 0.5, 0.5,
0.0, 0.0, 0.0, 1.0 );
this.textureMatrix.multiply( this.mirrorCamera.projectionMatrix );
this.textureMatrix.multiply( this.mirrorCamera.matrixWorldInverse );
// Now update projection matrix with new clip plane, implementing code from: http://www.terathon.com/code/oblique.html
// Paper explaining this technique: http://www.terathon.com/lengyel/Lengyel-Oblique.pdf
this.mirrorPlane.setFromNormalAndCoplanarPoint( this.normal, this.mirrorWorldPosition );
this.mirrorPlane.applyMatrix4( this.mirrorCamera.matrixWorldInverse );
this.clipPlane.set( this.mirrorPlane.normal.x, this.mirrorPlane.normal.y, this.mirrorPlane.normal.z, this.mirrorPlane.constant );
var q = new THREE.Vector4();
var projectionMatrix = this.mirrorCamera.projectionMatrix;
q.x = ( sign( this.clipPlane.x ) + projectionMatrix.elements[ 8 ] ) / projectionMatrix.elements[ 0 ];
q.y = ( sign( this.clipPlane.y ) + projectionMatrix.elements[ 9 ] ) / projectionMatrix.elements[ 5 ];
q.z = - 1.0;
q.w = ( 1.0 + projectionMatrix.elements[ 10 ] ) / projectionMatrix.elements[ 14 ];
// Calculate the scaled plane vector
var c = new THREE.Vector4();
c = this.clipPlane.multiplyScalar( 2.0 / this.clipPlane.dot( q ) );
// Replacing the third row of the projection matrix
projectionMatrix.elements[ 2 ] = c.x;
projectionMatrix.elements[ 6 ] = c.y;
projectionMatrix.elements[ 10 ] = c.z + 1.0 - this.clipBias;
projectionMatrix.elements[ 14 ] = c.w;
var worldCoordinates = new THREE.Vector3();
worldCoordinates.setFromMatrixPosition( this.camera.matrixWorld );
this.eye = worldCoordinates;
this.material.uniforms.eye.value = this.eye;
};

417
node_modules/three/examples/js/animation/CCDIKSolver.js generated vendored Normal file
View File

@@ -0,0 +1,417 @@
/**
* @author takahiro / https://github.com/takahirox
*
* CCD Algorithm
* https://sites.google.com/site/auraliusproject/ccd-algorithm
*
* mesh.geometry needs to have iks array.
*
* // ik parameter example
* //
* // target, effector, index in links are bone index in skeleton.
* // the bones relation should be
* // <-- parent child -->
* // links[ n ], links[ n - 1 ], ..., links[ 0 ], effector
* ik = {
* target: 1,
* effector: 2,
* links: [ { index: 5, limitation: new THREE.Vector3( 1, 0, 0 ) }, { index: 4, enabled: false }, { index : 3 } ],
* iteration: 10,
* minAngle: 0.0,
* maxAngle: 1.0,
* };
*/
THREE.CCDIKSolver = function ( mesh ) {
this.mesh = mesh;
this._valid();
};
THREE.CCDIKSolver.prototype = {
constructor: THREE.CCDIKSolver,
_valid: function () {
var iks = this.mesh.geometry.iks;
var bones = this.mesh.skeleton.bones;
for ( var i = 0, il = iks.length; i < il; i ++ ) {
var ik = iks[ i ];
var effector = bones[ ik.effector ];
var links = ik.links;
var link0, link1;
link0 = effector;
for ( var j = 0, jl = links.length; j < jl; j ++ ) {
link1 = bones[ links[ j ].index ];
if ( link0.parent !== link1 ) {
console.warn( 'THREE.CCDIKSolver: bone ' + link0.name + ' is not the child of bone ' + link1.name );
}
link0 = link1;
}
}
},
/*
* save the bone matrices before solving IK.
* they're used for generating VMD and VPD.
*/
_saveOriginalBonesInfo: function () {
var bones = this.mesh.skeleton.bones;
for ( var i = 0, il = bones.length; i < il; i ++ ) {
var bone = bones[ i ];
if ( bone.userData.ik === undefined ) bone.userData.ik = {};
bone.userData.ik.originalMatrix = bone.matrix.toArray();
}
},
update: function ( saveOriginalBones ) {
var q = new THREE.Quaternion();
var targetPos = new THREE.Vector3();
var targetVec = new THREE.Vector3();
var effectorPos = new THREE.Vector3();
var effectorVec = new THREE.Vector3();
var linkPos = new THREE.Vector3();
var invLinkQ = new THREE.Quaternion();
var linkScale = new THREE.Vector3();
var axis = new THREE.Vector3();
var bones = this.mesh.skeleton.bones;
var iks = this.mesh.geometry.iks;
var boneParams = this.mesh.geometry.bones;
// for reference overhead reduction in loop
var math = Math;
this.mesh.updateMatrixWorld( true );
if ( saveOriginalBones === true ) this._saveOriginalBonesInfo();
for ( var i = 0, il = iks.length; i < il; i++ ) {
var ik = iks[ i ];
var effector = bones[ ik.effector ];
var target = bones[ ik.target ];
// don't use getWorldPosition() here for the performance
// because it calls updateMatrixWorld( true ) inside.
targetPos.setFromMatrixPosition( target.matrixWorld );
var links = ik.links;
var iteration = ik.iteration !== undefined ? ik.iteration : 1;
for ( var j = 0; j < iteration; j++ ) {
var rotated = false;
for ( var k = 0, kl = links.length; k < kl; k++ ) {
var link = bones[ links[ k ].index ];
// skip this link and following links.
// this skip is used for MMD performance optimization.
if ( links[ k ].enabled === false ) break;
var limitation = links[ k ].limitation;
// don't use getWorldPosition/Quaternion() here for the performance
// because they call updateMatrixWorld( true ) inside.
link.matrixWorld.decompose( linkPos, invLinkQ, linkScale );
invLinkQ.inverse();
effectorPos.setFromMatrixPosition( effector.matrixWorld );
// work in link world
effectorVec.subVectors( effectorPos, linkPos );
effectorVec.applyQuaternion( invLinkQ );
effectorVec.normalize();
targetVec.subVectors( targetPos, linkPos );
targetVec.applyQuaternion( invLinkQ );
targetVec.normalize();
var angle = targetVec.dot( effectorVec );
if ( angle > 1.0 ) {
angle = 1.0;
} else if ( angle < -1.0 ) {
angle = -1.0;
}
angle = math.acos( angle );
// skip if changing angle is too small to prevent vibration of bone
// Refer to http://www20.atpages.jp/katwat/three.js_r58/examples/mytest37/mmd.three.js
if ( angle < 1e-5 ) continue;
if ( ik.minAngle !== undefined && angle < ik.minAngle ) {
angle = ik.minAngle;
}
if ( ik.maxAngle !== undefined && angle > ik.maxAngle ) {
angle = ik.maxAngle;
}
axis.crossVectors( effectorVec, targetVec );
axis.normalize();
q.setFromAxisAngle( axis, angle );
link.quaternion.multiply( q );
// TODO: re-consider the limitation specification
if ( limitation !== undefined ) {
var c = link.quaternion.w;
if ( c > 1.0 ) {
c = 1.0;
}
var c2 = math.sqrt( 1 - c * c );
link.quaternion.set( limitation.x * c2,
limitation.y * c2,
limitation.z * c2,
c );
}
link.updateMatrixWorld( true );
rotated = true;
}
if ( ! rotated ) break;
}
}
// just in case
this.mesh.updateMatrixWorld( true );
}
};
THREE.CCDIKHelper = function ( mesh ) {
if ( mesh.geometry.iks === undefined || mesh.skeleton === undefined ) {
throw 'THREE.CCDIKHelper requires iks in mesh.geometry and skeleton in mesh.';
}
THREE.Object3D.call( this );
this.root = mesh;
this.matrix = mesh.matrixWorld;
this.matrixAutoUpdate = false;
this.sphereGeometry = new THREE.SphereBufferGeometry( 0.25, 16, 8 );
this.targetSphereMaterial = new THREE.MeshBasicMaterial( {
color: new THREE.Color( 0xff8888 ),
depthTest: false,
depthWrite: false,
transparent: true
} );
this.effectorSphereMaterial = new THREE.MeshBasicMaterial( {
color: new THREE.Color( 0x88ff88 ),
depthTest: false,
depthWrite: false,
transparent: true
} );
this.linkSphereMaterial = new THREE.MeshBasicMaterial( {
color: new THREE.Color( 0x8888ff ),
depthTest: false,
depthWrite: false,
transparent: true
} );
this.lineMaterial = new THREE.LineBasicMaterial( {
color: new THREE.Color( 0xff0000 ),
depthTest: false,
depthWrite: false,
transparent: true
} );
this._init();
this.update();
};
THREE.CCDIKHelper.prototype = Object.create( THREE.Object3D.prototype );
THREE.CCDIKHelper.prototype.constructor = THREE.CCDIKHelper;
THREE.CCDIKHelper.prototype._init = function () {
var self = this;
var mesh = this.root;
var iks = mesh.geometry.iks;
function createLineGeometry( ik ) {
var geometry = new THREE.BufferGeometry();
var vertices = new Float32Array( ( 2 + ik.links.length ) * 3 );
geometry.addAttribute( 'position', new THREE.BufferAttribute( vertices, 3 ) );
return geometry;
}
function createTargetMesh() {
return new THREE.Mesh( self.sphereGeometry, self.targetSphereMaterial );
}
function createEffectorMesh() {
return new THREE.Mesh( self.sphereGeometry, self.effectorSphereMaterial );
}
function createLinkMesh() {
return new THREE.Mesh( self.sphereGeometry, self.linkSphereMaterial );
}
function createLine( ik ) {
return new THREE.Line( createLineGeometry( ik ), self.lineMaterial );
}
for ( var i = 0, il = iks.length; i < il; i ++ ) {
var ik = iks[ i ];
this.add( createTargetMesh() );
this.add( createEffectorMesh() );
for ( var j = 0, jl = ik.links.length; j < jl; j ++ ) {
this.add( createLinkMesh() );
}
this.add( createLine( ik ) );
}
};
THREE.CCDIKHelper.prototype.update = function () {
var offset = 0;
var mesh = this.root;
var iks = mesh.geometry.iks;
var bones = mesh.skeleton.bones;
var matrixWorldInv = new THREE.Matrix4().getInverse( mesh.matrixWorld );
var vector = new THREE.Vector3();
function getPosition( bone ) {
vector.setFromMatrixPosition( bone.matrixWorld );
vector.applyMatrix4( matrixWorldInv );
return vector;
}
function setPositionOfBoneToAttributeArray( array, index, bone ) {
var v = getPosition( bone );
array[ index * 3 + 0 ] = v.x;
array[ index * 3 + 1 ] = v.y;
array[ index * 3 + 2 ] = v.z;
}
for ( var i = 0, il = iks.length; i < il; i ++ ) {
var ik = iks[ i ];
var targetBone = bones[ ik.target ];
var effectorBone = bones[ ik.effector ];
var targetMesh = this.children[ offset ++ ];
var effectorMesh = this.children[ offset ++ ];
targetMesh.position.copy( getPosition( targetBone ) );
effectorMesh.position.copy( getPosition( effectorBone ) );
for ( var j = 0, jl = ik.links.length; j < jl; j ++ ) {
var link = ik.links[ j ];
var linkBone = bones[ link.index ];
var linkMesh = this.children[ offset ++ ];
linkMesh.position.copy( getPosition( linkBone ) );
}
var line = this.children[ offset ++ ];
var array = line.geometry.attributes.position.array;
setPositionOfBoneToAttributeArray( array, 0, targetBone );
setPositionOfBoneToAttributeArray( array, 1, effectorBone );
for ( var j = 0, jl = ik.links.length; j < jl; j ++ ) {
var link = ik.links[ j ];
var linkBone = bones[ link.index ];
setPositionOfBoneToAttributeArray( array, j + 2, linkBone );
}
line.geometry.attributes.position.needsUpdate = true;
}
};

1200
node_modules/three/examples/js/animation/MMDPhysics.js generated vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,188 @@
/**
* @author mrdoob / http://mrdoob.com/
* @author greggman / http://games.greggman.com/
* @author zz85 / http://www.lab4games.net/zz85/blog
* @author kaypiKun
*/
THREE.CinematicCamera = function( fov, aspect, near, far ) {
THREE.PerspectiveCamera.call( this, fov, aspect, near, far );
this.type = "CinematicCamera";
this.postprocessing = { enabled : true };
this.shaderSettings = {
rings: 3,
samples: 4
};
this.material_depth = new THREE.MeshDepthMaterial();
// In case of cinematicCamera, having a default lens set is important
this.setLens();
this.initPostProcessing();
};
THREE.CinematicCamera.prototype = Object.create( THREE.PerspectiveCamera.prototype );
THREE.CinematicCamera.prototype.constructor = THREE.CinematicCamera;
// providing fnumber and coc(Circle of Confusion) as extra arguments
THREE.CinematicCamera.prototype.setLens = function ( focalLength, filmGauge, fNumber, coc ) {
// In case of cinematicCamera, having a default lens set is important
if ( focalLength === undefined ) focalLength = 35;
if ( filmGauge !== undefined ) this.filmGauge = filmGauge;
this.setFocalLength( focalLength );
// if fnumber and coc are not provided, cinematicCamera tries to act as a basic PerspectiveCamera
if ( fNumber === undefined ) fNumber = 8;
if ( coc === undefined ) coc = 0.019;
this.fNumber = fNumber;
this.coc = coc;
// fNumber is focalLength by aperture
this.aperture = focalLength / this.fNumber;
// hyperFocal is required to calculate depthOfField when a lens tries to focus at a distance with given fNumber and focalLength
this.hyperFocal = ( focalLength * focalLength ) / ( this.aperture * this.coc );
};
THREE.CinematicCamera.prototype.linearize = function ( depth ) {
var zfar = this.far;
var znear = this.near;
return - zfar * znear / ( depth * ( zfar - znear ) - zfar );
};
THREE.CinematicCamera.prototype.smoothstep = function ( near, far, depth ) {
var x = this.saturate( ( depth - near ) / ( far - near ) );
return x * x * ( 3 - 2 * x );
};
THREE.CinematicCamera.prototype.saturate = function ( x ) {
return Math.max( 0, Math.min( 1, x ) );
};
// function for focusing at a distance from the camera
THREE.CinematicCamera.prototype.focusAt = function ( focusDistance ) {
if ( focusDistance === undefined ) focusDistance = 20;
var focalLength = this.getFocalLength();
// distance from the camera (normal to frustrum) to focus on
this.focus = focusDistance;
// the nearest point from the camera which is in focus (unused)
this.nearPoint = ( this.hyperFocal * this.focus ) / ( this.hyperFocal + ( this.focus - focalLength ) );
// the farthest point from the camera which is in focus (unused)
this.farPoint = ( this.hyperFocal * this.focus ) / ( this.hyperFocal - ( this.focus - focalLength ) );
// the gap or width of the space in which is everything is in focus (unused)
this.depthOfField = this.farPoint - this.nearPoint;
// Considering minimum distance of focus for a standard lens (unused)
if ( this.depthOfField < 0 ) this.depthOfField = 0;
this.sdistance = this.smoothstep( this.near, this.far, this.focus );
this.ldistance = this.linearize( 1 - this.sdistance );
this.postprocessing.bokeh_uniforms[ 'focalDepth' ].value = this.ldistance;
};
THREE.CinematicCamera.prototype.initPostProcessing = function () {
if ( this.postprocessing.enabled ) {
this.postprocessing.scene = new THREE.Scene();
this.postprocessing.camera = new THREE.OrthographicCamera( window.innerWidth / - 2, window.innerWidth / 2, window.innerHeight / 2, window.innerHeight / - 2, - 10000, 10000 );
this.postprocessing.scene.add( this.postprocessing.camera );
var pars = { minFilter: THREE.LinearFilter, magFilter: THREE.LinearFilter, format: THREE.RGBFormat };
this.postprocessing.rtTextureDepth = new THREE.WebGLRenderTarget( window.innerWidth, window.innerHeight, pars );
this.postprocessing.rtTextureColor = new THREE.WebGLRenderTarget( window.innerWidth, window.innerHeight, pars );
var bokeh_shader = THREE.BokehShader;
this.postprocessing.bokeh_uniforms = THREE.UniformsUtils.clone( bokeh_shader.uniforms );
this.postprocessing.bokeh_uniforms[ "tColor" ].value = this.postprocessing.rtTextureColor.texture;
this.postprocessing.bokeh_uniforms[ "tDepth" ].value = this.postprocessing.rtTextureDepth.texture;
this.postprocessing.bokeh_uniforms[ "manualdof" ].value = 0;
this.postprocessing.bokeh_uniforms[ "shaderFocus" ].value = 0;
this.postprocessing.bokeh_uniforms[ "fstop" ].value = 2.8;
this.postprocessing.bokeh_uniforms[ "showFocus" ].value = 1;
this.postprocessing.bokeh_uniforms[ "focalDepth" ].value = 0.1;
//console.log( this.postprocessing.bokeh_uniforms[ "focalDepth" ].value );
this.postprocessing.bokeh_uniforms[ "znear" ].value = this.near;
this.postprocessing.bokeh_uniforms[ "zfar" ].value = this.near;
this.postprocessing.bokeh_uniforms[ "textureWidth" ].value = window.innerWidth;
this.postprocessing.bokeh_uniforms[ "textureHeight" ].value = window.innerHeight;
this.postprocessing.materialBokeh = new THREE.ShaderMaterial( {
uniforms: this.postprocessing.bokeh_uniforms,
vertexShader: bokeh_shader.vertexShader,
fragmentShader: bokeh_shader.fragmentShader,
defines: {
RINGS: this.shaderSettings.rings,
SAMPLES: this.shaderSettings.samples
}
} );
this.postprocessing.quad = new THREE.Mesh( new THREE.PlaneBufferGeometry( window.innerWidth, window.innerHeight ), this.postprocessing.materialBokeh );
this.postprocessing.quad.position.z = - 500;
this.postprocessing.scene.add( this.postprocessing.quad );
}
};
THREE.CinematicCamera.prototype.renderCinematic = function ( scene, renderer ) {
if ( this.postprocessing.enabled ) {
renderer.clear();
// Render scene into texture
scene.overrideMaterial = null;
renderer.render( scene, camera, this.postprocessing.rtTextureColor, true );
// Render depth into texture
scene.overrideMaterial = this.material_depth;
renderer.render( scene, camera, this.postprocessing.rtTextureDepth, true );
// Render bokeh composite
renderer.render( this.postprocessing.scene, this.postprocessing.camera );
}
};

View File

@@ -0,0 +1,230 @@
/**
* @author zz85 / http://twitter.com/blurspline / http://www.lab4games.net/zz85/blog
*
* A general perpose camera, for setting FOV, Lens Focal Length,
* and switching between perspective and orthographic views easily.
* Use this only if you do not wish to manage
* both a Orthographic and Perspective Camera
*
*/
THREE.CombinedCamera = function ( width, height, fov, near, far, orthoNear, orthoFar ) {
THREE.Camera.call( this );
this.fov = fov;
this.left = - width / 2;
this.right = width / 2;
this.top = height / 2;
this.bottom = - height / 2;
// We could also handle the projectionMatrix internally, but just wanted to test nested camera objects
this.cameraO = new THREE.OrthographicCamera( width / - 2, width / 2, height / 2, height / - 2, orthoNear, orthoFar );
this.cameraP = new THREE.PerspectiveCamera( fov, width / height, near, far );
this.zoom = 1;
this.toPerspective();
};
THREE.CombinedCamera.prototype = Object.create( THREE.Camera.prototype );
THREE.CombinedCamera.prototype.constructor = THREE.CombinedCamera;
THREE.CombinedCamera.prototype.toPerspective = function () {
// Switches to the Perspective Camera
this.near = this.cameraP.near;
this.far = this.cameraP.far;
this.cameraP.fov = this.fov / this.zoom ;
this.cameraP.updateProjectionMatrix();
this.projectionMatrix = this.cameraP.projectionMatrix;
this.inPerspectiveMode = true;
this.inOrthographicMode = false;
};
THREE.CombinedCamera.prototype.toOrthographic = function () {
// Switches to the Orthographic camera estimating viewport from Perspective
var fov = this.fov;
var aspect = this.cameraP.aspect;
var near = this.cameraP.near;
var far = this.cameraP.far;
// The size that we set is the mid plane of the viewing frustum
var hyperfocus = ( near + far ) / 2;
var halfHeight = Math.tan( fov * Math.PI / 180 / 2 ) * hyperfocus;
var halfWidth = halfHeight * aspect;
halfHeight /= this.zoom;
halfWidth /= this.zoom;
this.cameraO.left = - halfWidth;
this.cameraO.right = halfWidth;
this.cameraO.top = halfHeight;
this.cameraO.bottom = - halfHeight;
// this.cameraO.left = -farHalfWidth;
// this.cameraO.right = farHalfWidth;
// this.cameraO.top = farHalfHeight;
// this.cameraO.bottom = -farHalfHeight;
// this.cameraO.left = this.left / this.zoom;
// this.cameraO.right = this.right / this.zoom;
// this.cameraO.top = this.top / this.zoom;
// this.cameraO.bottom = this.bottom / this.zoom;
this.cameraO.updateProjectionMatrix();
this.near = this.cameraO.near;
this.far = this.cameraO.far;
this.projectionMatrix = this.cameraO.projectionMatrix;
this.inPerspectiveMode = false;
this.inOrthographicMode = true;
};
THREE.CombinedCamera.prototype.setSize = function( width, height ) {
this.cameraP.aspect = width / height;
this.left = - width / 2;
this.right = width / 2;
this.top = height / 2;
this.bottom = - height / 2;
};
THREE.CombinedCamera.prototype.setFov = function( fov ) {
this.fov = fov;
if ( this.inPerspectiveMode ) {
this.toPerspective();
} else {
this.toOrthographic();
}
};
// For maintaining similar API with PerspectiveCamera
THREE.CombinedCamera.prototype.updateProjectionMatrix = function() {
if ( this.inPerspectiveMode ) {
this.toPerspective();
} else {
this.toPerspective();
this.toOrthographic();
}
};
/*
* Uses Focal Length (in mm) to estimate and set FOV
* 35mm (full frame) camera is used if frame size is not specified;
* Formula based on http://www.bobatkins.com/photography/technical/field_of_view.html
*/
THREE.CombinedCamera.prototype.setLens = function ( focalLength, filmGauge ) {
if ( filmGauge === undefined ) filmGauge = 35;
var vExtentSlope = 0.5 * filmGauge /
( focalLength * Math.max( this.cameraP.aspect, 1 ) );
var fov = THREE.Math.RAD2DEG * 2 * Math.atan( vExtentSlope );
this.setFov( fov );
return fov;
};
THREE.CombinedCamera.prototype.setZoom = function( zoom ) {
this.zoom = zoom;
if ( this.inPerspectiveMode ) {
this.toPerspective();
} else {
this.toOrthographic();
}
};
THREE.CombinedCamera.prototype.toFrontView = function() {
this.rotation.x = 0;
this.rotation.y = 0;
this.rotation.z = 0;
// should we be modifing the matrix instead?
};
THREE.CombinedCamera.prototype.toBackView = function() {
this.rotation.x = 0;
this.rotation.y = Math.PI;
this.rotation.z = 0;
};
THREE.CombinedCamera.prototype.toLeftView = function() {
this.rotation.x = 0;
this.rotation.y = - Math.PI / 2;
this.rotation.z = 0;
};
THREE.CombinedCamera.prototype.toRightView = function() {
this.rotation.x = 0;
this.rotation.y = Math.PI / 2;
this.rotation.z = 0;
};
THREE.CombinedCamera.prototype.toTopView = function() {
this.rotation.x = - Math.PI / 2;
this.rotation.y = 0;
this.rotation.z = 0;
};
THREE.CombinedCamera.prototype.toBottomView = function() {
this.rotation.x = Math.PI / 2;
this.rotation.y = 0;
this.rotation.z = 0;
};

View File

@@ -0,0 +1,111 @@
/**
* @author richt / http://richt.me
* @author WestLangley / http://github.com/WestLangley
*
* W3C Device Orientation control (http://w3c.github.io/deviceorientation/spec-source-orientation.html)
*/
THREE.DeviceOrientationControls = function( object ) {
var scope = this;
this.object = object;
this.object.rotation.reorder( "YXZ" );
this.enabled = true;
this.deviceOrientation = {};
this.screenOrientation = 0;
this.alpha = 0;
this.alphaOffsetAngle = 0;
var onDeviceOrientationChangeEvent = function( event ) {
scope.deviceOrientation = event;
};
var onScreenOrientationChangeEvent = function() {
scope.screenOrientation = window.orientation || 0;
};
// The angles alpha, beta and gamma form a set of intrinsic Tait-Bryan angles of type Z-X'-Y''
var setObjectQuaternion = function() {
var zee = new THREE.Vector3( 0, 0, 1 );
var euler = new THREE.Euler();
var q0 = new THREE.Quaternion();
var q1 = new THREE.Quaternion( - Math.sqrt( 0.5 ), 0, 0, Math.sqrt( 0.5 ) ); // - PI/2 around the x-axis
return function( quaternion, alpha, beta, gamma, orient ) {
euler.set( beta, alpha, - gamma, 'YXZ' ); // 'ZXY' for the device, but 'YXZ' for us
quaternion.setFromEuler( euler ); // orient the device
quaternion.multiply( q1 ); // camera looks out the back of the device, not the top
quaternion.multiply( q0.setFromAxisAngle( zee, - orient ) ); // adjust for screen orientation
}
}();
this.connect = function() {
onScreenOrientationChangeEvent(); // run once on load
window.addEventListener( 'orientationchange', onScreenOrientationChangeEvent, false );
window.addEventListener( 'deviceorientation', onDeviceOrientationChangeEvent, false );
scope.enabled = true;
};
this.disconnect = function() {
window.removeEventListener( 'orientationchange', onScreenOrientationChangeEvent, false );
window.removeEventListener( 'deviceorientation', onDeviceOrientationChangeEvent, false );
scope.enabled = false;
};
this.update = function() {
if ( scope.enabled === false ) return;
var alpha = scope.deviceOrientation.alpha ? THREE.Math.degToRad( scope.deviceOrientation.alpha ) + this.alphaOffsetAngle : 0; // Z
var beta = scope.deviceOrientation.beta ? THREE.Math.degToRad( scope.deviceOrientation.beta ) : 0; // X'
var gamma = scope.deviceOrientation.gamma ? THREE.Math.degToRad( scope.deviceOrientation.gamma ) : 0; // Y''
var orient = scope.screenOrientation ? THREE.Math.degToRad( scope.screenOrientation ) : 0; // O
setObjectQuaternion( scope.object.quaternion, alpha, beta, gamma, orient );
this.alpha = alpha;
};
this.updateAlphaOffsetAngle = function( angle ) {
this.alphaOffsetAngle = angle;
this.update();
};
this.dispose = function() {
this.disconnect();
};
this.connect();
};

193
node_modules/three/examples/js/controls/DragControls.js generated vendored Normal file
View File

@@ -0,0 +1,193 @@
/*
* @author zz85 / https://github.com/zz85
* @author mrdoob / http://mrdoob.com
* Running this will allow you to drag three.js objects around the screen.
*/
THREE.DragControls = function ( _objects, _camera, _domElement ) {
if ( _objects instanceof THREE.Camera ) {
console.warn( 'THREE.DragControls: Constructor now expects ( objects, camera, domElement )' );
var temp = _objects; _objects = _camera; _camera = temp;
}
var _plane = new THREE.Plane();
var _raycaster = new THREE.Raycaster();
var _mouse = new THREE.Vector2();
var _offset = new THREE.Vector3();
var _intersection = new THREE.Vector3();
var _selected = null, _hovered = null;
//
var scope = this;
function activate() {
_domElement.addEventListener( 'mousemove', onDocumentMouseMove, false );
_domElement.addEventListener( 'mousedown', onDocumentMouseDown, false );
_domElement.addEventListener( 'mouseup', onDocumentMouseUp, false );
}
function deactivate() {
_domElement.removeEventListener( 'mousemove', onDocumentMouseMove, false );
_domElement.removeEventListener( 'mousedown', onDocumentMouseDown, false );
_domElement.removeEventListener( 'mouseup', onDocumentMouseUp, false );
}
function dispose() {
deactivate();
}
function onDocumentMouseMove( event ) {
event.preventDefault();
_mouse.x = ( event.clientX / _domElement.width ) * 2 - 1;
_mouse.y = - ( event.clientY / _domElement.height ) * 2 + 1;
_raycaster.setFromCamera( _mouse, _camera );
if ( _selected && scope.enabled ) {
if ( _raycaster.ray.intersectPlane( _plane, _intersection ) ) {
_selected.position.copy( _intersection.sub( _offset ) );
}
scope.dispatchEvent( { type: 'drag', object: _selected } );
return;
}
_raycaster.setFromCamera( _mouse, _camera );
var intersects = _raycaster.intersectObjects( _objects );
if ( intersects.length > 0 ) {
var object = intersects[ 0 ].object;
_plane.setFromNormalAndCoplanarPoint( _camera.getWorldDirection( _plane.normal ), object.position );
if ( _hovered !== object ) {
scope.dispatchEvent( { type: 'hoveron', object: object } );
_domElement.style.cursor = 'pointer';
_hovered = object;
}
} else {
if ( _hovered !== null ) {
scope.dispatchEvent( { type: 'hoveroff', object: _hovered } );
_domElement.style.cursor = 'auto';
_hovered = null;
}
}
}
function onDocumentMouseDown( event ) {
event.preventDefault();
_raycaster.setFromCamera( _mouse, _camera );
var intersects = _raycaster.intersectObjects( _objects );
if ( intersects.length > 0 ) {
_selected = intersects[ 0 ].object;
if ( _raycaster.ray.intersectPlane( _plane, _intersection ) ) {
_offset.copy( _intersection ).sub( _selected.position );
}
_domElement.style.cursor = 'move';
scope.dispatchEvent( { type: 'dragstart', object: _selected } );
}
}
function onDocumentMouseUp( event ) {
event.preventDefault();
if ( _selected ) {
scope.dispatchEvent( { type: 'dragend', object: _selected } );
_selected = null;
}
_domElement.style.cursor = 'auto';
}
activate();
// API
this.enabled = true;
this.activate = activate;
this.deactivate = deactivate;
this.dispose = dispose;
// Backward compatibility
this.setObjects = function () {
console.error( 'THREE.DragControls: setObjects() has been removed.' );
};
this.on = function ( type, listener ) {
console.warn( 'THREE.DragControls: on() has been deprecated. Use addEventListener() instead.' );
scope.addEventListener( type, listener );
};
this.off = function ( type, listener ) {
console.warn( 'THREE.DragControls: off() has been deprecated. Use removeEventListener() instead.' );
scope.removeEventListener( type, listener );
};
this.notify = function ( type ) {
console.error( 'THREE.DragControls: notify() has been deprecated. Use dispatchEvent() instead.' );
scope.dispatchEvent( { type: type } );
};
};
THREE.DragControls.prototype = Object.create( THREE.EventDispatcher.prototype );
THREE.DragControls.prototype.constructor = THREE.DragControls;

View File

@@ -0,0 +1,293 @@
/**
* @author qiao / https://github.com/qiao
* @author mrdoob / http://mrdoob.com
* @author alteredq / http://alteredqualia.com/
* @author WestLangley / http://github.com/WestLangley
*/
THREE.EditorControls = function ( object, domElement ) {
domElement = ( domElement !== undefined ) ? domElement : document;
// API
this.enabled = true;
this.center = new THREE.Vector3();
this.panSpeed = 0.001;
this.zoomSpeed = 0.001;
this.rotationSpeed = 0.005;
// internals
var scope = this;
var vector = new THREE.Vector3();
var STATE = { NONE: - 1, ROTATE: 0, ZOOM: 1, PAN: 2 };
var state = STATE.NONE;
var center = this.center;
var normalMatrix = new THREE.Matrix3();
var pointer = new THREE.Vector2();
var pointerOld = new THREE.Vector2();
var spherical = new THREE.Spherical();
// events
var changeEvent = { type: 'change' };
this.focus = function ( target ) {
var box = new THREE.Box3().setFromObject( target );
object.lookAt( center.copy( box.getCenter() ) );
scope.dispatchEvent( changeEvent );
};
this.pan = function ( delta ) {
var distance = object.position.distanceTo( center );
delta.multiplyScalar( distance * scope.panSpeed );
delta.applyMatrix3( normalMatrix.getNormalMatrix( object.matrix ) );
object.position.add( delta );
center.add( delta );
scope.dispatchEvent( changeEvent );
};
this.zoom = function ( delta ) {
var distance = object.position.distanceTo( center );
delta.multiplyScalar( distance * scope.zoomSpeed );
if ( delta.length() > distance ) return;
delta.applyMatrix3( normalMatrix.getNormalMatrix( object.matrix ) );
object.position.add( delta );
scope.dispatchEvent( changeEvent );
};
this.rotate = function ( delta ) {
vector.copy( object.position ).sub( center );
spherical.setFromVector3( vector );
spherical.theta += delta.x;
spherical.phi += delta.y;
spherical.makeSafe();
vector.setFromSpherical( spherical );
object.position.copy( center ).add( vector );
object.lookAt( center );
scope.dispatchEvent( changeEvent );
};
// mouse
function onMouseDown( event ) {
if ( scope.enabled === false ) return;
if ( event.button === 0 ) {
state = STATE.ROTATE;
} else if ( event.button === 1 ) {
state = STATE.ZOOM;
} else if ( event.button === 2 ) {
state = STATE.PAN;
}
pointerOld.set( event.clientX, event.clientY );
domElement.addEventListener( 'mousemove', onMouseMove, false );
domElement.addEventListener( 'mouseup', onMouseUp, false );
domElement.addEventListener( 'mouseout', onMouseUp, false );
domElement.addEventListener( 'dblclick', onMouseUp, false );
}
function onMouseMove( event ) {
if ( scope.enabled === false ) return;
pointer.set( event.clientX, event.clientY );
var movementX = pointer.x - pointerOld.x;
var movementY = pointer.y - pointerOld.y;
if ( state === STATE.ROTATE ) {
scope.rotate( new THREE.Vector3( - movementX * scope.rotationSpeed, - movementY * scope.rotationSpeed, 0 ) );
} else if ( state === STATE.ZOOM ) {
scope.zoom( new THREE.Vector3( 0, 0, movementY ) );
} else if ( state === STATE.PAN ) {
scope.pan( new THREE.Vector3( - movementX, movementY, 0 ) );
}
pointerOld.set( event.clientX, event.clientY );
}
function onMouseUp( event ) {
domElement.removeEventListener( 'mousemove', onMouseMove, false );
domElement.removeEventListener( 'mouseup', onMouseUp, false );
domElement.removeEventListener( 'mouseout', onMouseUp, false );
domElement.removeEventListener( 'dblclick', onMouseUp, false );
state = STATE.NONE;
}
function onMouseWheel( event ) {
event.preventDefault();
// if ( scope.enabled === false ) return;
scope.zoom( new THREE.Vector3( 0, 0, event.deltaY ) );
}
function contextmenu( event ) {
event.preventDefault();
}
this.dispose = function() {
domElement.removeEventListener( 'contextmenu', contextmenu, false );
domElement.removeEventListener( 'mousedown', onMouseDown, false );
domElement.removeEventListener( 'wheel', onMouseWheel, false );
domElement.removeEventListener( 'mousemove', onMouseMove, false );
domElement.removeEventListener( 'mouseup', onMouseUp, false );
domElement.removeEventListener( 'mouseout', onMouseUp, false );
domElement.removeEventListener( 'dblclick', onMouseUp, false );
domElement.removeEventListener( 'touchstart', touchStart, false );
domElement.removeEventListener( 'touchmove', touchMove, false );
};
domElement.addEventListener( 'contextmenu', contextmenu, false );
domElement.addEventListener( 'mousedown', onMouseDown, false );
domElement.addEventListener( 'wheel', onMouseWheel, false );
// touch
var touch = new THREE.Vector3();
var touches = [ new THREE.Vector3(), new THREE.Vector3(), new THREE.Vector3() ];
var prevTouches = [ new THREE.Vector3(), new THREE.Vector3(), new THREE.Vector3() ];
var prevDistance = null;
function touchStart( event ) {
if ( scope.enabled === false ) return;
switch ( event.touches.length ) {
case 1:
touches[ 0 ].set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY, 0 );
touches[ 1 ].set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY, 0 );
break;
case 2:
touches[ 0 ].set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY, 0 );
touches[ 1 ].set( event.touches[ 1 ].pageX, event.touches[ 1 ].pageY, 0 );
prevDistance = touches[ 0 ].distanceTo( touches[ 1 ] );
break;
}
prevTouches[ 0 ].copy( touches[ 0 ] );
prevTouches[ 1 ].copy( touches[ 1 ] );
}
function touchMove( event ) {
if ( scope.enabled === false ) return;
event.preventDefault();
event.stopPropagation();
function getClosest( touch, touches ) {
var closest = touches[ 0 ];
for ( var i in touches ) {
if ( closest.distanceTo( touch ) > touches[ i ].distanceTo( touch ) ) closest = touches[ i ];
}
return closest;
}
switch ( event.touches.length ) {
case 1:
touches[ 0 ].set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY, 0 );
touches[ 1 ].set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY, 0 );
scope.rotate( touches[ 0 ].sub( getClosest( touches[ 0 ], prevTouches ) ).multiplyScalar( - scope.rotationSpeed ) );
break;
case 2:
touches[ 0 ].set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY, 0 );
touches[ 1 ].set( event.touches[ 1 ].pageX, event.touches[ 1 ].pageY, 0 );
distance = touches[ 0 ].distanceTo( touches[ 1 ] );
scope.zoom( new THREE.Vector3( 0, 0, prevDistance - distance ) );
prevDistance = distance;
var offset0 = touches[ 0 ].clone().sub( getClosest( touches[ 0 ], prevTouches ) );
var offset1 = touches[ 1 ].clone().sub( getClosest( touches[ 1 ], prevTouches ) );
offset0.x = - offset0.x;
offset1.x = - offset1.x;
scope.pan( offset0.add( offset1 ).multiplyScalar( 0.5 ) );
break;
}
prevTouches[ 0 ].copy( touches[ 0 ] );
prevTouches[ 1 ].copy( touches[ 1 ] );
}
domElement.addEventListener( 'touchstart', touchStart, false );
domElement.addEventListener( 'touchmove', touchMove, false );
};
THREE.EditorControls.prototype = Object.create( THREE.EventDispatcher.prototype );
THREE.EditorControls.prototype.constructor = THREE.EditorControls;

View File

@@ -0,0 +1,300 @@
/**
* @author mrdoob / http://mrdoob.com/
* @author alteredq / http://alteredqualia.com/
* @author paulirish / http://paulirish.com/
*/
THREE.FirstPersonControls = function ( object, domElement ) {
this.object = object;
this.target = new THREE.Vector3( 0, 0, 0 );
this.domElement = ( domElement !== undefined ) ? domElement : document;
this.enabled = true;
this.movementSpeed = 1.0;
this.lookSpeed = 0.005;
this.lookVertical = true;
this.autoForward = false;
this.activeLook = true;
this.heightSpeed = false;
this.heightCoef = 1.0;
this.heightMin = 0.0;
this.heightMax = 1.0;
this.constrainVertical = false;
this.verticalMin = 0;
this.verticalMax = Math.PI;
this.autoSpeedFactor = 0.0;
this.mouseX = 0;
this.mouseY = 0;
this.lat = 0;
this.lon = 0;
this.phi = 0;
this.theta = 0;
this.moveForward = false;
this.moveBackward = false;
this.moveLeft = false;
this.moveRight = false;
this.mouseDragOn = false;
this.viewHalfX = 0;
this.viewHalfY = 0;
if ( this.domElement !== document ) {
this.domElement.setAttribute( 'tabindex', - 1 );
}
//
this.handleResize = function () {
if ( this.domElement === document ) {
this.viewHalfX = window.innerWidth / 2;
this.viewHalfY = window.innerHeight / 2;
} else {
this.viewHalfX = this.domElement.offsetWidth / 2;
this.viewHalfY = this.domElement.offsetHeight / 2;
}
};
this.onMouseDown = function ( event ) {
if ( this.domElement !== document ) {
this.domElement.focus();
}
event.preventDefault();
event.stopPropagation();
if ( this.activeLook ) {
switch ( event.button ) {
case 0: this.moveForward = true; break;
case 2: this.moveBackward = true; break;
}
}
this.mouseDragOn = true;
};
this.onMouseUp = function ( event ) {
event.preventDefault();
event.stopPropagation();
if ( this.activeLook ) {
switch ( event.button ) {
case 0: this.moveForward = false; break;
case 2: this.moveBackward = false; break;
}
}
this.mouseDragOn = false;
};
this.onMouseMove = function ( event ) {
if ( this.domElement === document ) {
this.mouseX = event.pageX - this.viewHalfX;
this.mouseY = event.pageY - this.viewHalfY;
} else {
this.mouseX = event.pageX - this.domElement.offsetLeft - this.viewHalfX;
this.mouseY = event.pageY - this.domElement.offsetTop - this.viewHalfY;
}
};
this.onKeyDown = function ( event ) {
//event.preventDefault();
switch ( event.keyCode ) {
case 38: /*up*/
case 87: /*W*/ this.moveForward = true; break;
case 37: /*left*/
case 65: /*A*/ this.moveLeft = true; break;
case 40: /*down*/
case 83: /*S*/ this.moveBackward = true; break;
case 39: /*right*/
case 68: /*D*/ this.moveRight = true; break;
case 82: /*R*/ this.moveUp = true; break;
case 70: /*F*/ this.moveDown = true; break;
}
};
this.onKeyUp = function ( event ) {
switch ( event.keyCode ) {
case 38: /*up*/
case 87: /*W*/ this.moveForward = false; break;
case 37: /*left*/
case 65: /*A*/ this.moveLeft = false; break;
case 40: /*down*/
case 83: /*S*/ this.moveBackward = false; break;
case 39: /*right*/
case 68: /*D*/ this.moveRight = false; break;
case 82: /*R*/ this.moveUp = false; break;
case 70: /*F*/ this.moveDown = false; break;
}
};
this.update = function( delta ) {
if ( this.enabled === false ) return;
if ( this.heightSpeed ) {
var y = THREE.Math.clamp( this.object.position.y, this.heightMin, this.heightMax );
var heightDelta = y - this.heightMin;
this.autoSpeedFactor = delta * ( heightDelta * this.heightCoef );
} else {
this.autoSpeedFactor = 0.0;
}
var actualMoveSpeed = delta * this.movementSpeed;
if ( this.moveForward || ( this.autoForward && ! this.moveBackward ) ) this.object.translateZ( - ( actualMoveSpeed + this.autoSpeedFactor ) );
if ( this.moveBackward ) this.object.translateZ( actualMoveSpeed );
if ( this.moveLeft ) this.object.translateX( - actualMoveSpeed );
if ( this.moveRight ) this.object.translateX( actualMoveSpeed );
if ( this.moveUp ) this.object.translateY( actualMoveSpeed );
if ( this.moveDown ) this.object.translateY( - actualMoveSpeed );
var actualLookSpeed = delta * this.lookSpeed;
if ( ! this.activeLook ) {
actualLookSpeed = 0;
}
var verticalLookRatio = 1;
if ( this.constrainVertical ) {
verticalLookRatio = Math.PI / ( this.verticalMax - this.verticalMin );
}
this.lon += this.mouseX * actualLookSpeed;
if ( this.lookVertical ) this.lat -= this.mouseY * actualLookSpeed * verticalLookRatio;
this.lat = Math.max( - 85, Math.min( 85, this.lat ) );
this.phi = THREE.Math.degToRad( 90 - this.lat );
this.theta = THREE.Math.degToRad( this.lon );
if ( this.constrainVertical ) {
this.phi = THREE.Math.mapLinear( this.phi, 0, Math.PI, this.verticalMin, this.verticalMax );
}
var targetPosition = this.target,
position = this.object.position;
targetPosition.x = position.x + 100 * Math.sin( this.phi ) * Math.cos( this.theta );
targetPosition.y = position.y + 100 * Math.cos( this.phi );
targetPosition.z = position.z + 100 * Math.sin( this.phi ) * Math.sin( this.theta );
this.object.lookAt( targetPosition );
};
function contextmenu( event ) {
event.preventDefault();
}
this.dispose = function() {
this.domElement.removeEventListener( 'contextmenu', contextmenu, false );
this.domElement.removeEventListener( 'mousedown', _onMouseDown, false );
this.domElement.removeEventListener( 'mousemove', _onMouseMove, false );
this.domElement.removeEventListener( 'mouseup', _onMouseUp, false );
window.removeEventListener( 'keydown', _onKeyDown, false );
window.removeEventListener( 'keyup', _onKeyUp, false );
};
var _onMouseMove = bind( this, this.onMouseMove );
var _onMouseDown = bind( this, this.onMouseDown );
var _onMouseUp = bind( this, this.onMouseUp );
var _onKeyDown = bind( this, this.onKeyDown );
var _onKeyUp = bind( this, this.onKeyUp );
this.domElement.addEventListener( 'contextmenu', contextmenu, false );
this.domElement.addEventListener( 'mousemove', _onMouseMove, false );
this.domElement.addEventListener( 'mousedown', _onMouseDown, false );
this.domElement.addEventListener( 'mouseup', _onMouseUp, false );
window.addEventListener( 'keydown', _onKeyDown, false );
window.addEventListener( 'keyup', _onKeyUp, false );
function bind( scope, fn ) {
return function () {
fn.apply( scope, arguments );
};
}
this.handleResize();
};

293
node_modules/three/examples/js/controls/FlyControls.js generated vendored Normal file
View File

@@ -0,0 +1,293 @@
/**
* @author James Baicoianu / http://www.baicoianu.com/
*/
THREE.FlyControls = function ( object, domElement ) {
this.object = object;
this.domElement = ( domElement !== undefined ) ? domElement : document;
if ( domElement ) this.domElement.setAttribute( 'tabindex', - 1 );
// API
this.movementSpeed = 1.0;
this.rollSpeed = 0.005;
this.dragToLook = false;
this.autoForward = false;
// disable default target object behavior
// internals
this.tmpQuaternion = new THREE.Quaternion();
this.mouseStatus = 0;
this.moveState = { up: 0, down: 0, left: 0, right: 0, forward: 0, back: 0, pitchUp: 0, pitchDown: 0, yawLeft: 0, yawRight: 0, rollLeft: 0, rollRight: 0 };
this.moveVector = new THREE.Vector3( 0, 0, 0 );
this.rotationVector = new THREE.Vector3( 0, 0, 0 );
this.handleEvent = function ( event ) {
if ( typeof this[ event.type ] == 'function' ) {
this[ event.type ]( event );
}
};
this.keydown = function( event ) {
if ( event.altKey ) {
return;
}
//event.preventDefault();
switch ( event.keyCode ) {
case 16: /* shift */ this.movementSpeedMultiplier = .1; break;
case 87: /*W*/ this.moveState.forward = 1; break;
case 83: /*S*/ this.moveState.back = 1; break;
case 65: /*A*/ this.moveState.left = 1; break;
case 68: /*D*/ this.moveState.right = 1; break;
case 82: /*R*/ this.moveState.up = 1; break;
case 70: /*F*/ this.moveState.down = 1; break;
case 38: /*up*/ this.moveState.pitchUp = 1; break;
case 40: /*down*/ this.moveState.pitchDown = 1; break;
case 37: /*left*/ this.moveState.yawLeft = 1; break;
case 39: /*right*/ this.moveState.yawRight = 1; break;
case 81: /*Q*/ this.moveState.rollLeft = 1; break;
case 69: /*E*/ this.moveState.rollRight = 1; break;
}
this.updateMovementVector();
this.updateRotationVector();
};
this.keyup = function( event ) {
switch ( event.keyCode ) {
case 16: /* shift */ this.movementSpeedMultiplier = 1; break;
case 87: /*W*/ this.moveState.forward = 0; break;
case 83: /*S*/ this.moveState.back = 0; break;
case 65: /*A*/ this.moveState.left = 0; break;
case 68: /*D*/ this.moveState.right = 0; break;
case 82: /*R*/ this.moveState.up = 0; break;
case 70: /*F*/ this.moveState.down = 0; break;
case 38: /*up*/ this.moveState.pitchUp = 0; break;
case 40: /*down*/ this.moveState.pitchDown = 0; break;
case 37: /*left*/ this.moveState.yawLeft = 0; break;
case 39: /*right*/ this.moveState.yawRight = 0; break;
case 81: /*Q*/ this.moveState.rollLeft = 0; break;
case 69: /*E*/ this.moveState.rollRight = 0; break;
}
this.updateMovementVector();
this.updateRotationVector();
};
this.mousedown = function( event ) {
if ( this.domElement !== document ) {
this.domElement.focus();
}
event.preventDefault();
event.stopPropagation();
if ( this.dragToLook ) {
this.mouseStatus ++;
} else {
switch ( event.button ) {
case 0: this.moveState.forward = 1; break;
case 2: this.moveState.back = 1; break;
}
this.updateMovementVector();
}
};
this.mousemove = function( event ) {
if ( ! this.dragToLook || this.mouseStatus > 0 ) {
var container = this.getContainerDimensions();
var halfWidth = container.size[ 0 ] / 2;
var halfHeight = container.size[ 1 ] / 2;
this.moveState.yawLeft = - ( ( event.pageX - container.offset[ 0 ] ) - halfWidth ) / halfWidth;
this.moveState.pitchDown = ( ( event.pageY - container.offset[ 1 ] ) - halfHeight ) / halfHeight;
this.updateRotationVector();
}
};
this.mouseup = function( event ) {
event.preventDefault();
event.stopPropagation();
if ( this.dragToLook ) {
this.mouseStatus --;
this.moveState.yawLeft = this.moveState.pitchDown = 0;
} else {
switch ( event.button ) {
case 0: this.moveState.forward = 0; break;
case 2: this.moveState.back = 0; break;
}
this.updateMovementVector();
}
this.updateRotationVector();
};
this.update = function( delta ) {
var moveMult = delta * this.movementSpeed;
var rotMult = delta * this.rollSpeed;
this.object.translateX( this.moveVector.x * moveMult );
this.object.translateY( this.moveVector.y * moveMult );
this.object.translateZ( this.moveVector.z * moveMult );
this.tmpQuaternion.set( this.rotationVector.x * rotMult, this.rotationVector.y * rotMult, this.rotationVector.z * rotMult, 1 ).normalize();
this.object.quaternion.multiply( this.tmpQuaternion );
// expose the rotation vector for convenience
this.object.rotation.setFromQuaternion( this.object.quaternion, this.object.rotation.order );
};
this.updateMovementVector = function() {
var forward = ( this.moveState.forward || ( this.autoForward && ! this.moveState.back ) ) ? 1 : 0;
this.moveVector.x = ( - this.moveState.left + this.moveState.right );
this.moveVector.y = ( - this.moveState.down + this.moveState.up );
this.moveVector.z = ( - forward + this.moveState.back );
//console.log( 'move:', [ this.moveVector.x, this.moveVector.y, this.moveVector.z ] );
};
this.updateRotationVector = function() {
this.rotationVector.x = ( - this.moveState.pitchDown + this.moveState.pitchUp );
this.rotationVector.y = ( - this.moveState.yawRight + this.moveState.yawLeft );
this.rotationVector.z = ( - this.moveState.rollRight + this.moveState.rollLeft );
//console.log( 'rotate:', [ this.rotationVector.x, this.rotationVector.y, this.rotationVector.z ] );
};
this.getContainerDimensions = function() {
if ( this.domElement != document ) {
return {
size : [ this.domElement.offsetWidth, this.domElement.offsetHeight ],
offset : [ this.domElement.offsetLeft, this.domElement.offsetTop ]
};
} else {
return {
size : [ window.innerWidth, window.innerHeight ],
offset : [ 0, 0 ]
};
}
};
function bind( scope, fn ) {
return function () {
fn.apply( scope, arguments );
};
}
function contextmenu( event ) {
event.preventDefault();
}
this.dispose = function() {
this.domElement.removeEventListener( 'contextmenu', contextmenu, false );
this.domElement.removeEventListener( 'mousedown', _mousedown, false );
this.domElement.removeEventListener( 'mousemove', _mousemove, false );
this.domElement.removeEventListener( 'mouseup', _mouseup, false );
window.removeEventListener( 'keydown', _keydown, false );
window.removeEventListener( 'keyup', _keyup, false );
};
var _mousemove = bind( this, this.mousemove );
var _mousedown = bind( this, this.mousedown );
var _mouseup = bind( this, this.mouseup );
var _keydown = bind( this, this.keydown );
var _keyup = bind( this, this.keyup );
this.domElement.addEventListener( 'contextmenu', contextmenu, false );
this.domElement.addEventListener( 'mousemove', _mousemove, false );
this.domElement.addEventListener( 'mousedown', _mousedown, false );
this.domElement.addEventListener( 'mouseup', _mouseup, false );
window.addEventListener( 'keydown', _keydown, false );
window.addEventListener( 'keyup', _keyup, false );
this.updateMovementVector();
this.updateRotationVector();
};

1016
node_modules/three/examples/js/controls/OrbitControls.js generated vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,636 @@
/**
* @author Eberhard Graether / http://egraether.com/
* @author Mark Lundin / http://mark-lundin.com
* @author Patrick Fuller / http://patrick-fuller.com
* @author Max Smolens / https://github.com/msmolens
*/
THREE.OrthographicTrackballControls = function ( object, domElement ) {
var _this = this;
var STATE = { NONE: - 1, ROTATE: 0, ZOOM: 1, PAN: 2, TOUCH_ROTATE: 3, TOUCH_ZOOM_PAN: 4 };
this.object = object;
this.domElement = ( domElement !== undefined ) ? domElement : document;
// API
this.enabled = true;
this.screen = { left: 0, top: 0, width: 0, height: 0 };
this.radius = 0;
this.rotateSpeed = 1.0;
this.zoomSpeed = 1.2;
this.noRotate = false;
this.noZoom = false;
this.noPan = false;
this.noRoll = false;
this.staticMoving = false;
this.dynamicDampingFactor = 0.2;
this.keys = [ 65 /*A*/, 83 /*S*/, 68 /*D*/ ];
// internals
this.target = new THREE.Vector3();
var EPS = 0.000001;
var _changed = true;
var _state = STATE.NONE,
_prevState = STATE.NONE,
_eye = new THREE.Vector3(),
_rotateStart = new THREE.Vector3(),
_rotateEnd = new THREE.Vector3(),
_zoomStart = new THREE.Vector2(),
_zoomEnd = new THREE.Vector2(),
_touchZoomDistanceStart = 0,
_touchZoomDistanceEnd = 0,
_panStart = new THREE.Vector2(),
_panEnd = new THREE.Vector2();
// for reset
this.target0 = this.target.clone();
this.position0 = this.object.position.clone();
this.up0 = this.object.up.clone();
this.left0 = this.object.left;
this.right0 = this.object.right;
this.top0 = this.object.top;
this.bottom0 = this.object.bottom;
// events
var changeEvent = { type: 'change' };
var startEvent = { type: 'start' };
var endEvent = { type: 'end' };
// methods
this.handleResize = function () {
if ( this.domElement === document ) {
this.screen.left = 0;
this.screen.top = 0;
this.screen.width = window.innerWidth;
this.screen.height = window.innerHeight;
} else {
var box = this.domElement.getBoundingClientRect();
// adjustments come from similar code in the jquery offset() function
var d = this.domElement.ownerDocument.documentElement;
this.screen.left = box.left + window.pageXOffset - d.clientLeft;
this.screen.top = box.top + window.pageYOffset - d.clientTop;
this.screen.width = box.width;
this.screen.height = box.height;
}
this.radius = 0.5 * Math.min( this.screen.width, this.screen.height );
this.left0 = this.object.left;
this.right0 = this.object.right;
this.top0 = this.object.top;
this.bottom0 = this.object.bottom;
};
this.handleEvent = function ( event ) {
if ( typeof this[ event.type ] == 'function' ) {
this[ event.type ]( event );
}
};
var getMouseOnScreen = ( function () {
var vector = new THREE.Vector2();
return function getMouseOnScreen( pageX, pageY ) {
vector.set(
( pageX - _this.screen.left ) / _this.screen.width,
( pageY - _this.screen.top ) / _this.screen.height
);
return vector;
};
}() );
var getMouseProjectionOnBall = ( function () {
var vector = new THREE.Vector3();
var objectUp = new THREE.Vector3();
var mouseOnBall = new THREE.Vector3();
return function getMouseProjectionOnBall( pageX, pageY ) {
mouseOnBall.set(
( pageX - _this.screen.width * 0.5 - _this.screen.left ) / _this.radius,
( _this.screen.height * 0.5 + _this.screen.top - pageY ) / _this.radius,
0.0
);
var length = mouseOnBall.length();
if ( _this.noRoll ) {
if ( length < Math.SQRT1_2 ) {
mouseOnBall.z = Math.sqrt( 1.0 - length * length );
} else {
mouseOnBall.z = .5 / length;
}
} else if ( length > 1.0 ) {
mouseOnBall.normalize();
} else {
mouseOnBall.z = Math.sqrt( 1.0 - length * length );
}
_eye.copy( _this.object.position ).sub( _this.target );
vector.copy( _this.object.up ).setLength( mouseOnBall.y );
vector.add( objectUp.copy( _this.object.up ).cross( _eye ).setLength( mouseOnBall.x ) );
vector.add( _eye.setLength( mouseOnBall.z ) );
return vector;
};
}() );
this.rotateCamera = ( function() {
var axis = new THREE.Vector3(),
quaternion = new THREE.Quaternion();
return function rotateCamera() {
var angle = Math.acos( _rotateStart.dot( _rotateEnd ) / _rotateStart.length() / _rotateEnd.length() );
if ( angle ) {
axis.crossVectors( _rotateStart, _rotateEnd ).normalize();
angle *= _this.rotateSpeed;
quaternion.setFromAxisAngle( axis, - angle );
_eye.applyQuaternion( quaternion );
_this.object.up.applyQuaternion( quaternion );
_rotateEnd.applyQuaternion( quaternion );
if ( _this.staticMoving ) {
_rotateStart.copy( _rotateEnd );
} else {
quaternion.setFromAxisAngle( axis, angle * ( _this.dynamicDampingFactor - 1.0 ) );
_rotateStart.applyQuaternion( quaternion );
}
_changed = true;
}
}
}() );
this.zoomCamera = function () {
if ( _state === STATE.TOUCH_ZOOM_PAN ) {
var factor = _touchZoomDistanceEnd / _touchZoomDistanceStart;
_touchZoomDistanceStart = _touchZoomDistanceEnd;
_this.object.zoom *= factor;
_changed = true;
} else {
var factor = 1.0 + ( _zoomEnd.y - _zoomStart.y ) * _this.zoomSpeed;
if ( Math.abs( factor - 1.0 ) > EPS && factor > 0.0 ) {
_this.object.zoom /= factor;
if ( _this.staticMoving ) {
_zoomStart.copy( _zoomEnd );
} else {
_zoomStart.y += ( _zoomEnd.y - _zoomStart.y ) * this.dynamicDampingFactor;
}
_changed = true;
}
}
};
this.panCamera = ( function() {
var mouseChange = new THREE.Vector2(),
objectUp = new THREE.Vector3(),
pan = new THREE.Vector3();
return function panCamera() {
mouseChange.copy( _panEnd ).sub( _panStart );
if ( mouseChange.lengthSq() ) {
// Scale movement to keep clicked/dragged position under cursor
var scale_x = ( _this.object.right - _this.object.left ) / _this.object.zoom;
var scale_y = ( _this.object.top - _this.object.bottom ) / _this.object.zoom;
mouseChange.x *= scale_x;
mouseChange.y *= scale_y;
pan.copy( _eye ).cross( _this.object.up ).setLength( mouseChange.x );
pan.add( objectUp.copy( _this.object.up ).setLength( mouseChange.y ) );
_this.object.position.add( pan );
_this.target.add( pan );
if ( _this.staticMoving ) {
_panStart.copy( _panEnd );
} else {
_panStart.add( mouseChange.subVectors( _panEnd, _panStart ).multiplyScalar( _this.dynamicDampingFactor ) );
}
_changed = true;
}
}
}() );
this.update = function () {
_eye.subVectors( _this.object.position, _this.target );
if ( ! _this.noRotate ) {
_this.rotateCamera();
}
if ( ! _this.noZoom ) {
_this.zoomCamera();
if ( _changed ) {
_this.object.updateProjectionMatrix();
}
}
if ( ! _this.noPan ) {
_this.panCamera();
}
_this.object.position.addVectors( _this.target, _eye );
_this.object.lookAt( _this.target );
if ( _changed ) {
_this.dispatchEvent( changeEvent );
_changed = false;
}
};
this.reset = function () {
_state = STATE.NONE;
_prevState = STATE.NONE;
_this.target.copy( _this.target0 );
_this.object.position.copy( _this.position0 );
_this.object.up.copy( _this.up0 );
_eye.subVectors( _this.object.position, _this.target );
_this.object.left = _this.left0;
_this.object.right = _this.right0;
_this.object.top = _this.top0;
_this.object.bottom = _this.bottom0;
_this.object.lookAt( _this.target );
_this.dispatchEvent( changeEvent );
_changed = false;
};
// listeners
function keydown( event ) {
if ( _this.enabled === false ) return;
window.removeEventListener( 'keydown', keydown );
_prevState = _state;
if ( _state !== STATE.NONE ) {
return;
} else if ( event.keyCode === _this.keys[ STATE.ROTATE ] && ! _this.noRotate ) {
_state = STATE.ROTATE;
} else if ( event.keyCode === _this.keys[ STATE.ZOOM ] && ! _this.noZoom ) {
_state = STATE.ZOOM;
} else if ( event.keyCode === _this.keys[ STATE.PAN ] && ! _this.noPan ) {
_state = STATE.PAN;
}
}
function keyup( event ) {
if ( _this.enabled === false ) return;
_state = _prevState;
window.addEventListener( 'keydown', keydown, false );
}
function mousedown( event ) {
if ( _this.enabled === false ) return;
event.preventDefault();
event.stopPropagation();
if ( _state === STATE.NONE ) {
_state = event.button;
}
if ( _state === STATE.ROTATE && ! _this.noRotate ) {
_rotateStart.copy( getMouseProjectionOnBall( event.pageX, event.pageY ) );
_rotateEnd.copy( _rotateStart );
} else if ( _state === STATE.ZOOM && ! _this.noZoom ) {
_zoomStart.copy( getMouseOnScreen( event.pageX, event.pageY ) );
_zoomEnd.copy( _zoomStart );
} else if ( _state === STATE.PAN && ! _this.noPan ) {
_panStart.copy( getMouseOnScreen( event.pageX, event.pageY ) );
_panEnd.copy( _panStart )
}
document.addEventListener( 'mousemove', mousemove, false );
document.addEventListener( 'mouseup', mouseup, false );
_this.dispatchEvent( startEvent );
}
function mousemove( event ) {
if ( _this.enabled === false ) return;
event.preventDefault();
event.stopPropagation();
if ( _state === STATE.ROTATE && ! _this.noRotate ) {
_rotateEnd.copy( getMouseProjectionOnBall( event.pageX, event.pageY ) );
} else if ( _state === STATE.ZOOM && ! _this.noZoom ) {
_zoomEnd.copy( getMouseOnScreen( event.pageX, event.pageY ) );
} else if ( _state === STATE.PAN && ! _this.noPan ) {
_panEnd.copy( getMouseOnScreen( event.pageX, event.pageY ) );
}
}
function mouseup( event ) {
if ( _this.enabled === false ) return;
event.preventDefault();
event.stopPropagation();
_state = STATE.NONE;
document.removeEventListener( 'mousemove', mousemove );
document.removeEventListener( 'mouseup', mouseup );
_this.dispatchEvent( endEvent );
}
function mousewheel( event ) {
if ( _this.enabled === false ) return;
event.preventDefault();
event.stopPropagation();
_zoomStart.y += event.deltaY * 0.01;
_this.dispatchEvent( startEvent );
_this.dispatchEvent( endEvent );
}
function touchstart( event ) {
if ( _this.enabled === false ) return;
switch ( event.touches.length ) {
case 1:
_state = STATE.TOUCH_ROTATE;
_rotateStart.copy( getMouseProjectionOnBall( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ) );
_rotateEnd.copy( _rotateStart );
break;
case 2:
_state = STATE.TOUCH_ZOOM_PAN;
var dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX;
var dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY;
_touchZoomDistanceEnd = _touchZoomDistanceStart = Math.sqrt( dx * dx + dy * dy );
var x = ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX ) / 2;
var y = ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY ) / 2;
_panStart.copy( getMouseOnScreen( x, y ) );
_panEnd.copy( _panStart );
break;
default:
_state = STATE.NONE;
}
_this.dispatchEvent( startEvent );
}
function touchmove( event ) {
if ( _this.enabled === false ) return;
event.preventDefault();
event.stopPropagation();
switch ( event.touches.length ) {
case 1:
_rotateEnd.copy( getMouseProjectionOnBall( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ) );
break;
case 2:
var dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX;
var dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY;
_touchZoomDistanceEnd = Math.sqrt( dx * dx + dy * dy );
var x = ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX ) / 2;
var y = ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY ) / 2;
_panEnd.copy( getMouseOnScreen( x, y ) );
break;
default:
_state = STATE.NONE;
}
}
function touchend( event ) {
if ( _this.enabled === false ) return;
switch ( event.touches.length ) {
case 1:
_rotateEnd.copy( getMouseProjectionOnBall( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ) );
_rotateStart.copy( _rotateEnd );
break;
case 2:
_touchZoomDistanceStart = _touchZoomDistanceEnd = 0;
var x = ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX ) / 2;
var y = ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY ) / 2;
_panEnd.copy( getMouseOnScreen( x, y ) );
_panStart.copy( _panEnd );
break;
}
_state = STATE.NONE;
_this.dispatchEvent( endEvent );
}
function contextmenu( event ) {
event.preventDefault();
}
this.dispose = function() {
this.domElement.removeEventListener( 'contextmenu', contextmenu, false );
this.domElement.removeEventListener( 'mousedown', mousedown, false );
this.domElement.removeEventListener( 'wheel', mousewheel, false );
this.domElement.removeEventListener( 'touchstart', touchstart, false );
this.domElement.removeEventListener( 'touchend', touchend, false );
this.domElement.removeEventListener( 'touchmove', touchmove, false );
document.removeEventListener( 'mousemove', mousemove, false );
document.removeEventListener( 'mouseup', mouseup, false );
window.removeEventListener( 'keydown', keydown, false );
window.removeEventListener( 'keyup', keyup, false );
};
this.domElement.addEventListener( 'contextmenu', contextmenu, false );
this.domElement.addEventListener( 'mousedown', mousedown, false );
this.domElement.addEventListener( 'wheel', mousewheel, false );
this.domElement.addEventListener( 'touchstart', touchstart, false );
this.domElement.addEventListener( 'touchend', touchend, false );
this.domElement.addEventListener( 'touchmove', touchmove, false );
window.addEventListener( 'keydown', keydown, false );
window.addEventListener( 'keyup', keyup, false );
this.handleResize();
// force an update at start
this.update();
};
THREE.OrthographicTrackballControls.prototype = Object.create( THREE.EventDispatcher.prototype );
THREE.OrthographicTrackballControls.prototype.constructor = THREE.OrthographicTrackballControls;

View File

@@ -0,0 +1,69 @@
/**
* @author mrdoob / http://mrdoob.com/
*/
THREE.PointerLockControls = function ( camera ) {
var scope = this;
camera.rotation.set( 0, 0, 0 );
var pitchObject = new THREE.Object3D();
pitchObject.add( camera );
var yawObject = new THREE.Object3D();
yawObject.position.y = 10;
yawObject.add( pitchObject );
var PI_2 = Math.PI / 2;
var onMouseMove = function ( event ) {
if ( scope.enabled === false ) return;
var movementX = event.movementX || event.mozMovementX || event.webkitMovementX || 0;
var movementY = event.movementY || event.mozMovementY || event.webkitMovementY || 0;
yawObject.rotation.y -= movementX * 0.002;
pitchObject.rotation.x -= movementY * 0.002;
pitchObject.rotation.x = Math.max( - PI_2, Math.min( PI_2, pitchObject.rotation.x ) );
};
this.dispose = function() {
document.removeEventListener( 'mousemove', onMouseMove, false );
};
document.addEventListener( 'mousemove', onMouseMove, false );
this.enabled = false;
this.getObject = function () {
return yawObject;
};
this.getDirection = function() {
// assumes the camera itself is not rotated
var direction = new THREE.Vector3( 0, 0, - 1 );
var rotation = new THREE.Euler( 0, 0, 0, "YXZ" );
return function( v ) {
rotation.set( pitchObject.rotation.x, yawObject.rotation.y, 0 );
v.copy( direction ).applyEuler( rotation );
return v;
};
}();
};

View File

@@ -0,0 +1,623 @@
/**
* @author Eberhard Graether / http://egraether.com/
* @author Mark Lundin / http://mark-lundin.com
* @author Simone Manini / http://daron1337.github.io
* @author Luca Antiga / http://lantiga.github.io
*/
THREE.TrackballControls = function ( object, domElement ) {
var _this = this;
var STATE = { NONE: - 1, ROTATE: 0, ZOOM: 1, PAN: 2, TOUCH_ROTATE: 3, TOUCH_ZOOM_PAN: 4 };
this.object = object;
this.domElement = ( domElement !== undefined ) ? domElement : document;
// API
this.enabled = true;
this.screen = { left: 0, top: 0, width: 0, height: 0 };
this.rotateSpeed = 1.0;
this.zoomSpeed = 1.2;
this.panSpeed = 0.3;
this.noRotate = false;
this.noZoom = false;
this.noPan = false;
this.staticMoving = false;
this.dynamicDampingFactor = 0.2;
this.minDistance = 0;
this.maxDistance = Infinity;
this.keys = [ 65 /*A*/, 83 /*S*/, 68 /*D*/ ];
// internals
this.target = new THREE.Vector3();
var EPS = 0.000001;
var lastPosition = new THREE.Vector3();
var _state = STATE.NONE,
_prevState = STATE.NONE,
_eye = new THREE.Vector3(),
_movePrev = new THREE.Vector2(),
_moveCurr = new THREE.Vector2(),
_lastAxis = new THREE.Vector3(),
_lastAngle = 0,
_zoomStart = new THREE.Vector2(),
_zoomEnd = new THREE.Vector2(),
_touchZoomDistanceStart = 0,
_touchZoomDistanceEnd = 0,
_panStart = new THREE.Vector2(),
_panEnd = new THREE.Vector2();
// for reset
this.target0 = this.target.clone();
this.position0 = this.object.position.clone();
this.up0 = this.object.up.clone();
// events
var changeEvent = { type: 'change' };
var startEvent = { type: 'start' };
var endEvent = { type: 'end' };
// methods
this.handleResize = function () {
if ( this.domElement === document ) {
this.screen.left = 0;
this.screen.top = 0;
this.screen.width = window.innerWidth;
this.screen.height = window.innerHeight;
} else {
var box = this.domElement.getBoundingClientRect();
// adjustments come from similar code in the jquery offset() function
var d = this.domElement.ownerDocument.documentElement;
this.screen.left = box.left + window.pageXOffset - d.clientLeft;
this.screen.top = box.top + window.pageYOffset - d.clientTop;
this.screen.width = box.width;
this.screen.height = box.height;
}
};
this.handleEvent = function ( event ) {
if ( typeof this[ event.type ] == 'function' ) {
this[ event.type ]( event );
}
};
var getMouseOnScreen = ( function () {
var vector = new THREE.Vector2();
return function getMouseOnScreen( pageX, pageY ) {
vector.set(
( pageX - _this.screen.left ) / _this.screen.width,
( pageY - _this.screen.top ) / _this.screen.height
);
return vector;
};
}() );
var getMouseOnCircle = ( function () {
var vector = new THREE.Vector2();
return function getMouseOnCircle( pageX, pageY ) {
vector.set(
( ( pageX - _this.screen.width * 0.5 - _this.screen.left ) / ( _this.screen.width * 0.5 ) ),
( ( _this.screen.height + 2 * ( _this.screen.top - pageY ) ) / _this.screen.width ) // screen.width intentional
);
return vector;
};
}() );
this.rotateCamera = ( function() {
var axis = new THREE.Vector3(),
quaternion = new THREE.Quaternion(),
eyeDirection = new THREE.Vector3(),
objectUpDirection = new THREE.Vector3(),
objectSidewaysDirection = new THREE.Vector3(),
moveDirection = new THREE.Vector3(),
angle;
return function rotateCamera() {
moveDirection.set( _moveCurr.x - _movePrev.x, _moveCurr.y - _movePrev.y, 0 );
angle = moveDirection.length();
if ( angle ) {
_eye.copy( _this.object.position ).sub( _this.target );
eyeDirection.copy( _eye ).normalize();
objectUpDirection.copy( _this.object.up ).normalize();
objectSidewaysDirection.crossVectors( objectUpDirection, eyeDirection ).normalize();
objectUpDirection.setLength( _moveCurr.y - _movePrev.y );
objectSidewaysDirection.setLength( _moveCurr.x - _movePrev.x );
moveDirection.copy( objectUpDirection.add( objectSidewaysDirection ) );
axis.crossVectors( moveDirection, _eye ).normalize();
angle *= _this.rotateSpeed;
quaternion.setFromAxisAngle( axis, angle );
_eye.applyQuaternion( quaternion );
_this.object.up.applyQuaternion( quaternion );
_lastAxis.copy( axis );
_lastAngle = angle;
} else if ( ! _this.staticMoving && _lastAngle ) {
_lastAngle *= Math.sqrt( 1.0 - _this.dynamicDampingFactor );
_eye.copy( _this.object.position ).sub( _this.target );
quaternion.setFromAxisAngle( _lastAxis, _lastAngle );
_eye.applyQuaternion( quaternion );
_this.object.up.applyQuaternion( quaternion );
}
_movePrev.copy( _moveCurr );
};
}() );
this.zoomCamera = function () {
var factor;
if ( _state === STATE.TOUCH_ZOOM_PAN ) {
factor = _touchZoomDistanceStart / _touchZoomDistanceEnd;
_touchZoomDistanceStart = _touchZoomDistanceEnd;
_eye.multiplyScalar( factor );
} else {
factor = 1.0 + ( _zoomEnd.y - _zoomStart.y ) * _this.zoomSpeed;
if ( factor !== 1.0 && factor > 0.0 ) {
_eye.multiplyScalar( factor );
}
if ( _this.staticMoving ) {
_zoomStart.copy( _zoomEnd );
} else {
_zoomStart.y += ( _zoomEnd.y - _zoomStart.y ) * this.dynamicDampingFactor;
}
}
};
this.panCamera = ( function() {
var mouseChange = new THREE.Vector2(),
objectUp = new THREE.Vector3(),
pan = new THREE.Vector3();
return function panCamera() {
mouseChange.copy( _panEnd ).sub( _panStart );
if ( mouseChange.lengthSq() ) {
mouseChange.multiplyScalar( _eye.length() * _this.panSpeed );
pan.copy( _eye ).cross( _this.object.up ).setLength( mouseChange.x );
pan.add( objectUp.copy( _this.object.up ).setLength( mouseChange.y ) );
_this.object.position.add( pan );
_this.target.add( pan );
if ( _this.staticMoving ) {
_panStart.copy( _panEnd );
} else {
_panStart.add( mouseChange.subVectors( _panEnd, _panStart ).multiplyScalar( _this.dynamicDampingFactor ) );
}
}
};
}() );
this.checkDistances = function () {
if ( ! _this.noZoom || ! _this.noPan ) {
if ( _eye.lengthSq() > _this.maxDistance * _this.maxDistance ) {
_this.object.position.addVectors( _this.target, _eye.setLength( _this.maxDistance ) );
_zoomStart.copy( _zoomEnd );
}
if ( _eye.lengthSq() < _this.minDistance * _this.minDistance ) {
_this.object.position.addVectors( _this.target, _eye.setLength( _this.minDistance ) );
_zoomStart.copy( _zoomEnd );
}
}
};
this.update = function () {
_eye.subVectors( _this.object.position, _this.target );
if ( ! _this.noRotate ) {
_this.rotateCamera();
}
if ( ! _this.noZoom ) {
_this.zoomCamera();
}
if ( ! _this.noPan ) {
_this.panCamera();
}
_this.object.position.addVectors( _this.target, _eye );
_this.checkDistances();
_this.object.lookAt( _this.target );
if ( lastPosition.distanceToSquared( _this.object.position ) > EPS ) {
_this.dispatchEvent( changeEvent );
lastPosition.copy( _this.object.position );
}
};
this.reset = function () {
_state = STATE.NONE;
_prevState = STATE.NONE;
_this.target.copy( _this.target0 );
_this.object.position.copy( _this.position0 );
_this.object.up.copy( _this.up0 );
_eye.subVectors( _this.object.position, _this.target );
_this.object.lookAt( _this.target );
_this.dispatchEvent( changeEvent );
lastPosition.copy( _this.object.position );
};
// listeners
function keydown( event ) {
if ( _this.enabled === false ) return;
window.removeEventListener( 'keydown', keydown );
_prevState = _state;
if ( _state !== STATE.NONE ) {
return;
} else if ( event.keyCode === _this.keys[ STATE.ROTATE ] && ! _this.noRotate ) {
_state = STATE.ROTATE;
} else if ( event.keyCode === _this.keys[ STATE.ZOOM ] && ! _this.noZoom ) {
_state = STATE.ZOOM;
} else if ( event.keyCode === _this.keys[ STATE.PAN ] && ! _this.noPan ) {
_state = STATE.PAN;
}
}
function keyup( event ) {
if ( _this.enabled === false ) return;
_state = _prevState;
window.addEventListener( 'keydown', keydown, false );
}
function mousedown( event ) {
if ( _this.enabled === false ) return;
event.preventDefault();
event.stopPropagation();
if ( _state === STATE.NONE ) {
_state = event.button;
}
if ( _state === STATE.ROTATE && ! _this.noRotate ) {
_moveCurr.copy( getMouseOnCircle( event.pageX, event.pageY ) );
_movePrev.copy( _moveCurr );
} else if ( _state === STATE.ZOOM && ! _this.noZoom ) {
_zoomStart.copy( getMouseOnScreen( event.pageX, event.pageY ) );
_zoomEnd.copy( _zoomStart );
} else if ( _state === STATE.PAN && ! _this.noPan ) {
_panStart.copy( getMouseOnScreen( event.pageX, event.pageY ) );
_panEnd.copy( _panStart );
}
document.addEventListener( 'mousemove', mousemove, false );
document.addEventListener( 'mouseup', mouseup, false );
_this.dispatchEvent( startEvent );
}
function mousemove( event ) {
if ( _this.enabled === false ) return;
event.preventDefault();
event.stopPropagation();
if ( _state === STATE.ROTATE && ! _this.noRotate ) {
_movePrev.copy( _moveCurr );
_moveCurr.copy( getMouseOnCircle( event.pageX, event.pageY ) );
} else if ( _state === STATE.ZOOM && ! _this.noZoom ) {
_zoomEnd.copy( getMouseOnScreen( event.pageX, event.pageY ) );
} else if ( _state === STATE.PAN && ! _this.noPan ) {
_panEnd.copy( getMouseOnScreen( event.pageX, event.pageY ) );
}
}
function mouseup( event ) {
if ( _this.enabled === false ) return;
event.preventDefault();
event.stopPropagation();
_state = STATE.NONE;
document.removeEventListener( 'mousemove', mousemove );
document.removeEventListener( 'mouseup', mouseup );
_this.dispatchEvent( endEvent );
}
function mousewheel( event ) {
if ( _this.enabled === false ) return;
event.preventDefault();
event.stopPropagation();
switch ( event.deltaMode ) {
case 2:
// Zoom in pages
_zoomStart.y -= event.deltaY * 0.025;
break;
case 1:
// Zoom in lines
_zoomStart.y -= event.deltaY * 0.01;
break;
default:
// undefined, 0, assume pixels
_zoomStart.y -= event.deltaY * 0.00025;
break;
}
_this.dispatchEvent( startEvent );
_this.dispatchEvent( endEvent );
}
function touchstart( event ) {
if ( _this.enabled === false ) return;
switch ( event.touches.length ) {
case 1:
_state = STATE.TOUCH_ROTATE;
_moveCurr.copy( getMouseOnCircle( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ) );
_movePrev.copy( _moveCurr );
break;
default: // 2 or more
_state = STATE.TOUCH_ZOOM_PAN;
var dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX;
var dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY;
_touchZoomDistanceEnd = _touchZoomDistanceStart = Math.sqrt( dx * dx + dy * dy );
var x = ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX ) / 2;
var y = ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY ) / 2;
_panStart.copy( getMouseOnScreen( x, y ) );
_panEnd.copy( _panStart );
break;
}
_this.dispatchEvent( startEvent );
}
function touchmove( event ) {
if ( _this.enabled === false ) return;
event.preventDefault();
event.stopPropagation();
switch ( event.touches.length ) {
case 1:
_movePrev.copy( _moveCurr );
_moveCurr.copy( getMouseOnCircle( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ) );
break;
default: // 2 or more
var dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX;
var dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY;
_touchZoomDistanceEnd = Math.sqrt( dx * dx + dy * dy );
var x = ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX ) / 2;
var y = ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY ) / 2;
_panEnd.copy( getMouseOnScreen( x, y ) );
break;
}
}
function touchend( event ) {
if ( _this.enabled === false ) return;
switch ( event.touches.length ) {
case 0:
_state = STATE.NONE;
break;
case 1:
_state = STATE.TOUCH_ROTATE;
_moveCurr.copy( getMouseOnCircle( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ) );
_movePrev.copy( _moveCurr );
break;
}
_this.dispatchEvent( endEvent );
}
function contextmenu( event ) {
event.preventDefault();
}
this.dispose = function() {
this.domElement.removeEventListener( 'contextmenu', contextmenu, false );
this.domElement.removeEventListener( 'mousedown', mousedown, false );
this.domElement.removeEventListener( 'wheel', mousewheel, false );
this.domElement.removeEventListener( 'touchstart', touchstart, false );
this.domElement.removeEventListener( 'touchend', touchend, false );
this.domElement.removeEventListener( 'touchmove', touchmove, false );
document.removeEventListener( 'mousemove', mousemove, false );
document.removeEventListener( 'mouseup', mouseup, false );
window.removeEventListener( 'keydown', keydown, false );
window.removeEventListener( 'keyup', keyup, false );
};
this.domElement.addEventListener( 'contextmenu', contextmenu, false );
this.domElement.addEventListener( 'mousedown', mousedown, false );
this.domElement.addEventListener( 'wheel', mousewheel, false );
this.domElement.addEventListener( 'touchstart', touchstart, false );
this.domElement.addEventListener( 'touchend', touchend, false );
this.domElement.addEventListener( 'touchmove', touchmove, false );
window.addEventListener( 'keydown', keydown, false );
window.addEventListener( 'keyup', keyup, false );
this.handleResize();
// force an update at start
this.update();
};
THREE.TrackballControls.prototype = Object.create( THREE.EventDispatcher.prototype );
THREE.TrackballControls.prototype.constructor = THREE.TrackballControls;

File diff suppressed because it is too large Load Diff

173
node_modules/three/examples/js/controls/VRControls.js generated vendored Normal file
View File

@@ -0,0 +1,173 @@
/**
* @author dmarcos / https://github.com/dmarcos
* @author mrdoob / http://mrdoob.com
*/
THREE.VRControls = function ( object, onError ) {
var scope = this;
var vrDisplay, vrDisplays;
var standingMatrix = new THREE.Matrix4();
var frameData = null;
if ( 'VRFrameData' in window ) {
frameData = new VRFrameData();
}
function gotVRDisplays( displays ) {
vrDisplays = displays;
if ( displays.length > 0 ) {
vrDisplay = displays[ 0 ];
} else {
if ( onError ) onError( 'VR input not available.' );
}
}
if ( navigator.getVRDisplays ) {
navigator.getVRDisplays().then( gotVRDisplays ).catch ( function () {
console.warn( 'THREE.VRControls: Unable to get VR Displays' );
} );
}
// the Rift SDK returns the position in meters
// this scale factor allows the user to define how meters
// are converted to scene units.
this.scale = 1;
// If true will use "standing space" coordinate system where y=0 is the
// floor and x=0, z=0 is the center of the room.
this.standing = false;
// Distance from the users eyes to the floor in meters. Used when
// standing=true but the VRDisplay doesn't provide stageParameters.
this.userHeight = 1.6;
this.getVRDisplay = function () {
return vrDisplay;
};
this.setVRDisplay = function ( value ) {
vrDisplay = value;
};
this.getVRDisplays = function () {
console.warn( 'THREE.VRControls: getVRDisplays() is being deprecated.' );
return vrDisplays;
};
this.getStandingMatrix = function () {
return standingMatrix;
};
this.update = function () {
if ( vrDisplay ) {
var pose;
if ( vrDisplay.getFrameData ) {
vrDisplay.getFrameData( frameData );
pose = frameData.pose;
} else if ( vrDisplay.getPose ) {
pose = vrDisplay.getPose();
}
if ( pose.orientation !== null ) {
object.quaternion.fromArray( pose.orientation );
}
if ( pose.position !== null ) {
object.position.fromArray( pose.position );
} else {
object.position.set( 0, 0, 0 );
}
if ( this.standing ) {
if ( vrDisplay.stageParameters ) {
object.updateMatrix();
standingMatrix.fromArray( vrDisplay.stageParameters.sittingToStandingTransform );
object.applyMatrix( standingMatrix );
} else {
object.position.setY( object.position.y + this.userHeight );
}
}
object.position.multiplyScalar( scope.scale );
}
};
this.resetPose = function () {
if ( vrDisplay ) {
vrDisplay.resetPose();
}
};
this.resetSensor = function () {
console.warn( 'THREE.VRControls: .resetSensor() is now .resetPose().' );
this.resetPose();
};
this.zeroSensor = function () {
console.warn( 'THREE.VRControls: .zeroSensor() is now .resetPose().' );
this.resetPose();
};
this.dispose = function () {
vrDisplay = null;
};
};

39
node_modules/three/examples/js/crossfade/gui.js generated vendored Normal file
View File

@@ -0,0 +1,39 @@
var transitionParams = {
"useTexture": true,
"transition": 0.5,
"transitionSpeed": 2.0,
"texture": 5,
"loopTexture": true,
"animateTransition": true,
"textureThreshold": 0.3
};
function initGUI() {
var gui = new dat.GUI();
gui.add( transitionParams, "useTexture" ).onChange( function( value ) {
transition.useTexture( value );
} );
gui.add( transitionParams, 'loopTexture' );
gui.add( transitionParams, 'texture', { Perlin: 0, Squares: 1, Cells: 2, Distort: 3, Gradient: 4, Radial: 5 } ).onChange( function( value ) {
transition.setTexture( value );
} ).listen();
gui.add( transitionParams, "textureThreshold", 0, 1, 0.01 ).onChange( function( value ) {
transition.setTextureThreshold( value );
} );
gui.add( transitionParams, "animateTransition" );
gui.add( transitionParams, "transition", 0, 1, 0.01 ).listen();
gui.add( transitionParams, "transitionSpeed", 0.5, 5, 0.01 );
}

111
node_modules/three/examples/js/crossfade/scenes.js generated vendored Normal file
View File

@@ -0,0 +1,111 @@
function generateGeometry( objectType, numObjects ) {
var geometry = new THREE.Geometry();
function applyVertexColors( g, c ) {
g.faces.forEach( function( f ) {
var n = ( f instanceof THREE.Face3 ) ? 3 : 4;
for ( var j = 0; j < n; j ++ ) {
f.vertexColors[ j ] = c;
}
} );
}
for ( var i = 0; i < numObjects; i ++ ) {
var position = new THREE.Vector3();
position.x = Math.random() * 10000 - 5000;
position.y = Math.random() * 6000 - 3000;
position.z = Math.random() * 8000 - 4000;
var rotation = new THREE.Euler();
rotation.x = Math.random() * 2 * Math.PI;
rotation.y = Math.random() * 2 * Math.PI;
rotation.z = Math.random() * 2 * Math.PI;
var scale = new THREE.Vector3();
var geom, color = new THREE.Color();
scale.x = Math.random() * 200 + 100;
if ( objectType == "cube" ) {
geom = new THREE.BoxGeometry( 1, 1, 1 );
scale.y = Math.random() * 200 + 100;
scale.z = Math.random() * 200 + 100;
color.setRGB( 0, 0, Math.random() + 0.1 );
} else if ( objectType == "sphere" ) {
geom = new THREE.IcosahedronGeometry( 1, 1 );
scale.y = scale.z = scale.x;
color.setRGB( Math.random() + 0.1, 0, 0 );
}
// give the geom's vertices a random color, to be displayed
applyVertexColors( geom, color );
var mesh = new THREE.Mesh( geom );
mesh.position.copy( position );
mesh.rotation.copy( rotation );
mesh.scale.copy( scale );
mesh.updateMatrix();
geometry.merge( mesh.geometry, mesh.matrix );
}
return geometry;
}
function Scene ( type, numObjects, cameraZ, fov, rotationSpeed, clearColor ) {
this.clearColor = clearColor;
this.camera = new THREE.PerspectiveCamera( fov, window.innerWidth / window.innerHeight, 1, 10000 );
this.camera.position.z = cameraZ;
// Setup scene
this.scene = new THREE.Scene();
this.scene.add( new THREE.AmbientLight( 0x555555 ) );
var light = new THREE.SpotLight( 0xffffff, 1.5 );
light.position.set( 0, 500, 2000 );
this.scene.add( light );
this.rotationSpeed = rotationSpeed;
defaultMaterial = new THREE.MeshPhongMaterial( { color: 0xffffff, shading: THREE.FlatShading, vertexColors: THREE.VertexColors } );
this.mesh = new THREE.Mesh( generateGeometry( type, numObjects ), defaultMaterial );
this.scene.add( this.mesh );
renderTargetParameters = { minFilter: THREE.LinearFilter, magFilter: THREE.LinearFilter, format: THREE.RGBFormat, stencilBuffer: false };
this.fbo = new THREE.WebGLRenderTarget( window.innerWidth, window.innerHeight, renderTargetParameters );
this.render = function( delta, rtt ) {
this.mesh.rotation.x += delta * this.rotationSpeed.x;
this.mesh.rotation.y += delta * this.rotationSpeed.y;
this.mesh.rotation.z += delta * this.rotationSpeed.z;
renderer.setClearColor( this.clearColor );
if ( rtt )
renderer.render( this.scene, this.camera, this.fbo, true );
else
renderer.render( this.scene, this.camera );
};
}

161
node_modules/three/examples/js/crossfade/transition.js generated vendored Normal file
View File

@@ -0,0 +1,161 @@
function Transition ( sceneA, sceneB ) {
this.scene = new THREE.Scene();
this.cameraOrtho = new THREE.OrthographicCamera( window.innerWidth / - 2, window.innerWidth / 2, window.innerHeight / 2, window.innerHeight / - 2, - 10, 10 );
this.textures = [];
for ( var i = 0; i < 6; i ++ )
this.textures[ i ] = new THREE.TextureLoader().load( 'textures/transition/transition' + ( i + 1 ) + '.png' );
this.quadmaterial = new THREE.ShaderMaterial( {
uniforms: {
tDiffuse1: {
value: null
},
tDiffuse2: {
value: null
},
mixRatio: {
value: 0.0
},
threshold: {
value: 0.1
},
useTexture: {
value: 1
},
tMixTexture: {
value: this.textures[ 0 ]
}
},
vertexShader: [
"varying vec2 vUv;",
"void main() {",
"vUv = vec2( uv.x, uv.y );",
"gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",
"}"
].join( "\n" ),
fragmentShader: [
"uniform float mixRatio;",
"uniform sampler2D tDiffuse1;",
"uniform sampler2D tDiffuse2;",
"uniform sampler2D tMixTexture;",
"uniform int useTexture;",
"uniform float threshold;",
"varying vec2 vUv;",
"void main() {",
"vec4 texel1 = texture2D( tDiffuse1, vUv );",
"vec4 texel2 = texture2D( tDiffuse2, vUv );",
"if (useTexture==1) {",
"vec4 transitionTexel = texture2D( tMixTexture, vUv );",
"float r = mixRatio * (1.0 + threshold * 2.0) - threshold;",
"float mixf=clamp((transitionTexel.r - r)*(1.0/threshold), 0.0, 1.0);",
"gl_FragColor = mix( texel1, texel2, mixf );",
"} else {",
"gl_FragColor = mix( texel2, texel1, mixRatio );",
"}",
"}"
].join( "\n" )
} );
quadgeometry = new THREE.PlaneBufferGeometry( window.innerWidth, window.innerHeight );
this.quad = new THREE.Mesh( quadgeometry, this.quadmaterial );
this.scene.add( this.quad );
// Link both scenes and their FBOs
this.sceneA = sceneA;
this.sceneB = sceneB;
this.quadmaterial.uniforms.tDiffuse1.value = sceneA.fbo.texture;
this.quadmaterial.uniforms.tDiffuse2.value = sceneB.fbo.texture;
this.needChange = false;
this.setTextureThreshold = function ( value ) {
this.quadmaterial.uniforms.threshold.value = value;
};
this.useTexture = function ( value ) {
this.quadmaterial.uniforms.useTexture.value = value ? 1 : 0;
};
this.setTexture = function ( i ) {
this.quadmaterial.uniforms.tMixTexture.value = this.textures[ i ];
};
this.render = function( delta ) {
// Transition animation
if ( transitionParams.animateTransition ) {
var t = ( 1 + Math.sin( transitionParams.transitionSpeed * clock.getElapsedTime() / Math.PI ) ) / 2;
transitionParams.transition = THREE.Math.smoothstep( t, 0.3, 0.7 );
// Change the current alpha texture after each transition
if ( transitionParams.loopTexture && ( transitionParams.transition == 0 || transitionParams.transition == 1 ) ) {
if ( this.needChange ) {
transitionParams.texture = ( transitionParams.texture + 1 ) % this.textures.length;
this.quadmaterial.uniforms.tMixTexture.value = this.textures[ transitionParams.texture ];
this.needChange = false;
}
} else
this.needChange = true;
}
this.quadmaterial.uniforms.mixRatio.value = transitionParams.transition;
// Prevent render both scenes when it's not necessary
if ( transitionParams.transition == 0 ) {
this.sceneB.render( delta, false );
} else if ( transitionParams.transition == 1 ) {
this.sceneA.render( delta, false );
} else {
// When 0<transition<1 render transition between two scenes
this.sceneA.render( delta, true );
this.sceneB.render( delta, true );
renderer.render( this.scene, this.cameraOrtho, null, true );
}
}
}

65
node_modules/three/examples/js/curves/NURBSCurve.js generated vendored Normal file
View File

@@ -0,0 +1,65 @@
/**
* @author renej
* NURBS curve object
*
* Derives from Curve, overriding getPoint and getTangent.
*
* Implementation is based on (x, y [, z=0 [, w=1]]) control points with w=weight.
*
**/
/**************************************************************
* NURBS curve
**************************************************************/
THREE.NURBSCurve = function ( degree, knots /* array of reals */, controlPoints /* array of Vector(2|3|4) */ ) {
this.degree = degree;
this.knots = knots;
this.controlPoints = [];
for ( var i = 0; i < controlPoints.length; ++ i ) {
// ensure Vector4 for control points
var point = controlPoints[ i ];
this.controlPoints[ i ] = new THREE.Vector4( point.x, point.y, point.z, point.w );
}
};
THREE.NURBSCurve.prototype = Object.create( THREE.Curve.prototype );
THREE.NURBSCurve.prototype.constructor = THREE.NURBSCurve;
THREE.NURBSCurve.prototype.getPoint = function ( t ) {
var u = this.knots[ 0 ] + t * ( this.knots[ this.knots.length - 1 ] - this.knots[ 0 ] ); // linear mapping t->u
// following results in (wx, wy, wz, w) homogeneous point
var hpoint = THREE.NURBSUtils.calcBSplinePoint( this.degree, this.knots, this.controlPoints, u );
if ( hpoint.w != 1.0 ) {
// project to 3D space: (wx, wy, wz, w) -> (x, y, z, 1)
hpoint.divideScalar( hpoint.w );
}
return new THREE.Vector3( hpoint.x, hpoint.y, hpoint.z );
};
THREE.NURBSCurve.prototype.getTangent = function ( t ) {
var u = this.knots[ 0 ] + t * ( this.knots[ this.knots.length - 1 ] - this.knots[ 0 ] );
var ders = THREE.NURBSUtils.calcNURBSDerivatives( this.degree, this.knots, this.controlPoints, u, 1 );
var tangent = ders[ 1 ].clone();
tangent.normalize();
return tangent;
};

55
node_modules/three/examples/js/curves/NURBSSurface.js generated vendored Normal file
View File

@@ -0,0 +1,55 @@
/**
* @author renej
* NURBS surface object
*
* Implementation is based on (x, y [, z=0 [, w=1]]) control points with w=weight.
*
**/
/**************************************************************
* NURBS surface
**************************************************************/
THREE.NURBSSurface = function ( degree1, degree2, knots1, knots2 /* arrays of reals */, controlPoints /* array^2 of Vector(2|3|4) */ ) {
this.degree1 = degree1;
this.degree2 = degree2;
this.knots1 = knots1;
this.knots2 = knots2;
this.controlPoints = [];
var len1 = knots1.length - degree1 - 1;
var len2 = knots2.length - degree2 - 1;
// ensure Vector4 for control points
for ( var i = 0; i < len1; ++ i ) {
this.controlPoints[ i ] = [];
for ( var j = 0; j < len2; ++ j ) {
var point = controlPoints[ i ][ j ];
this.controlPoints[ i ][ j ] = new THREE.Vector4( point.x, point.y, point.z, point.w );
}
}
};
THREE.NURBSSurface.prototype = {
constructor: THREE.NURBSSurface,
getPoint: function ( t1, t2 ) {
var u = this.knots1[ 0 ] + t1 * ( this.knots1[ this.knots1.length - 1 ] - this.knots1[ 0 ] ); // linear mapping t1->u
var v = this.knots2[ 0 ] + t2 * ( this.knots2[ this.knots2.length - 1 ] - this.knots2[ 0 ] ); // linear mapping t2->u
return THREE.NURBSUtils.calcSurfacePoint( this.degree1, this.degree2, this.knots1, this.knots2, this.controlPoints, u, v );
}
};

472
node_modules/three/examples/js/curves/NURBSUtils.js generated vendored Normal file
View File

@@ -0,0 +1,472 @@
/**
* @author renej
* NURBS utils
*
* See NURBSCurve and NURBSSurface.
*
**/
/**************************************************************
* NURBS Utils
**************************************************************/
THREE.NURBSUtils = {
/*
Finds knot vector span.
p : degree
u : parametric value
U : knot vector
returns the span
*/
findSpan: function( p, u, U ) {
var n = U.length - p - 1;
if ( u >= U[ n ] ) {
return n - 1;
}
if ( u <= U[ p ] ) {
return p;
}
var low = p;
var high = n;
var mid = Math.floor( ( low + high ) / 2 );
while ( u < U[ mid ] || u >= U[ mid + 1 ] ) {
if ( u < U[ mid ] ) {
high = mid;
} else {
low = mid;
}
mid = Math.floor( ( low + high ) / 2 );
}
return mid;
},
/*
Calculate basis functions. See The NURBS Book, page 70, algorithm A2.2
span : span in which u lies
u : parametric point
p : degree
U : knot vector
returns array[p+1] with basis functions values.
*/
calcBasisFunctions: function( span, u, p, U ) {
var N = [];
var left = [];
var right = [];
N[ 0 ] = 1.0;
for ( var j = 1; j <= p; ++ j ) {
left[ j ] = u - U[ span + 1 - j ];
right[ j ] = U[ span + j ] - u;
var saved = 0.0;
for ( var r = 0; r < j; ++ r ) {
var rv = right[ r + 1 ];
var lv = left[ j - r ];
var temp = N[ r ] / ( rv + lv );
N[ r ] = saved + rv * temp;
saved = lv * temp;
}
N[ j ] = saved;
}
return N;
},
/*
Calculate B-Spline curve points. See The NURBS Book, page 82, algorithm A3.1.
p : degree of B-Spline
U : knot vector
P : control points (x, y, z, w)
u : parametric point
returns point for given u
*/
calcBSplinePoint: function( p, U, P, u ) {
var span = this.findSpan( p, u, U );
var N = this.calcBasisFunctions( span, u, p, U );
var C = new THREE.Vector4( 0, 0, 0, 0 );
for ( var j = 0; j <= p; ++ j ) {
var point = P[ span - p + j ];
var Nj = N[ j ];
var wNj = point.w * Nj;
C.x += point.x * wNj;
C.y += point.y * wNj;
C.z += point.z * wNj;
C.w += point.w * Nj;
}
return C;
},
/*
Calculate basis functions derivatives. See The NURBS Book, page 72, algorithm A2.3.
span : span in which u lies
u : parametric point
p : degree
n : number of derivatives to calculate
U : knot vector
returns array[n+1][p+1] with basis functions derivatives
*/
calcBasisFunctionDerivatives: function( span, u, p, n, U ) {
var zeroArr = [];
for ( var i = 0; i <= p; ++ i )
zeroArr[ i ] = 0.0;
var ders = [];
for ( var i = 0; i <= n; ++ i )
ders[ i ] = zeroArr.slice( 0 );
var ndu = [];
for ( var i = 0; i <= p; ++ i )
ndu[ i ] = zeroArr.slice( 0 );
ndu[ 0 ][ 0 ] = 1.0;
var left = zeroArr.slice( 0 );
var right = zeroArr.slice( 0 );
for ( var j = 1; j <= p; ++ j ) {
left[ j ] = u - U[ span + 1 - j ];
right[ j ] = U[ span + j ] - u;
var saved = 0.0;
for ( var r = 0; r < j; ++ r ) {
var rv = right[ r + 1 ];
var lv = left[ j - r ];
ndu[ j ][ r ] = rv + lv;
var temp = ndu[ r ][ j - 1 ] / ndu[ j ][ r ];
ndu[ r ][ j ] = saved + rv * temp;
saved = lv * temp;
}
ndu[ j ][ j ] = saved;
}
for ( var j = 0; j <= p; ++ j ) {
ders[ 0 ][ j ] = ndu[ j ][ p ];
}
for ( var r = 0; r <= p; ++ r ) {
var s1 = 0;
var s2 = 1;
var a = [];
for ( var i = 0; i <= p; ++ i ) {
a[ i ] = zeroArr.slice( 0 );
}
a[ 0 ][ 0 ] = 1.0;
for ( var k = 1; k <= n; ++ k ) {
var d = 0.0;
var rk = r - k;
var pk = p - k;
if ( r >= k ) {
a[ s2 ][ 0 ] = a[ s1 ][ 0 ] / ndu[ pk + 1 ][ rk ];
d = a[ s2 ][ 0 ] * ndu[ rk ][ pk ];
}
var j1 = ( rk >= - 1 ) ? 1 : - rk;
var j2 = ( r - 1 <= pk ) ? k - 1 : p - r;
for ( var j = j1; j <= j2; ++ j ) {
a[ s2 ][ j ] = ( a[ s1 ][ j ] - a[ s1 ][ j - 1 ] ) / ndu[ pk + 1 ][ rk + j ];
d += a[ s2 ][ j ] * ndu[ rk + j ][ pk ];
}
if ( r <= pk ) {
a[ s2 ][ k ] = - a[ s1 ][ k - 1 ] / ndu[ pk + 1 ][ r ];
d += a[ s2 ][ k ] * ndu[ r ][ pk ];
}
ders[ k ][ r ] = d;
var j = s1;
s1 = s2;
s2 = j;
}
}
var r = p;
for ( var k = 1; k <= n; ++ k ) {
for ( var j = 0; j <= p; ++ j ) {
ders[ k ][ j ] *= r;
}
r *= p - k;
}
return ders;
},
/*
Calculate derivatives of a B-Spline. See The NURBS Book, page 93, algorithm A3.2.
p : degree
U : knot vector
P : control points
u : Parametric points
nd : number of derivatives
returns array[d+1] with derivatives
*/
calcBSplineDerivatives: function( p, U, P, u, nd ) {
var du = nd < p ? nd : p;
var CK = [];
var span = this.findSpan( p, u, U );
var nders = this.calcBasisFunctionDerivatives( span, u, p, du, U );
var Pw = [];
for ( var i = 0; i < P.length; ++ i ) {
var point = P[ i ].clone();
var w = point.w;
point.x *= w;
point.y *= w;
point.z *= w;
Pw[ i ] = point;
}
for ( var k = 0; k <= du; ++ k ) {
var point = Pw[ span - p ].clone().multiplyScalar( nders[ k ][ 0 ] );
for ( var j = 1; j <= p; ++ j ) {
point.add( Pw[ span - p + j ].clone().multiplyScalar( nders[ k ][ j ] ) );
}
CK[ k ] = point;
}
for ( var k = du + 1; k <= nd + 1; ++ k ) {
CK[ k ] = new THREE.Vector4( 0, 0, 0 );
}
return CK;
},
/*
Calculate "K over I"
returns k!/(i!(k-i)!)
*/
calcKoverI: function( k, i ) {
var nom = 1;
for ( var j = 2; j <= k; ++ j ) {
nom *= j;
}
var denom = 1;
for ( var j = 2; j <= i; ++ j ) {
denom *= j;
}
for ( var j = 2; j <= k - i; ++ j ) {
denom *= j;
}
return nom / denom;
},
/*
Calculate derivatives (0-nd) of rational curve. See The NURBS Book, page 127, algorithm A4.2.
Pders : result of function calcBSplineDerivatives
returns array with derivatives for rational curve.
*/
calcRationalCurveDerivatives: function ( Pders ) {
var nd = Pders.length;
var Aders = [];
var wders = [];
for ( var i = 0; i < nd; ++ i ) {
var point = Pders[ i ];
Aders[ i ] = new THREE.Vector3( point.x, point.y, point.z );
wders[ i ] = point.w;
}
var CK = [];
for ( var k = 0; k < nd; ++ k ) {
var v = Aders[ k ].clone();
for ( var i = 1; i <= k; ++ i ) {
v.sub( CK[ k - i ].clone().multiplyScalar( this.calcKoverI( k, i ) * wders[ i ] ) );
}
CK[ k ] = v.divideScalar( wders[ 0 ] );
}
return CK;
},
/*
Calculate NURBS curve derivatives. See The NURBS Book, page 127, algorithm A4.2.
p : degree
U : knot vector
P : control points in homogeneous space
u : parametric points
nd : number of derivatives
returns array with derivatives.
*/
calcNURBSDerivatives: function( p, U, P, u, nd ) {
var Pders = this.calcBSplineDerivatives( p, U, P, u, nd );
return this.calcRationalCurveDerivatives( Pders );
},
/*
Calculate rational B-Spline surface point. See The NURBS Book, page 134, algorithm A4.3.
p1, p2 : degrees of B-Spline surface
U1, U2 : knot vectors
P : control points (x, y, z, w)
u, v : parametric values
returns point for given (u, v)
*/
calcSurfacePoint: function( p, q, U, V, P, u, v ) {
var uspan = this.findSpan( p, u, U );
var vspan = this.findSpan( q, v, V );
var Nu = this.calcBasisFunctions( uspan, u, p, U );
var Nv = this.calcBasisFunctions( vspan, v, q, V );
var temp = [];
for ( var l = 0; l <= q; ++ l ) {
temp[ l ] = new THREE.Vector4( 0, 0, 0, 0 );
for ( var k = 0; k <= p; ++ k ) {
var point = P[ uspan - p + k ][ vspan - q + l ].clone();
var w = point.w;
point.x *= w;
point.y *= w;
point.z *= w;
temp[ l ].add( point.multiplyScalar( Nu[ k ] ) );
}
}
var Sw = new THREE.Vector4( 0, 0, 0, 0 );
for ( var l = 0; l <= q; ++ l ) {
Sw.add( temp[ l ].multiplyScalar( Nv[ l ] ) );
}
Sw.divideScalar( Sw.w );
return new THREE.Vector3( Sw.x, Sw.y, Sw.z );
}
};

View File

@@ -0,0 +1,152 @@
/**
* @author mrdoob / http://mrdoob.com/
* @author marklundin / http://mark-lundin.com/
* @author alteredq / http://alteredqualia.com/
* @author tschw
*/
THREE.AnaglyphEffect = function ( renderer, width, height ) {
// Matrices generated with angler.js https://github.com/tschw/angler.js/
// (in column-major element order, as accepted by WebGL)
this.colorMatrixLeft = new THREE.Matrix3().fromArray( [
1.0671679973602295, -0.0016435992438346148, 0.0001777536963345483, // r out
-0.028107794001698494, -0.00019593400065787137, -0.0002875397040043026, // g out
-0.04279090091586113, 0.000015809757314855233, -0.00024287120322696865 // b out
] );
// red green blue in
this.colorMatrixRight = new THREE.Matrix3().fromArray( [
-0.0355340838432312, -0.06440307199954987, 0.018319187685847282, // r out
-0.10269022732973099, 0.8079727292060852, -0.04835830628871918, // g out
0.0001224992738571018, -0.009558862075209618, 0.567823588848114 // b out
] );
var _camera = new THREE.OrthographicCamera( - 1, 1, 1, - 1, 0, 1 );
var _scene = new THREE.Scene();
var _stereo = new THREE.StereoCamera();
var _params = { minFilter: THREE.LinearFilter, magFilter: THREE.NearestFilter, format: THREE.RGBAFormat };
if ( width === undefined ) width = 512;
if ( height === undefined ) height = 512;
var _renderTargetL = new THREE.WebGLRenderTarget( width, height, _params );
var _renderTargetR = new THREE.WebGLRenderTarget( width, height, _params );
var _material = new THREE.ShaderMaterial( {
uniforms: {
"mapLeft": { value: _renderTargetL.texture },
"mapRight": { value: _renderTargetR.texture },
"colorMatrixLeft": { value: this.colorMatrixLeft },
"colorMatrixRight": { value: this.colorMatrixRight }
},
vertexShader: [
"varying vec2 vUv;",
"void main() {",
" vUv = vec2( uv.x, uv.y );",
" gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",
"}"
].join( "\n" ),
fragmentShader: [
"uniform sampler2D mapLeft;",
"uniform sampler2D mapRight;",
"varying vec2 vUv;",
"uniform mat3 colorMatrixLeft;",
"uniform mat3 colorMatrixRight;",
// These functions implement sRGB linearization and gamma correction
"float lin( float c ) {",
" return c <= 0.04045 ? c * 0.0773993808 :",
" pow( c * 0.9478672986 + 0.0521327014, 2.4 );",
"}",
"vec4 lin( vec4 c ) {",
" return vec4( lin( c.r ), lin( c.g ), lin( c.b ), c.a );",
"}",
"float dev( float c ) {",
" return c <= 0.0031308 ? c * 12.92",
" : pow( c, 0.41666 ) * 1.055 - 0.055;",
"}",
"void main() {",
" vec2 uv = vUv;",
" vec4 colorL = lin( texture2D( mapLeft, uv ) );",
" vec4 colorR = lin( texture2D( mapRight, uv ) );",
" vec3 color = clamp(",
" colorMatrixLeft * colorL.rgb +",
" colorMatrixRight * colorR.rgb, 0., 1. );",
" gl_FragColor = vec4(",
" dev( color.r ), dev( color.g ), dev( color.b ),",
" max( colorL.a, colorR.a ) );",
"}"
].join( "\n" )
} );
var mesh = new THREE.Mesh( new THREE.PlaneBufferGeometry( 2, 2 ), _material );
_scene.add( mesh );
this.setSize = function ( width, height ) {
renderer.setSize( width, height );
var pixelRatio = renderer.getPixelRatio();
_renderTargetL.setSize( width * pixelRatio, height * pixelRatio );
_renderTargetR.setSize( width * pixelRatio, height * pixelRatio );
};
this.render = function ( scene, camera ) {
scene.updateMatrixWorld();
if ( camera.parent === null ) camera.updateMatrixWorld();
_stereo.update( camera );
renderer.render( scene, _stereo.cameraL, _renderTargetL, true );
renderer.render( scene, _stereo.cameraR, _renderTargetR, true );
renderer.render( _scene, _camera );
};
this.dispose = function() {
if ( _renderTargetL ) _renderTargetL.dispose();
if ( _renderTargetR ) _renderTargetR.dispose();
};
};

283
node_modules/three/examples/js/effects/AsciiEffect.js generated vendored Normal file
View File

@@ -0,0 +1,283 @@
/*
* @author zz85 / https://github.com/zz85
*
* Ascii generation is based on http://www.nihilogic.dk/labs/jsascii/
* Maybe more about this later with a blog post at http://lab4games.net/zz85/blog
*
* 16 April 2012 - @blurspline
*/
THREE.AsciiEffect = function ( renderer, charSet, options ) {
// its fun to create one your own!
charSet = ( charSet === undefined ) ? ' .:-=+*#%@' : charSet;
// ' .,:;=|iI+hHOE#`$';
// darker bolder character set from https://github.com/saw/Canvas-ASCII-Art/
// ' .\'`^",:;Il!i~+_-?][}{1)(|/tfjrxnuvczXYUJCLQ0OZmwqpdbkhao*#MW&8%B@$'.split('');
if ( ! options ) options = {};
// Some ASCII settings
var bResolution = ! options[ 'resolution' ] ? 0.15 : options[ 'resolution' ]; // Higher for more details
var iScale = ! options[ 'scale' ] ? 1 : options[ 'scale' ];
var bColor = ! options[ 'color' ] ? false : options[ 'color' ]; // nice but slows down rendering!
var bAlpha = ! options[ 'alpha' ] ? false : options[ 'alpha' ]; // Transparency
var bBlock = ! options[ 'block' ] ? false : options[ 'block' ]; // blocked characters. like good O dos
var bInvert = ! options[ 'invert' ] ? false : options[ 'invert' ]; // black is white, white is black
var strResolution = 'low';
var width, height;
var domElement = document.createElement( 'div' );
domElement.style.cursor = 'default';
var oAscii = document.createElement( "table" );
domElement.appendChild( oAscii );
var iWidth, iHeight;
var oImg;
this.setSize = function ( w, h ) {
width = w;
height = h;
renderer.setSize( w, h );
initAsciiSize();
};
this.render = function ( scene, camera ) {
renderer.render( scene, camera );
asciifyImage( renderer, oAscii );
};
this.domElement = domElement;
// Throw in ascii library from http://www.nihilogic.dk/labs/jsascii/jsascii.js
/*
* jsAscii 0.1
* Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
* MIT License [http://www.nihilogic.dk/licenses/mit-license.txt]
*/
function initAsciiSize() {
iWidth = Math.round( width * fResolution );
iHeight = Math.round( height * fResolution );
oCanvas.width = iWidth;
oCanvas.height = iHeight;
// oCanvas.style.display = "none";
// oCanvas.style.width = iWidth;
// oCanvas.style.height = iHeight;
oImg = renderer.domElement;
if ( oImg.style.backgroundColor ) {
oAscii.rows[ 0 ].cells[ 0 ].style.backgroundColor = oImg.style.backgroundColor;
oAscii.rows[ 0 ].cells[ 0 ].style.color = oImg.style.color;
}
oAscii.cellSpacing = 0;
oAscii.cellPadding = 0;
var oStyle = oAscii.style;
oStyle.display = "inline";
oStyle.width = Math.round( iWidth / fResolution * iScale ) + "px";
oStyle.height = Math.round( iHeight / fResolution * iScale ) + "px";
oStyle.whiteSpace = "pre";
oStyle.margin = "0px";
oStyle.padding = "0px";
oStyle.letterSpacing = fLetterSpacing + "px";
oStyle.fontFamily = strFont;
oStyle.fontSize = fFontSize + "px";
oStyle.lineHeight = fLineHeight + "px";
oStyle.textAlign = "left";
oStyle.textDecoration = "none";
}
var aDefaultCharList = ( " .,:;i1tfLCG08@" ).split( "" );
var aDefaultColorCharList = ( " CGO08@" ).split( "" );
var strFont = "courier new, monospace";
var oCanvasImg = renderer.domElement;
var oCanvas = document.createElement( "canvas" );
if ( ! oCanvas.getContext ) {
return;
}
var oCtx = oCanvas.getContext( "2d" );
if ( ! oCtx.getImageData ) {
return;
}
var aCharList = ( bColor ? aDefaultColorCharList : aDefaultCharList );
if ( charSet ) aCharList = charSet;
var fResolution = 0.5;
switch ( strResolution ) {
case "low" : fResolution = 0.25; break;
case "medium" : fResolution = 0.5; break;
case "high" : fResolution = 1; break;
}
if ( bResolution ) fResolution = bResolution;
// Setup dom
var fFontSize = ( 2 / fResolution ) * iScale;
var fLineHeight = ( 2 / fResolution ) * iScale;
// adjust letter-spacing for all combinations of scale and resolution to get it to fit the image width.
var fLetterSpacing = 0;
if ( strResolution == "low" ) {
switch ( iScale ) {
case 1 : fLetterSpacing = - 1; break;
case 2 :
case 3 : fLetterSpacing = - 2.1; break;
case 4 : fLetterSpacing = - 3.1; break;
case 5 : fLetterSpacing = - 4.15; break;
}
}
if ( strResolution == "medium" ) {
switch ( iScale ) {
case 1 : fLetterSpacing = 0; break;
case 2 : fLetterSpacing = - 1; break;
case 3 : fLetterSpacing = - 1.04; break;
case 4 :
case 5 : fLetterSpacing = - 2.1; break;
}
}
if ( strResolution == "high" ) {
switch ( iScale ) {
case 1 :
case 2 : fLetterSpacing = 0; break;
case 3 :
case 4 :
case 5 : fLetterSpacing = - 1; break;
}
}
// can't get a span or div to flow like an img element, but a table works?
// convert img element to ascii
function asciifyImage( canvasRenderer, oAscii ) {
oCtx.clearRect( 0, 0, iWidth, iHeight );
oCtx.drawImage( oCanvasImg, 0, 0, iWidth, iHeight );
var oImgData = oCtx.getImageData( 0, 0, iWidth, iHeight ).data;
// Coloring loop starts now
var strChars = "";
// console.time('rendering');
for ( var y = 0; y < iHeight; y += 2 ) {
for ( var x = 0; x < iWidth; x ++ ) {
var iOffset = ( y * iWidth + x ) * 4;
var iRed = oImgData[ iOffset ];
var iGreen = oImgData[ iOffset + 1 ];
var iBlue = oImgData[ iOffset + 2 ];
var iAlpha = oImgData[ iOffset + 3 ];
var iCharIdx;
var fBrightness;
fBrightness = ( 0.3 * iRed + 0.59 * iGreen + 0.11 * iBlue ) / 255;
// fBrightness = (0.3*iRed + 0.5*iGreen + 0.3*iBlue) / 255;
if ( iAlpha == 0 ) {
// should calculate alpha instead, but quick hack :)
//fBrightness *= (iAlpha / 255);
fBrightness = 1;
}
iCharIdx = Math.floor( ( 1 - fBrightness ) * ( aCharList.length - 1 ) );
if ( bInvert ) {
iCharIdx = aCharList.length - iCharIdx - 1;
}
// good for debugging
//fBrightness = Math.floor(fBrightness * 10);
//strThisChar = fBrightness;
var strThisChar = aCharList[ iCharIdx ];
if ( strThisChar === undefined || strThisChar == " " )
strThisChar = "&nbsp;";
if ( bColor ) {
strChars += "<span style='"
+ "color:rgb(" + iRed + "," + iGreen + "," + iBlue + ");"
+ ( bBlock ? "background-color:rgb(" + iRed + "," + iGreen + "," + iBlue + ");" : "" )
+ ( bAlpha ? "opacity:" + ( iAlpha / 255 ) + ";" : "" )
+ "'>" + strThisChar + "</span>";
} else {
strChars += strThisChar;
}
}
strChars += "<br/>";
}
oAscii.innerHTML = "<tr><td>" + strChars + "</td></tr>";
// console.timeEnd('rendering');
// return oAscii;
}
// end modified asciifyImage block
};

569
node_modules/three/examples/js/effects/OutlineEffect.js generated vendored Normal file
View File

@@ -0,0 +1,569 @@
/**
* @author takahirox / http://github.com/takahirox/
*
* Reference: https://en.wikipedia.org/wiki/Cel_shading
*
* // How to set default outline parameters
* new THREE.OutlineEffect( renderer, {
* defaultThickNess: 0.01,
* defaultColor: new THREE.Color( 0x888888 ),
* defaultAlpha: 0.8,
* defaultKeepAlive: true // keeps outline material in cache even if material is removed from scene
* } );
*
* // How to set outline parameters for each material
* material.outlineParameters = {
* thickNess: 0.01, // this paremeter won't work for MultiMaterial
* color: new THREE.Color( 0x888888 ), // this paremeter won't work for MultiMaterial
* alpha: 0.8, // this paremeter won't work for MultiMaterial
* visible: true,
* keepAlive: true // this paremeter won't work for Material in materials of MultiMaterial
* };
*
* TODO
* - support shader material without objectNormal in its vertexShader
*/
THREE.OutlineEffect = function ( renderer, parameters ) {
parameters = parameters || {};
this.enabled = true;
var defaultThickness = parameters.defaultThickness !== undefined ? parameters.defaultThickness : 0.003;
var defaultColor = parameters.defaultColor !== undefined ? parameters.defaultColor : new THREE.Color( 0x000000 );
var defaultAlpha = parameters.defaultAlpha !== undefined ? parameters.defaultAlpha : 1.0;
var defaultKeepAlive = parameters.defaultKeepAlive !== undefined ? parameters.defaultKeepAlive : false;
// object.material.uuid -> outlineMaterial
// (no mapping from children of MultiMaterial)
// save at the outline material creation and release
// if it's unused removeThresholdCount frames
// unless keepAlive is true.
var cache = {};
var removeThresholdCount = 60;
// outlineMaterial.uuid (or object.uuid for invisibleMaterial) -> originalMaterial
// including children of MultiMaterial.
// save before render and release after render.
var originalMaterials = {};
// object.uuid -> originalOnBeforeRender
// save before render and release after render.
var originalOnBeforeRenders = {};
//this.cache = cache; // for debug
var invisibleMaterial = new THREE.ShaderMaterial( { visible: false } );
// copied from WebGLPrograms and removed some materials
var shaderIDs = {
MeshBasicMaterial: 'basic',
MeshLambertMaterial: 'lambert',
MeshPhongMaterial: 'phong',
MeshToonMaterial: 'phong',
MeshStandardMaterial: 'physical',
MeshPhysicalMaterial: 'physical'
};
var uniformsChunk = {
outlineThickness: { type: "f", value: defaultThickness },
outlineColor: { type: "c", value: defaultColor },
outlineAlpha: { type: "f", value: defaultAlpha }
};
var vertexShaderChunk = [
"#include <fog_pars_vertex>",
"uniform float outlineThickness;",
"vec4 calculateOutline( vec4 pos, vec3 objectNormal, vec4 skinned ) {",
" float thickness = outlineThickness;",
" const float ratio = 1.0;", // TODO: support outline thickness ratio for each vertex
" vec4 pos2 = projectionMatrix * modelViewMatrix * vec4( skinned.xyz + objectNormal, 1.0 );",
// NOTE: subtract pos2 from pos because BackSide objectNormal is negative
" vec4 norm = normalize( pos - pos2 );",
" return pos + norm * thickness * pos.w * ratio;",
"}"
].join( "\n" );
var vertexShaderChunk2 = [
"#if ! defined( LAMBERT ) && ! defined( PHONG ) && ! defined( TOON ) && ! defined( PHYSICAL )",
" #ifndef USE_ENVMAP",
" vec3 objectNormal = normalize( normal );",
" #ifdef FLIP_SIDED",
" objectNormal = -objectNormal;",
" #endif",
" #endif",
"#endif",
"#ifdef DECLARE_TRANSFORMED",
" vec3 transformed = vec3( position );",
"#endif",
"#ifdef USE_SKINNING",
" gl_Position = calculateOutline( gl_Position, objectNormal, skinned );",
"#else",
" gl_Position = calculateOutline( gl_Position, objectNormal, vec4( transformed, 1.0 ) );",
"#endif",
"#include <fog_vertex>"
].join( "\n" );
var fragmentShader = [
"#include <common>",
"#include <fog_pars_fragment>",
"uniform vec3 outlineColor;",
"uniform float outlineAlpha;",
"void main() {",
" gl_FragColor = vec4( outlineColor, outlineAlpha );",
" #include <fog_fragment>",
"}"
].join( "\n" );
function createMaterial( originalMaterial ) {
var shaderID = shaderIDs[ originalMaterial.type ];
var originalUniforms, originalVertexShader;
var outlineParameters = originalMaterial.outlineParameters;
if ( shaderID !== undefined ) {
var shader = THREE.ShaderLib[ shaderID ];
originalUniforms = shader.uniforms;
originalVertexShader = shader.vertexShader;
} else if ( originalMaterial.isRawShaderMaterial === true ) {
originalUniforms = originalMaterial.uniforms;
originalVertexShader = originalMaterial.vertexShader;
if ( ! /attribute\s+vec3\s+position\s*;/.test( originalVertexShader ) ||
! /attribute\s+vec3\s+normal\s*;/.test( originalVertexShader ) ) {
console.warn( 'THREE.OutlineEffect requires both vec3 position and normal attributes in vertex shader, ' +
'does not draw outline for ' + originalMaterial.name + '(uuid:' + originalMaterial.uuid + ') material.' );
return invisibleMaterial;
}
} else if ( originalMaterial.isShaderMaterial === true ) {
originalUniforms = originalMaterial.uniforms;
originalVertexShader = originalMaterial.vertexShader;
} else {
return invisibleMaterial;
}
var uniforms = Object.assign( {}, originalUniforms, uniformsChunk );
var vertexShader = originalVertexShader
// put vertexShaderChunk right before "void main() {...}"
.replace( /void\s+main\s*\(\s*\)/, vertexShaderChunk + '\nvoid main()' )
// put vertexShaderChunk2 the end of "void main() {...}"
// Note: here assums originalVertexShader ends with "}" of "void main() {...}"
.replace( /\}\s*$/, vertexShaderChunk2 + '\n}' )
// remove any light related lines
// Note: here is very sensitive to originalVertexShader
// TODO: consider safer way
.replace( /#include\s+<[\w_]*light[\w_]*>/g, '' );
var defines = {};
if ( ! /vec3\s+transformed\s*=/.test( originalVertexShader ) &&
! /#include\s+<begin_vertex>/.test( originalVertexShader ) ) defines.DECLARE_TRANSFORMED = true;
var material = new THREE.ShaderMaterial( {
defines: defines,
uniforms: uniforms,
vertexShader: vertexShader,
fragmentShader: fragmentShader,
side: THREE.BackSide,
//wireframe: true,
skinning: false,
morphTargets: false,
morphNormals: false,
fog: false
} );
return material;
}
function createMultiMaterial( originalMaterial ) {
var materials = [];
for ( var i = 0, il = originalMaterial.materials.length; i < il; i ++ ) {
materials.push( createMaterial( originalMaterial.materials[ i ] ) );
}
return new THREE.MultiMaterial( materials );
}
function setOutlineMaterial( object ) {
if ( object.material === undefined ) return;
var data = cache[ object.material.uuid ];
if ( data === undefined ) {
data = {
material: object.material.isMultiMaterial === true ? createMultiMaterial( object.material ) : createMaterial( object.material ),
used: true,
keepAlive: defaultKeepAlive,
count: 0
};
cache[ object.material.uuid ] = data;
}
var outlineMaterial = data.material;
data.used = true;
var uuid = outlineMaterial !== invisibleMaterial ? outlineMaterial.uuid : object.uuid;
originalMaterials[ uuid ] = object.material;
if ( object.material.isMultiMaterial === true ) {
for ( var i = 0, il = object.material.materials.length; i < il; i ++ ) {
// originalMaterial of leaf material of MultiMaterial is used only for
// updating outlineMaterial. so need not to save for invisibleMaterial.
if ( outlineMaterial.materials[ i ] !== invisibleMaterial ) {
originalMaterials[ outlineMaterial.materials[ i ].uuid ] = object.material.materials[ i ];
}
}
updateOutlineMultiMaterial( outlineMaterial, object.material );
} else {
updateOutlineMaterial( outlineMaterial, object.material );
}
object.material = outlineMaterial;
originalOnBeforeRenders[ object.uuid ] = object.onBeforeRender;
object.onBeforeRender = onBeforeRender;
}
function restoreOriginalMaterial( object ) {
if ( object.material === undefined ) return;
var originalMaterial = originalMaterials[ object.material.uuid ];
if ( originalMaterial === undefined ) {
originalMaterial = originalMaterials[ object.uuid ];
if ( originalMaterial === undefined ) return;
}
object.material = originalMaterial;
object.onBeforeRender = originalOnBeforeRenders[ object.uuid ];
}
function onBeforeRender( renderer, scene, camera, geometry, material, group ) {
// check some things before updating just in case
if ( material === invisibleMaterial ) return;
if ( material.isMultiMaterial === true ) return;
var originalMaterial = originalMaterials[ material.uuid ];
if ( originalMaterial === undefined ) return;
updateUniforms( material, originalMaterial );
}
function updateUniforms( material, originalMaterial ) {
var outlineParameters = originalMaterial.outlineParameters;
material.uniforms.outlineAlpha.value = originalMaterial.opacity;
if ( outlineParameters !== undefined ) {
if ( outlineParameters.thickness !== undefined ) material.uniforms.outlineThickness.value = outlineParameters.thickness;
if ( outlineParameters.color !== undefined ) material.uniforms.outlineColor.value.copy( outlineParameters.color );
if ( outlineParameters.alpha !== undefined ) material.uniforms.outlineAlpha.value = outlineParameters.alpha;
}
}
function updateOutlineMaterial( material, originalMaterial ) {
if ( material === invisibleMaterial ) return;
var outlineParameters = originalMaterial.outlineParameters;
material.skinning = originalMaterial.skinning;
material.morphTargets = originalMaterial.morphTargets;
material.morphNormals = originalMaterial.morphNormals;
material.fog = originalMaterial.fog;
if ( outlineParameters !== undefined ) {
if ( originalMaterial.visible === false ) {
material.visible = false;
} else {
material.visible = ( outlineParameters.visible !== undefined ) ? outlineParameters.visible : true;
}
material.transparent = ( outlineParameters.alpha !== undefined && outlineParameters.alpha < 1.0 ) ? true : originalMaterial.transparent;
// cache[ originalMaterial.uuid ] is undefined if originalMaterial is in materials of MultiMaterial
if ( outlineParameters.keepAlive !== undefined && cache[ originalMaterial.uuid ] !== undefined ) cache[ originalMaterial.uuid ].keepAlive = outlineParameters.keepAlive;
} else {
material.transparent = originalMaterial.transparent;
material.visible = originalMaterial.visible;
}
if ( originalMaterial.wireframe === true || originalMaterial.depthTest === false ) material.visible = false;
}
function updateOutlineMultiMaterial( material, originalMaterial ) {
if ( material === invisibleMaterial ) return;
var outlineParameters = originalMaterial.outlineParameters;
if ( outlineParameters !== undefined ) {
if ( originalMaterial.visible === false ) {
material.visible = false;
} else {
material.visible = ( outlineParameters.visible !== undefined ) ? outlineParameters.visible : true;
}
if ( outlineParameters.keepAlive !== undefined ) cache[ originalMaterial.uuid ].keepAlive = outlineParameters.keepAlive;
} else {
material.visible = originalMaterial.visible;
}
for ( var i = 0, il = material.materials.length; i < il; i ++ ) {
updateOutlineMaterial( material.materials[ i ], originalMaterial.materials[ i ] );
}
}
function cleanupCache() {
var keys;
// clear originialMaterials
keys = Object.keys( originalMaterials );
for ( var i = 0, il = keys.length; i < il; i ++ ) {
originalMaterials[ keys[ i ] ] = undefined;
}
// clear originalOnBeforeRenders
keys = Object.keys( originalOnBeforeRenders );
for ( var i = 0, il = keys.length; i < il; i ++ ) {
originalOnBeforeRenders[ keys[ i ] ] = undefined;
}
// remove unused outlineMaterial from cache
keys = Object.keys( cache );
for ( var i = 0, il = keys.length; i < il; i ++ ) {
var key = keys[ i ];
if ( cache[ key ].used === false ) {
cache[ key ].count++;
if ( cache[ key ].keepAlive === false && cache[ key ].count > removeThresholdCount ) {
delete cache[ key ];
}
} else {
cache[ key ].used = false;
cache[ key ].count = 0;
}
}
}
this.render = function ( scene, camera, renderTarget, forceClear ) {
if ( this.enabled === false ) {
renderer.render( scene, camera, renderTarget, forceClear );
return;
}
var currentAutoClear = renderer.autoClear;
renderer.autoClear = this.autoClear;
// 1. render normally
renderer.render( scene, camera, renderTarget, forceClear );
// 2. render outline
var currentSceneAutoUpdate = scene.autoUpdate;
var currentSceneBackground = scene.background;
var currentShadowMapEnabled = renderer.shadowMap.enabled;
scene.autoUpdate = false;
scene.background = null;
renderer.autoClear = false;
renderer.shadowMap.enabled = false;
scene.traverse( setOutlineMaterial );
renderer.render( scene, camera, renderTarget );
scene.traverse( restoreOriginalMaterial );
cleanupCache();
scene.autoUpdate = currentSceneAutoUpdate;
scene.background = currentSceneBackground;
renderer.autoClear = currentAutoClear;
renderer.shadowMap.enabled = currentShadowMapEnabled;
};
/*
* See #9918
*
* The following property copies and wrapper methods enable
* THREE.OutlineEffect to be called from other *Effect, like
*
* effect = new THREE.VREffect( new THREE.OutlineEffect( renderer ) );
*
* function render () {
*
* effect.render( scene, camera );
*
* }
*/
this.autoClear = renderer.autoClear;
this.domElement = renderer.domElement;
this.shadowMap = renderer.shadowMap;
this.clear = function ( color, depth, stencil ) {
renderer.clear( color, depth, stencil );
};
this.getPixelRatio = function () {
return renderer.getPixelRatio();
};
this.setPixelRatio = function ( value ) {
renderer.setPixelRatio( value );
};
this.getSize = function () {
return renderer.getSize();
};
this.setSize = function ( width, height, updateStyle ) {
renderer.setSize( width, height, updateStyle );
};
this.setViewport = function ( x, y, width, height ) {
renderer.setViewport( x, y, width, height );
};
this.setScissor = function ( x, y, width, height ) {
renderer.setScissor( x, y, width, height );
};
this.setScissorTest = function ( boolean ) {
renderer.setScissorTest( boolean );
};
this.setRenderTarget = function ( renderTarget ) {
renderer.setRenderTarget( renderTarget );
};
};

View File

@@ -0,0 +1,96 @@
/**
* @author mrdoob / http://mrdoob.com/
* @author marklundin / http://mark-lundin.com/
* @author alteredq / http://alteredqualia.com/
*/
THREE.ParallaxBarrierEffect = function ( renderer ) {
var _camera = new THREE.OrthographicCamera( - 1, 1, 1, - 1, 0, 1 );
var _scene = new THREE.Scene();
var _stereo = new THREE.StereoCamera();
var _params = { minFilter: THREE.LinearFilter, magFilter: THREE.NearestFilter, format: THREE.RGBAFormat };
var _renderTargetL = new THREE.WebGLRenderTarget( 512, 512, _params );
var _renderTargetR = new THREE.WebGLRenderTarget( 512, 512, _params );
var _material = new THREE.ShaderMaterial( {
uniforms: {
"mapLeft": { value: _renderTargetL.texture },
"mapRight": { value: _renderTargetR.texture }
},
vertexShader: [
"varying vec2 vUv;",
"void main() {",
" vUv = vec2( uv.x, uv.y );",
" gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",
"}"
].join( "\n" ),
fragmentShader: [
"uniform sampler2D mapLeft;",
"uniform sampler2D mapRight;",
"varying vec2 vUv;",
"void main() {",
" vec2 uv = vUv;",
" if ( ( mod( gl_FragCoord.y, 2.0 ) ) > 1.00 ) {",
" gl_FragColor = texture2D( mapLeft, uv );",
" } else {",
" gl_FragColor = texture2D( mapRight, uv );",
" }",
"}"
].join( "\n" )
} );
var mesh = new THREE.Mesh( new THREE.PlaneBufferGeometry( 2, 2 ), _material );
_scene.add( mesh );
this.setSize = function ( width, height ) {
renderer.setSize( width, height );
var pixelRatio = renderer.getPixelRatio();
_renderTargetL.setSize( width * pixelRatio, height * pixelRatio );
_renderTargetR.setSize( width * pixelRatio, height * pixelRatio );
};
this.render = function ( scene, camera ) {
scene.updateMatrixWorld();
if ( camera.parent === null ) camera.updateMatrixWorld();
_stereo.update( camera );
renderer.render( scene, _stereo.cameraL, _renderTargetL, true );
renderer.render( scene, _stereo.cameraR, _renderTargetR, true );
renderer.render( _scene, _camera );
};
};

View File

@@ -0,0 +1,143 @@
/**
* Created by tpowellmeto on 29/10/2015.
*
* peppers ghost effect based on http://www.instructables.com/id/Reflective-Prism/?ALLSTEPS
*/
THREE.PeppersGhostEffect = function ( renderer ) {
var scope = this;
scope.cameraDistance = 15;
scope.reflectFromAbove = false;
// Internals
var _halfWidth, _width, _height;
var _cameraF = new THREE.PerspectiveCamera(); //front
var _cameraB = new THREE.PerspectiveCamera(); //back
var _cameraL = new THREE.PerspectiveCamera(); //left
var _cameraR = new THREE.PerspectiveCamera(); //right
var _position = new THREE.Vector3();
var _quaternion = new THREE.Quaternion();
var _scale = new THREE.Vector3();
// Initialization
renderer.autoClear = false;
this.setSize = function ( width, height ) {
_halfWidth = width / 2;
if ( width < height ) {
_width = width / 3;
_height = width / 3;
} else {
_width = height / 3;
_height = height / 3;
}
renderer.setSize( width, height );
};
this.render = function ( scene, camera ) {
scene.updateMatrixWorld();
if ( camera.parent === null ) camera.updateMatrixWorld();
camera.matrixWorld.decompose( _position, _quaternion, _scale );
// front
_cameraF.position.copy( _position );
_cameraF.quaternion.copy( _quaternion );
_cameraF.translateZ( scope.cameraDistance );
_cameraF.lookAt( scene.position );
// back
_cameraB.position.copy( _position );
_cameraB.quaternion.copy( _quaternion );
_cameraB.translateZ( - ( scope.cameraDistance ) );
_cameraB.lookAt( scene.position );
_cameraB.rotation.z += 180 * ( Math.PI / 180 );
// left
_cameraL.position.copy( _position );
_cameraL.quaternion.copy( _quaternion );
_cameraL.translateX( - ( scope.cameraDistance ) );
_cameraL.lookAt( scene.position );
_cameraL.rotation.x += 90 * ( Math.PI / 180 );
// right
_cameraR.position.copy( _position );
_cameraR.quaternion.copy( _quaternion );
_cameraR.translateX( scope.cameraDistance );
_cameraR.lookAt( scene.position );
_cameraR.rotation.x += 90 * ( Math.PI / 180 );
renderer.clear();
renderer.setScissorTest( true );
renderer.setScissor( _halfWidth - ( _width / 2 ), ( _height * 2 ), _width, _height );
renderer.setViewport( _halfWidth - ( _width / 2 ), ( _height * 2 ), _width, _height );
if ( scope.reflectFromAbove ) {
renderer.render( scene, _cameraB );
} else {
renderer.render( scene, _cameraF );
}
renderer.setScissor( _halfWidth - ( _width / 2 ), 0, _width, _height );
renderer.setViewport( _halfWidth - ( _width / 2 ), 0, _width, _height );
if ( scope.reflectFromAbove ) {
renderer.render( scene, _cameraF );
} else {
renderer.render( scene, _cameraB );
}
renderer.setScissor( _halfWidth - ( _width / 2 ) - _width, _height, _width, _height );
renderer.setViewport( _halfWidth - ( _width / 2 ) - _width, _height, _width, _height );
if ( scope.reflectFromAbove ) {
renderer.render( scene, _cameraR );
} else {
renderer.render( scene, _cameraL );
}
renderer.setScissor( _halfWidth + ( _width / 2 ), _height, _width, _height );
renderer.setViewport( _halfWidth + ( _width / 2 ), _height, _width, _height );
if ( scope.reflectFromAbove ) {
renderer.render( scene, _cameraL );
} else {
renderer.render( scene, _cameraR );
}
renderer.setScissorTest( false );
};
};

50
node_modules/three/examples/js/effects/StereoEffect.js generated vendored Normal file
View File

@@ -0,0 +1,50 @@
/**
* @author alteredq / http://alteredqualia.com/
* @authod mrdoob / http://mrdoob.com/
* @authod arodic / http://aleksandarrodic.com/
* @authod fonserbc / http://fonserbc.github.io/
*/
THREE.StereoEffect = function ( renderer ) {
var _stereo = new THREE.StereoCamera();
_stereo.aspect = 0.5;
this.setEyeSeparation = function ( eyeSep ) {
_stereo.eyeSep = eyeSep;
};
this.setSize = function ( width, height ) {
renderer.setSize( width, height );
};
this.render = function ( scene, camera ) {
scene.updateMatrixWorld();
if ( camera.parent === null ) camera.updateMatrixWorld();
_stereo.update( camera );
var size = renderer.getSize();
if ( renderer.autoClear ) renderer.clear();
renderer.setScissorTest( true );
renderer.setScissor( 0, 0, size.width / 2, size.height );
renderer.setViewport( 0, 0, size.width / 2, size.height );
renderer.render( scene, _stereo.cameraL );
renderer.setScissor( size.width / 2, 0, size.width / 2, size.height );
renderer.setViewport( size.width / 2, 0, size.width / 2, size.height );
renderer.render( scene, _stereo.cameraR );
renderer.setScissorTest( false );
};
};

477
node_modules/three/examples/js/effects/VREffect.js generated vendored Normal file
View File

@@ -0,0 +1,477 @@
/**
* @author dmarcos / https://github.com/dmarcos
* @author mrdoob / http://mrdoob.com
*
* WebVR Spec: http://mozvr.github.io/webvr-spec/webvr.html
*
* Firefox: http://mozvr.com/downloads/
* Chromium: https://webvr.info/get-chrome
*
*/
THREE.VREffect = function( renderer, onError ) {
var vrDisplay, vrDisplays;
var eyeTranslationL = new THREE.Vector3();
var eyeTranslationR = new THREE.Vector3();
var renderRectL, renderRectR;
var frameData = null;
if ( 'VRFrameData' in window ) {
frameData = new window.VRFrameData();
}
function gotVRDisplays( displays ) {
vrDisplays = displays;
if ( displays.length > 0 ) {
vrDisplay = displays[ 0 ];
} else {
if ( onError ) onError( 'HMD not available' );
}
}
if ( navigator.getVRDisplays ) {
navigator.getVRDisplays().then( gotVRDisplays ).catch( function() {
console.warn( 'THREE.VREffect: Unable to get VR Displays' );
} );
}
//
this.isPresenting = false;
this.scale = 1;
var scope = this;
var rendererSize = renderer.getSize();
var rendererUpdateStyle = false;
var rendererPixelRatio = renderer.getPixelRatio();
this.getVRDisplay = function() {
return vrDisplay;
};
this.setVRDisplay = function( value ) {
vrDisplay = value;
};
this.getVRDisplays = function() {
console.warn( 'THREE.VREffect: getVRDisplays() is being deprecated.' );
return vrDisplays;
};
this.setSize = function( width, height, updateStyle ) {
rendererSize = { width: width, height: height };
rendererUpdateStyle = updateStyle;
if ( scope.isPresenting ) {
var eyeParamsL = vrDisplay.getEyeParameters( 'left' );
renderer.setPixelRatio( 1 );
renderer.setSize( eyeParamsL.renderWidth * 2, eyeParamsL.renderHeight, false );
} else {
renderer.setPixelRatio( rendererPixelRatio );
renderer.setSize( width, height, updateStyle );
}
};
// VR presentation
var canvas = renderer.domElement;
var defaultLeftBounds = [ 0.0, 0.0, 0.5, 1.0 ];
var defaultRightBounds = [ 0.5, 0.0, 0.5, 1.0 ];
function onVRDisplayPresentChange() {
var wasPresenting = scope.isPresenting;
scope.isPresenting = vrDisplay !== undefined && vrDisplay.isPresenting;
if ( scope.isPresenting ) {
var eyeParamsL = vrDisplay.getEyeParameters( 'left' );
var eyeWidth = eyeParamsL.renderWidth;
var eyeHeight = eyeParamsL.renderHeight;
if ( ! wasPresenting ) {
rendererPixelRatio = renderer.getPixelRatio();
rendererSize = renderer.getSize();
renderer.setPixelRatio( 1 );
renderer.setSize( eyeWidth * 2, eyeHeight, false );
}
} else if ( wasPresenting ) {
renderer.setPixelRatio( rendererPixelRatio );
renderer.setSize( rendererSize.width, rendererSize.height, rendererUpdateStyle );
}
}
window.addEventListener( 'vrdisplaypresentchange', onVRDisplayPresentChange, false );
this.setFullScreen = function( boolean ) {
return new Promise( function( resolve, reject ) {
if ( vrDisplay === undefined ) {
reject( new Error( 'No VR hardware found.' ) );
return;
}
if ( scope.isPresenting === boolean ) {
resolve();
return;
}
if ( boolean ) {
resolve( vrDisplay.requestPresent( [ { source: canvas } ] ) );
} else {
resolve( vrDisplay.exitPresent() );
}
} );
};
this.requestPresent = function() {
return this.setFullScreen( true );
};
this.exitPresent = function() {
return this.setFullScreen( false );
};
this.requestAnimationFrame = function( f ) {
if ( vrDisplay !== undefined ) {
return vrDisplay.requestAnimationFrame( f );
} else {
return window.requestAnimationFrame( f );
}
};
this.cancelAnimationFrame = function( h ) {
if ( vrDisplay !== undefined ) {
vrDisplay.cancelAnimationFrame( h );
} else {
window.cancelAnimationFrame( h );
}
};
this.submitFrame = function() {
if ( vrDisplay !== undefined && scope.isPresenting ) {
vrDisplay.submitFrame();
}
};
this.autoSubmitFrame = true;
// render
var cameraL = new THREE.PerspectiveCamera();
cameraL.layers.enable( 1 );
var cameraR = new THREE.PerspectiveCamera();
cameraR.layers.enable( 2 );
this.render = function( scene, camera, renderTarget, forceClear ) {
if ( vrDisplay && scope.isPresenting ) {
var autoUpdate = scene.autoUpdate;
if ( autoUpdate ) {
scene.updateMatrixWorld();
scene.autoUpdate = false;
}
var eyeParamsL = vrDisplay.getEyeParameters( 'left' );
var eyeParamsR = vrDisplay.getEyeParameters( 'right' );
eyeTranslationL.fromArray( eyeParamsL.offset );
eyeTranslationR.fromArray( eyeParamsR.offset );
if ( Array.isArray( scene ) ) {
console.warn( 'THREE.VREffect.render() no longer supports arrays. Use object.layers instead.' );
scene = scene[ 0 ];
}
// When rendering we don't care what the recommended size is, only what the actual size
// of the backbuffer is.
var size = renderer.getSize();
var layers = vrDisplay.getLayers();
var leftBounds;
var rightBounds;
if ( layers.length ) {
var layer = layers[ 0 ];
leftBounds = layer.leftBounds !== null && layer.leftBounds.length === 4 ? layer.leftBounds : defaultLeftBounds;
rightBounds = layer.rightBounds !== null && layer.rightBounds.length === 4 ? layer.rightBounds : defaultRightBounds;
} else {
leftBounds = defaultLeftBounds;
rightBounds = defaultRightBounds;
}
renderRectL = {
x: Math.round( size.width * leftBounds[ 0 ] ),
y: Math.round( size.height * leftBounds[ 1 ] ),
width: Math.round( size.width * leftBounds[ 2 ] ),
height: Math.round( size.height * leftBounds[ 3 ] )
};
renderRectR = {
x: Math.round( size.width * rightBounds[ 0 ] ),
y: Math.round( size.height * rightBounds[ 1 ] ),
width: Math.round( size.width * rightBounds[ 2 ] ),
height: Math.round( size.height * rightBounds[ 3 ] )
};
if ( renderTarget ) {
renderer.setRenderTarget( renderTarget );
renderTarget.scissorTest = true;
} else {
renderer.setRenderTarget( null );
renderer.setScissorTest( true );
}
if ( renderer.autoClear || forceClear ) renderer.clear();
if ( camera.parent === null ) camera.updateMatrixWorld();
camera.matrixWorld.decompose( cameraL.position, cameraL.quaternion, cameraL.scale );
camera.matrixWorld.decompose( cameraR.position, cameraR.quaternion, cameraR.scale );
var scale = this.scale;
cameraL.translateOnAxis( eyeTranslationL, scale );
cameraR.translateOnAxis( eyeTranslationR, scale );
if ( vrDisplay.getFrameData ) {
vrDisplay.depthNear = camera.near;
vrDisplay.depthFar = camera.far;
vrDisplay.getFrameData( frameData );
cameraL.projectionMatrix.elements = frameData.leftProjectionMatrix;
cameraR.projectionMatrix.elements = frameData.rightProjectionMatrix;
} else {
cameraL.projectionMatrix = fovToProjection( eyeParamsL.fieldOfView, true, camera.near, camera.far );
cameraR.projectionMatrix = fovToProjection( eyeParamsR.fieldOfView, true, camera.near, camera.far );
}
// render left eye
if ( renderTarget ) {
renderTarget.viewport.set( renderRectL.x, renderRectL.y, renderRectL.width, renderRectL.height );
renderTarget.scissor.set( renderRectL.x, renderRectL.y, renderRectL.width, renderRectL.height );
} else {
renderer.setViewport( renderRectL.x, renderRectL.y, renderRectL.width, renderRectL.height );
renderer.setScissor( renderRectL.x, renderRectL.y, renderRectL.width, renderRectL.height );
}
renderer.render( scene, cameraL, renderTarget, forceClear );
// render right eye
if ( renderTarget ) {
renderTarget.viewport.set( renderRectR.x, renderRectR.y, renderRectR.width, renderRectR.height );
renderTarget.scissor.set( renderRectR.x, renderRectR.y, renderRectR.width, renderRectR.height );
} else {
renderer.setViewport( renderRectR.x, renderRectR.y, renderRectR.width, renderRectR.height );
renderer.setScissor( renderRectR.x, renderRectR.y, renderRectR.width, renderRectR.height );
}
renderer.render( scene, cameraR, renderTarget, forceClear );
if ( renderTarget ) {
renderTarget.viewport.set( 0, 0, size.width, size.height );
renderTarget.scissor.set( 0, 0, size.width, size.height );
renderTarget.scissorTest = false;
renderer.setRenderTarget( null );
} else {
renderer.setViewport( 0, 0, size.width, size.height );
renderer.setScissorTest( false );
}
if ( autoUpdate ) {
scene.autoUpdate = true;
}
if ( scope.autoSubmitFrame ) {
scope.submitFrame();
}
return;
}
// Regular render mode if not HMD
renderer.render( scene, camera, renderTarget, forceClear );
};
this.dispose = function() {
window.removeEventListener( 'vrdisplaypresentchange', onVRDisplayPresentChange, false );
};
//
function fovToNDCScaleOffset( fov ) {
var pxscale = 2.0 / ( fov.leftTan + fov.rightTan );
var pxoffset = ( fov.leftTan - fov.rightTan ) * pxscale * 0.5;
var pyscale = 2.0 / ( fov.upTan + fov.downTan );
var pyoffset = ( fov.upTan - fov.downTan ) * pyscale * 0.5;
return { scale: [ pxscale, pyscale ], offset: [ pxoffset, pyoffset ] };
}
function fovPortToProjection( fov, rightHanded, zNear, zFar ) {
rightHanded = rightHanded === undefined ? true : rightHanded;
zNear = zNear === undefined ? 0.01 : zNear;
zFar = zFar === undefined ? 10000.0 : zFar;
var handednessScale = rightHanded ? - 1.0 : 1.0;
// start with an identity matrix
var mobj = new THREE.Matrix4();
var m = mobj.elements;
// and with scale/offset info for normalized device coords
var scaleAndOffset = fovToNDCScaleOffset( fov );
// X result, map clip edges to [-w,+w]
m[ 0 * 4 + 0 ] = scaleAndOffset.scale[ 0 ];
m[ 0 * 4 + 1 ] = 0.0;
m[ 0 * 4 + 2 ] = scaleAndOffset.offset[ 0 ] * handednessScale;
m[ 0 * 4 + 3 ] = 0.0;
// Y result, map clip edges to [-w,+w]
// Y offset is negated because this proj matrix transforms from world coords with Y=up,
// but the NDC scaling has Y=down (thanks D3D?)
m[ 1 * 4 + 0 ] = 0.0;
m[ 1 * 4 + 1 ] = scaleAndOffset.scale[ 1 ];
m[ 1 * 4 + 2 ] = - scaleAndOffset.offset[ 1 ] * handednessScale;
m[ 1 * 4 + 3 ] = 0.0;
// Z result (up to the app)
m[ 2 * 4 + 0 ] = 0.0;
m[ 2 * 4 + 1 ] = 0.0;
m[ 2 * 4 + 2 ] = zFar / ( zNear - zFar ) * - handednessScale;
m[ 2 * 4 + 3 ] = ( zFar * zNear ) / ( zNear - zFar );
// W result (= Z in)
m[ 3 * 4 + 0 ] = 0.0;
m[ 3 * 4 + 1 ] = 0.0;
m[ 3 * 4 + 2 ] = handednessScale;
m[ 3 * 4 + 3 ] = 0.0;
mobj.transpose();
return mobj;
}
function fovToProjection( fov, rightHanded, zNear, zFar ) {
var DEG2RAD = Math.PI / 180.0;
var fovPort = {
upTan: Math.tan( fov.upDegrees * DEG2RAD ),
downTan: Math.tan( fov.downDegrees * DEG2RAD ),
leftTan: Math.tan( fov.leftDegrees * DEG2RAD ),
rightTan: Math.tan( fov.rightDegrees * DEG2RAD )
};
return fovPortToProjection( fovPort, rightHanded, zNear, zFar );
}
};

211
node_modules/three/examples/js/exporters/MMDExporter.js generated vendored Normal file
View File

@@ -0,0 +1,211 @@
/**
* @author takahiro / http://github.com/takahirox
*
* Dependencies
* - mmd-parser https://github.com/takahirox/mmd-parser
*/
THREE.MMDExporter = function () {
// Unicode to Shift_JIS table
var u2sTable;
function unicodeToShiftjis( str ) {
if ( u2sTable === undefined ) {
var encoder = new MMDParser.CharsetEncoder();
var table = encoder.s2uTable;
u2sTable = {};
var keys = Object.keys( table );
for ( var i = 0, il = keys.length; i < il; i ++ ) {
var key = keys[ i ];
var value = table[ key ];
key = parseInt( key );
u2sTable[ value ] = key;
}
}
var array = [];
for ( var i = 0, il = str.length; i < il; i ++ ) {
var code = str.charCodeAt( i )
var value = u2sTable[ code ];
if ( value === undefined ) {
throw 'cannot convert charcode 0x' + code.toString( 16 );
} else if ( value > 0xff ) {
array.push( ( value >> 8 ) & 0xff );
array.push( value & 0xff );
} else {
array.push( value & 0xff );
}
}
return new Uint8Array( array );
}
function getBindBones( skin ) {
// any more efficient ways?
var poseSkin = skin.clone();
poseSkin.pose();
return poseSkin.skeleton.bones;
}
/* TODO: implement
// mesh -> pmd
this.parsePmd = function ( object ) {
};
*/
/* TODO: implement
// mesh -> pmx
this.parsePmx = function ( object ) {
};
*/
/*
* skeleton -> vpd
* Returns Shift_JIS encoded Uint8Array. Otherwise return strings.
*/
this.parseVpd = function ( skin, outputShiftJis, useOriginalBones ) {
if ( skin.isSkinnedMesh !== true ) {
console.warn( 'THREE.MMDExporter: parseVpd() requires SkinnedMesh instance.' );
return null;
}
function toStringsFromNumber( num ) {
if ( Math.abs( num ) < 1e-6 ) num = 0;
var a = num.toString();
if ( a.indexOf( '.' ) === -1 ) {
a += '.';
}
a += '000000';
var index = a.indexOf( '.' );
var d = a.slice( 0, index );
var p = a.slice( index + 1, index + 7 );
return d + '.' + p;
}
function toStringsFromArray( array ) {
var a = [];
for ( var i = 0, il = array.length; i < il; i ++ ) {
a.push( toStringsFromNumber( array[ i ] ) );
}
return a.join( ',' );
}
skin.updateMatrixWorld( true );
var bones = skin.skeleton.bones;
var bones2 = getBindBones( skin );
var position = new THREE.Vector3();
var quaternion = new THREE.Quaternion();
var quaternion2 = new THREE.Quaternion();
var matrix = new THREE.Matrix4();
var array = [];
array.push( 'Vocaloid Pose Data file' );
array.push( '' );
array.push( ( skin.name !== '' ? skin.name.replace( /\s/g, '_' ) : 'skin' ) + '.osm;' );
array.push( bones.length + ';' );
array.push( '' );
for ( var i = 0, il = bones.length; i < il; i ++ ) {
var bone = bones[ i ];
var bone2 = bones2[ i ];
/*
* use the bone matrix saved before solving IK.
* see CCDIKSolver for the detail.
*/
if ( useOriginalBones === true &&
bone.userData.ik !== undefined &&
bone.userData.ik.originalMatrix !== undefined ) {
matrix.fromArray( bone.userData.ik.originalMatrix );
} else {
matrix.copy( bone.matrix );
}
position.setFromMatrixPosition( matrix );
quaternion.setFromRotationMatrix( matrix );
var pArray = position.sub( bone2.position ).toArray();
var qArray = quaternion2.copy( bone2.quaternion ).conjugate().multiply( quaternion ).toArray();
// right to left
pArray[ 2 ] = -pArray[ 2 ];
qArray[ 0 ] = -qArray[ 0 ];
qArray[ 1 ] = -qArray[ 1 ];
array.push( 'Bone' + i + '{' + bone.name );
array.push( ' ' + toStringsFromArray( pArray ) + ';' );
array.push( ' ' + toStringsFromArray( qArray ) + ';' );
array.push( '}' );
array.push( '' );
}
array.push( '' );
var lines = array.join( '\n' );
return ( outputShiftJis === true ) ? unicodeToShiftjis( lines ) : lines;
};
/* TODO: implement
// animation + skeleton -> vmd
this.parseVmd = function ( object ) {
};
*/
};

256
node_modules/three/examples/js/exporters/OBJExporter.js generated vendored Normal file
View File

@@ -0,0 +1,256 @@
/**
* @author mrdoob / http://mrdoob.com/
*/
THREE.OBJExporter = function () {};
THREE.OBJExporter.prototype = {
constructor: THREE.OBJExporter,
parse: function ( object ) {
var output = '';
var indexVertex = 0;
var indexVertexUvs = 0;
var indexNormals = 0;
var vertex = new THREE.Vector3();
var normal = new THREE.Vector3();
var uv = new THREE.Vector2();
var i, j, l, m, face = [];
var parseMesh = function ( mesh ) {
var nbVertex = 0;
var nbNormals = 0;
var nbVertexUvs = 0;
var geometry = mesh.geometry;
var normalMatrixWorld = new THREE.Matrix3();
if ( geometry instanceof THREE.Geometry ) {
geometry = new THREE.BufferGeometry().setFromObject( mesh );
}
if ( geometry instanceof THREE.BufferGeometry ) {
// shortcuts
var vertices = geometry.getAttribute( 'position' );
var normals = geometry.getAttribute( 'normal' );
var uvs = geometry.getAttribute( 'uv' );
var indices = geometry.getIndex();
// name of the mesh object
output += 'o ' + mesh.name + '\n';
// vertices
if( vertices !== undefined ) {
for ( i = 0, l = vertices.count; i < l; i ++, nbVertex++ ) {
vertex.x = vertices.getX( i );
vertex.y = vertices.getY( i );
vertex.z = vertices.getZ( i );
// transfrom the vertex to world space
vertex.applyMatrix4( mesh.matrixWorld );
// transform the vertex to export format
output += 'v ' + vertex.x + ' ' + vertex.y + ' ' + vertex.z + '\n';
}
}
// uvs
if( uvs !== undefined ) {
for ( i = 0, l = uvs.count; i < l; i ++, nbVertexUvs++ ) {
uv.x = uvs.getX( i );
uv.y = uvs.getY( i );
// transform the uv to export format
output += 'vt ' + uv.x + ' ' + uv.y + '\n';
}
}
// normals
if( normals !== undefined ) {
normalMatrixWorld.getNormalMatrix( mesh.matrixWorld );
for ( i = 0, l = normals.count; i < l; i ++, nbNormals++ ) {
normal.x = normals.getX( i );
normal.y = normals.getY( i );
normal.z = normals.getZ( i );
// transfrom the normal to world space
normal.applyMatrix3( normalMatrixWorld );
// transform the normal to export format
output += 'vn ' + normal.x + ' ' + normal.y + ' ' + normal.z + '\n';
}
}
// faces
if( indices !== null ) {
for ( i = 0, l = indices.count; i < l; i += 3 ) {
for( m = 0; m < 3; m ++ ){
j = indices.getX( i + m ) + 1;
face[ m ] = ( indexVertex + j ) + '/' + ( uvs ? ( indexVertexUvs + j ) : '' ) + '/' + ( indexNormals + j );
}
// transform the face to export format
output += 'f ' + face.join( ' ' ) + "\n";
}
} else {
for ( i = 0, l = vertices.count; i < l; i += 3 ) {
for( m = 0; m < 3; m ++ ){
j = i + m + 1;
face[ m ] = ( indexVertex + j ) + '/' + ( uvs ? ( indexVertexUvs + j ) : '' ) + '/' + ( indexNormals + j );
}
// transform the face to export format
output += 'f ' + face.join( ' ' ) + "\n";
}
}
} else {
console.warn( 'THREE.OBJExporter.parseMesh(): geometry type unsupported', geometry );
}
// update index
indexVertex += nbVertex;
indexVertexUvs += nbVertexUvs;
indexNormals += nbNormals;
};
var parseLine = function( line ) {
var nbVertex = 0;
var geometry = line.geometry;
var type = line.type;
if ( geometry instanceof THREE.Geometry ) {
geometry = new THREE.BufferGeometry().setFromObject( line );
}
if ( geometry instanceof THREE.BufferGeometry ) {
// shortcuts
var vertices = geometry.getAttribute( 'position' );
var indices = geometry.getIndex();
// name of the line object
output += 'o ' + line.name + '\n';
if( vertices !== undefined ) {
for ( i = 0, l = vertices.count; i < l; i ++, nbVertex++ ) {
vertex.x = vertices.getX( i );
vertex.y = vertices.getY( i );
vertex.z = vertices.getZ( i );
// transfrom the vertex to world space
vertex.applyMatrix4( line.matrixWorld );
// transform the vertex to export format
output += 'v ' + vertex.x + ' ' + vertex.y + ' ' + vertex.z + '\n';
}
}
if ( type === 'Line' ) {
output += 'l ';
for ( j = 1, l = vertices.count; j <= l; j++ ) {
output += ( indexVertex + j ) + ' ';
}
output += '\n';
}
if ( type === 'LineSegments' ) {
for ( j = 1, k = j + 1, l = vertices.count; j < l; j += 2, k = j + 1 ) {
output += 'l ' + ( indexVertex + j ) + ' ' + ( indexVertex + k ) + '\n';
}
}
} else {
console.warn('THREE.OBJExporter.parseLine(): geometry type unsupported', geometry );
}
// update index
indexVertex += nbVertex;
};
object.traverse( function ( child ) {
if ( child instanceof THREE.Mesh ) {
parseMesh( child );
}
if ( child instanceof THREE.Line ) {
parseLine( child );
}
} );
return output;
}
};

View File

@@ -0,0 +1,94 @@
/**
* @author kovacsv / http://kovacsv.hu/
* @author mrdoob / http://mrdoob.com/
* @author mudcube / http://mudcu.be/
*/
THREE.STLBinaryExporter = function () {};
THREE.STLBinaryExporter.prototype = {
constructor: THREE.STLBinaryExporter,
parse: ( function () {
var vector = new THREE.Vector3();
var normalMatrixWorld = new THREE.Matrix3();
return function parse( scene ) {
// We collect objects first, as we may need to convert from BufferGeometry to Geometry
var objects = [];
var triangles = 0;
scene.traverse( function ( object ) {
if ( ! ( object instanceof THREE.Mesh ) ) return;
var geometry = object.geometry;
if ( geometry instanceof THREE.BufferGeometry ) {
geometry = new THREE.Geometry().fromBufferGeometry( geometry );
}
if ( ! ( geometry instanceof THREE.Geometry ) ) return;
triangles += geometry.faces.length;
objects.push( {
geometry: geometry,
matrix: object.matrixWorld
} );
} );
var offset = 80; // skip header
var bufferLength = triangles * 2 + triangles * 3 * 4 * 4 + 80 + 4;
var arrayBuffer = new ArrayBuffer( bufferLength );
var output = new DataView( arrayBuffer );
output.setUint32( offset, triangles, true ); offset += 4;
// Traversing our collected objects
objects.forEach( function ( object ) {
var vertices = object.geometry.vertices;
var faces = object.geometry.faces;
normalMatrixWorld.getNormalMatrix( object.matrix );
for ( var i = 0, l = faces.length; i < l; i ++ ) {
var face = faces[ i ];
vector.copy( face.normal ).applyMatrix3( normalMatrixWorld ).normalize();
output.setFloat32( offset, vector.x, true ); offset += 4; // normal
output.setFloat32( offset, vector.y, true ); offset += 4;
output.setFloat32( offset, vector.z, true ); offset += 4;
var indices = [ face.a, face.b, face.c ];
for ( var j = 0; j < 3; j ++ ) {
vector.copy( vertices[ indices[ j ] ] ).applyMatrix4( object.matrix );
output.setFloat32( offset, vector.x, true ); offset += 4; // vertices
output.setFloat32( offset, vector.y, true ); offset += 4;
output.setFloat32( offset, vector.z, true ); offset += 4;
}
output.setUint16( offset, 0, true ); offset += 2; // attribute byte count
}
} );
return output;
};
}() )
};

View File

@@ -0,0 +1,75 @@
/**
* @author kovacsv / http://kovacsv.hu/
* @author mrdoob / http://mrdoob.com/
*/
THREE.STLExporter = function () {};
THREE.STLExporter.prototype = {
constructor: THREE.STLExporter,
parse: ( function () {
var vector = new THREE.Vector3();
var normalMatrixWorld = new THREE.Matrix3();
return function parse( scene ) {
var output = '';
output += 'solid exported\n';
scene.traverse( function ( object ) {
if ( object instanceof THREE.Mesh ) {
var geometry = object.geometry;
var matrixWorld = object.matrixWorld;
if ( geometry instanceof THREE.Geometry ) {
var vertices = geometry.vertices;
var faces = geometry.faces;
normalMatrixWorld.getNormalMatrix( matrixWorld );
for ( var i = 0, l = faces.length; i < l; i ++ ) {
var face = faces[ i ];
vector.copy( face.normal ).applyMatrix3( normalMatrixWorld ).normalize();
output += '\tfacet normal ' + vector.x + ' ' + vector.y + ' ' + vector.z + '\n';
output += '\t\touter loop\n';
var indices = [ face.a, face.b, face.c ];
for ( var j = 0; j < 3; j ++ ) {
vector.copy( vertices[ indices[ j ] ] ).applyMatrix4( matrixWorld );
output += '\t\t\tvertex ' + vector.x + ' ' + vector.y + ' ' + vector.z + '\n';
}
output += '\t\tendloop\n';
output += '\tendfacet\n';
}
}
}
} );
output += 'endsolid exported\n';
return output;
};
}() )
};

View File

@@ -0,0 +1,55 @@
/**
* @author mrdoob / http://mrdoob.com/
*/
THREE.TypedGeometryExporter = function () {};
THREE.TypedGeometryExporter.prototype = {
constructor: THREE.TypedGeometryExporter,
parse: function ( geometry ) {
var output = {
metadata: {
version: 4.0,
type: 'TypedGeometry',
generator: 'TypedGeometryExporter'
}
};
var attributes = [ 'vertices', 'normals', 'uvs' ];
for ( var key in attributes ) {
var attribute = attributes[ key ];
var typedArray = geometry[ attribute ];
var array = [];
for ( var i = 0, l = typedArray.length; i < l; i ++ ) {
array[ i ] = typedArray[ i ];
}
output[ attribute ] = array;
}
var boundingSphere = geometry.boundingSphere;
if ( boundingSphere !== null ) {
output.boundingSphere = {
center: boundingSphere.center.toArray(),
radius: boundingSphere.radius
}
}
return output;
}
};

View File

@@ -0,0 +1,214 @@
/**
* @author qiao / https://github.com/qiao
* @fileoverview This is a convex hull generator using the incremental method.
* The complexity is O(n^2) where n is the number of vertices.
* O(nlogn) algorithms do exist, but they are much more complicated.
*
* Benchmark:
*
* Platform: CPU: P7350 @2.00GHz Engine: V8
*
* Num Vertices Time(ms)
*
* 10 1
* 20 3
* 30 19
* 40 48
* 50 107
*/
THREE.ConvexGeometry = function( vertices ) {
THREE.Geometry.call( this );
var faces = [ [ 0, 1, 2 ], [ 0, 2, 1 ] ];
for ( var i = 3; i < vertices.length; i ++ ) {
addPoint( i );
}
function addPoint( vertexId ) {
var vertex = vertices[ vertexId ].clone();
var mag = vertex.length();
vertex.x += mag * randomOffset();
vertex.y += mag * randomOffset();
vertex.z += mag * randomOffset();
var hole = [];
for ( var f = 0; f < faces.length; ) {
var face = faces[ f ];
// for each face, if the vertex can see it,
// then we try to add the face's edges into the hole.
if ( visible( face, vertex ) ) {
for ( var e = 0; e < 3; e ++ ) {
var edge = [ face[ e ], face[ ( e + 1 ) % 3 ] ];
var boundary = true;
// remove duplicated edges.
for ( var h = 0; h < hole.length; h ++ ) {
if ( equalEdge( hole[ h ], edge ) ) {
hole[ h ] = hole[ hole.length - 1 ];
hole.pop();
boundary = false;
break;
}
}
if ( boundary ) {
hole.push( edge );
}
}
// remove faces[ f ]
faces[ f ] = faces[ faces.length - 1 ];
faces.pop();
} else {
// not visible
f ++;
}
}
// construct the new faces formed by the edges of the hole and the vertex
for ( var h = 0; h < hole.length; h ++ ) {
faces.push( [
hole[ h ][ 0 ],
hole[ h ][ 1 ],
vertexId
] );
}
}
/**
* Whether the face is visible from the vertex
*/
function visible( face, vertex ) {
var va = vertices[ face[ 0 ] ];
var vb = vertices[ face[ 1 ] ];
var vc = vertices[ face[ 2 ] ];
var n = normal( va, vb, vc );
// distance from face to origin
var dist = n.dot( va );
return n.dot( vertex ) >= dist;
}
/**
* Face normal
*/
function normal( va, vb, vc ) {
var cb = new THREE.Vector3();
var ab = new THREE.Vector3();
cb.subVectors( vc, vb );
ab.subVectors( va, vb );
cb.cross( ab );
cb.normalize();
return cb;
}
/**
* Detect whether two edges are equal.
* Note that when constructing the convex hull, two same edges can only
* be of the negative direction.
*/
function equalEdge( ea, eb ) {
return ea[ 0 ] === eb[ 1 ] && ea[ 1 ] === eb[ 0 ];
}
/**
* Create a random offset between -1e-6 and 1e-6.
*/
function randomOffset() {
return ( Math.random() - 0.5 ) * 2 * 1e-6;
}
// Push vertices into `this.vertices`, skipping those inside the hull
var id = 0;
var newId = new Array( vertices.length ); // map from old vertex id to new id
for ( var i = 0; i < faces.length; i ++ ) {
var face = faces[ i ];
for ( var j = 0; j < 3; j ++ ) {
if ( newId[ face[ j ] ] === undefined ) {
newId[ face[ j ] ] = id ++;
this.vertices.push( vertices[ face[ j ] ] );
}
face[ j ] = newId[ face[ j ] ];
}
}
// Convert faces into instances of THREE.Face3
for ( var i = 0; i < faces.length; i ++ ) {
this.faces.push( new THREE.Face3(
faces[ i ][ 0 ],
faces[ i ][ 1 ],
faces[ i ][ 2 ]
) );
}
this.computeFaceNormals();
// Compute flat vertex normals
for ( var i = 0; i < this.faces.length; i ++ ) {
var face = this.faces[ i ];
var normal = face.normal;
face.vertexNormals[ 0 ] = normal.clone();
face.vertexNormals[ 1 ] = normal.clone();
face.vertexNormals[ 2 ] = normal.clone();
}
};
THREE.ConvexGeometry.prototype = Object.create( THREE.Geometry.prototype );
THREE.ConvexGeometry.prototype.constructor = THREE.ConvexGeometry;

View File

@@ -0,0 +1,289 @@
THREE.DecalVertex = function( v, n ) {
this.vertex = v;
this.normal = n;
};
THREE.DecalVertex.prototype.clone = function() {
return new THREE.DecalVertex( this.vertex.clone(), this.normal.clone() );
};
THREE.DecalGeometry = function( mesh, position, rotation, dimensions, check ) {
THREE.Geometry.call( this );
if ( check === undefined ) check = null;
check = check || new THREE.Vector3( 1, 1, 1 );
this.uvs = [];
this.cube = new THREE.Mesh( new THREE.BoxGeometry( dimensions.x, dimensions.y, dimensions.z ), new THREE.MeshBasicMaterial() );
this.cube.rotation.set( rotation.x, rotation.y, rotation.z );
this.cube.position.copy( position );
this.cube.scale.set( 1, 1, 1 );
this.cube.updateMatrix();
this.iCubeMatrix = ( new THREE.Matrix4() ).getInverse( this.cube.matrix );
this.faceIndices = [ 'a', 'b', 'c', 'd' ];
this.clipFace = function( inVertices, plane ) {
var size = .5 * Math.abs( ( dimensions.clone() ).dot( plane ) );
function clip( v0, v1, p ) {
var d0 = v0.vertex.dot( p ) - size,
d1 = v1.vertex.dot( p ) - size;
var s = d0 / ( d0 - d1 );
var v = new THREE.DecalVertex(
new THREE.Vector3(
v0.vertex.x + s * ( v1.vertex.x - v0.vertex.x ),
v0.vertex.y + s * ( v1.vertex.y - v0.vertex.y ),
v0.vertex.z + s * ( v1.vertex.z - v0.vertex.z )
),
new THREE.Vector3(
v0.normal.x + s * ( v1.normal.x - v0.normal.x ),
v0.normal.y + s * ( v1.normal.y - v0.normal.y ),
v0.normal.z + s * ( v1.normal.z - v0.normal.z )
)
);
// need to clip more values (texture coordinates)? do it this way:
//intersectpoint.value = a.value + s*(b.value-a.value);
return v;
}
if ( inVertices.length === 0 ) return [];
var outVertices = [];
for ( var j = 0; j < inVertices.length; j += 3 ) {
var v1Out, v2Out, v3Out, total = 0;
var d1 = inVertices[ j + 0 ].vertex.dot( plane ) - size,
d2 = inVertices[ j + 1 ].vertex.dot( plane ) - size,
d3 = inVertices[ j + 2 ].vertex.dot( plane ) - size;
v1Out = d1 > 0;
v2Out = d2 > 0;
v3Out = d3 > 0;
total = ( v1Out ? 1 : 0 ) + ( v2Out ? 1 : 0 ) + ( v3Out ? 1 : 0 );
switch ( total ) {
case 0: {
outVertices.push( inVertices[ j ] );
outVertices.push( inVertices[ j + 1 ] );
outVertices.push( inVertices[ j + 2 ] );
break;
}
case 1: {
var nV1, nV2, nV3, nV4;
if ( v1Out ) {
nV1 = inVertices[ j + 1 ];
nV2 = inVertices[ j + 2 ];
nV3 = clip( inVertices[ j ], nV1, plane );
nV4 = clip( inVertices[ j ], nV2, plane );
}
if ( v2Out ) {
nV1 = inVertices[ j ];
nV2 = inVertices[ j + 2 ];
nV3 = clip( inVertices[ j + 1 ], nV1, plane );
nV4 = clip( inVertices[ j + 1 ], nV2, plane );
outVertices.push( nV3 );
outVertices.push( nV2.clone() );
outVertices.push( nV1.clone() );
outVertices.push( nV2.clone() );
outVertices.push( nV3.clone() );
outVertices.push( nV4 );
break;
}
if ( v3Out ) {
nV1 = inVertices[ j ];
nV2 = inVertices[ j + 1 ];
nV3 = clip( inVertices[ j + 2 ], nV1, plane );
nV4 = clip( inVertices[ j + 2 ], nV2, plane );
}
outVertices.push( nV1.clone() );
outVertices.push( nV2.clone() );
outVertices.push( nV3 );
outVertices.push( nV4 );
outVertices.push( nV3.clone() );
outVertices.push( nV2.clone() );
break;
}
case 2: {
var nV1, nV2, nV3;
if ( ! v1Out ) {
nV1 = inVertices[ j ].clone();
nV2 = clip( nV1, inVertices[ j + 1 ], plane );
nV3 = clip( nV1, inVertices[ j + 2 ], plane );
outVertices.push( nV1 );
outVertices.push( nV2 );
outVertices.push( nV3 );
}
if ( ! v2Out ) {
nV1 = inVertices[ j + 1 ].clone();
nV2 = clip( nV1, inVertices[ j + 2 ], plane );
nV3 = clip( nV1, inVertices[ j ], plane );
outVertices.push( nV1 );
outVertices.push( nV2 );
outVertices.push( nV3 );
}
if ( ! v3Out ) {
nV1 = inVertices[ j + 2 ].clone();
nV2 = clip( nV1, inVertices[ j ], plane );
nV3 = clip( nV1, inVertices[ j + 1 ], plane );
outVertices.push( nV1 );
outVertices.push( nV2 );
outVertices.push( nV3 );
}
break;
}
case 3: {
break;
}
}
}
return outVertices;
};
this.pushVertex = function( vertices, id, n ) {
var v = mesh.geometry.vertices[ id ].clone();
v.applyMatrix4( mesh.matrix );
v.applyMatrix4( this.iCubeMatrix );
vertices.push( new THREE.DecalVertex( v, n.clone() ) );
};
this.computeDecal = function() {
var finalVertices = [];
for ( var i = 0; i < mesh.geometry.faces.length; i ++ ) {
var f = mesh.geometry.faces[ i ];
var vertices = [];
this.pushVertex( vertices, f[ this.faceIndices[ 0 ] ], f.vertexNormals[ 0 ] );
this.pushVertex( vertices, f[ this.faceIndices[ 1 ] ], f.vertexNormals[ 1 ] );
this.pushVertex( vertices, f[ this.faceIndices[ 2 ] ], f.vertexNormals[ 2 ] );
if ( check.x ) {
vertices = this.clipFace( vertices, new THREE.Vector3( 1, 0, 0 ) );
vertices = this.clipFace( vertices, new THREE.Vector3( - 1, 0, 0 ) );
}
if ( check.y ) {
vertices = this.clipFace( vertices, new THREE.Vector3( 0, 1, 0 ) );
vertices = this.clipFace( vertices, new THREE.Vector3( 0, - 1, 0 ) );
}
if ( check.z ) {
vertices = this.clipFace( vertices, new THREE.Vector3( 0, 0, 1 ) );
vertices = this.clipFace( vertices, new THREE.Vector3( 0, 0, - 1 ) );
}
for ( var j = 0; j < vertices.length; j ++ ) {
var v = vertices[ j ];
this.uvs.push( new THREE.Vector2(
.5 + ( v.vertex.x / dimensions.x ),
.5 + ( v.vertex.y / dimensions.y )
) );
vertices[ j ].vertex.applyMatrix4( this.cube.matrix );
}
if ( vertices.length === 0 ) continue;
finalVertices = finalVertices.concat( vertices );
}
for ( var k = 0; k < finalVertices.length; k += 3 ) {
this.vertices.push(
finalVertices[ k ].vertex,
finalVertices[ k + 1 ].vertex,
finalVertices[ k + 2 ].vertex
);
var f = new THREE.Face3(
k,
k + 1,
k + 2
);
f.vertexNormals.push( finalVertices[ k + 0 ].normal );
f.vertexNormals.push( finalVertices[ k + 1 ].normal );
f.vertexNormals.push( finalVertices[ k + 2 ].normal );
this.faces.push( f );
this.faceVertexUvs[ 0 ].push( [
this.uvs[ k ],
this.uvs[ k + 1 ],
this.uvs[ k + 2 ]
] );
}
this.verticesNeedUpdate = true;
this.elementsNeedUpdate = true;
this.morphTargetsNeedUpdate = true;
this.uvsNeedUpdate = true;
this.normalsNeedUpdate = true;
this.colorsNeedUpdate = true;
this.computeFaceNormals();
};
this.computeDecal();
};
THREE.DecalGeometry.prototype = Object.create( THREE.Geometry.prototype );
THREE.DecalGeometry.prototype.constructor = THREE.DecalGeometry;

View File

@@ -0,0 +1,753 @@
/**
* @author Eric Haines / http://erichaines.com/
*
* Tessellates the famous Utah teapot database by Martin Newell into triangles.
*
* THREE.TeapotBufferGeometry = function ( size, segments, bottom, lid, body, fitLid, blinn )
*
* defaults: size = 50, segments = 10, bottom = true, lid = true, body = true,
* fitLid = false, blinn = true
*
* size is a relative scale: I've scaled the teapot to fit vertically between -1 and 1.
* Think of it as a "radius".
* segments - number of line segments to subdivide each patch edge;
* 1 is possible but gives degenerates, so two is the real minimum.
* bottom - boolean, if true (default) then the bottom patches are added. Some consider
* adding the bottom heresy, so set this to "false" to adhere to the One True Way.
* lid - to remove the lid and look inside, set to true.
* body - to remove the body and leave the lid, set this and "bottom" to false.
* fitLid - the lid is a tad small in the original. This stretches it a bit so you can't
* see the teapot's insides through the gap.
* blinn - Jim Blinn scaled the original data vertically by dividing by about 1.3 to look
* nicer. If you want to see the original teapot, similar to the real-world model, set
* this to false. True by default.
* See http://en.wikipedia.org/wiki/File:Original_Utah_Teapot.jpg for the original
* real-world teapot (from http://en.wikipedia.org/wiki/Utah_teapot).
*
* Note that the bottom (the last four patches) is not flat - blame Frank Crow, not me.
*
* The teapot should normally be rendered as a double sided object, since for some
* patches both sides can be seen, e.g., the gap around the lid and inside the spout.
*
* Segments 'n' determines the number of triangles output.
* Total triangles = 32*2*n*n - 8*n [degenerates at the top and bottom cusps are deleted]
*
* size_factor # triangles
* 1 56
* 2 240
* 3 552
* 4 992
*
* 10 6320
* 20 25440
* 30 57360
*
* Code converted from my ancient SPD software, http://tog.acm.org/resources/SPD/
* Created for the Udacity course "Interactive Rendering", http://bit.ly/ericity
* Lesson: https://www.udacity.com/course/viewer#!/c-cs291/l-68866048/m-106482448
* YouTube video on teapot history: https://www.youtube.com/watch?v=DxMfblPzFNc
*
* See https://en.wikipedia.org/wiki/Utah_teapot for the history of the teapot
*
*/
/*global THREE */
THREE.TeapotBufferGeometry = function ( size, segments, bottom, lid, body, fitLid, blinn ) {
"use strict";
// 32 * 4 * 4 Bezier spline patches
var teapotPatches = [
/*rim*/
0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,
3,16,17,18,7,19,20,21,11,22,23,24,15,25,26,27,
18,28,29,30,21,31,32,33,24,34,35,36,27,37,38,39,
30,40,41,0,33,42,43,4,36,44,45,8,39,46,47,12,
/*body*/
12,13,14,15,48,49,50,51,52,53,54,55,56,57,58,59,
15,25,26,27,51,60,61,62,55,63,64,65,59,66,67,68,
27,37,38,39,62,69,70,71,65,72,73,74,68,75,76,77,
39,46,47,12,71,78,79,48,74,80,81,52,77,82,83,56,
56,57,58,59,84,85,86,87,88,89,90,91,92,93,94,95,
59,66,67,68,87,96,97,98,91,99,100,101,95,102,103,104,
68,75,76,77,98,105,106,107,101,108,109,110,104,111,112,113,
77,82,83,56,107,114,115,84,110,116,117,88,113,118,119,92,
/*handle*/
120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,
123,136,137,120,127,138,139,124,131,140,141,128,135,142,143,132,
132,133,134,135,144,145,146,147,148,149,150,151,68,152,153,154,
135,142,143,132,147,155,156,144,151,157,158,148,154,159,160,68,
/*spout*/
161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,
164,177,178,161,168,179,180,165,172,181,182,169,176,183,184,173,
173,174,175,176,185,186,187,188,189,190,191,192,193,194,195,196,
176,183,184,173,188,197,198,185,192,199,200,189,196,201,202,193,
/*lid*/
203,203,203,203,204,205,206,207,208,208,208,208,209,210,211,212,
203,203,203,203,207,213,214,215,208,208,208,208,212,216,217,218,
203,203,203,203,215,219,220,221,208,208,208,208,218,222,223,224,
203,203,203,203,221,225,226,204,208,208,208,208,224,227,228,209,
209,210,211,212,229,230,231,232,233,234,235,236,237,238,239,240,
212,216,217,218,232,241,242,243,236,244,245,246,240,247,248,249,
218,222,223,224,243,250,251,252,246,253,254,255,249,256,257,258,
224,227,228,209,252,259,260,229,255,261,262,233,258,263,264,237,
/*bottom*/
265,265,265,265,266,267,268,269,270,271,272,273,92,119,118,113,
265,265,265,265,269,274,275,276,273,277,278,279,113,112,111,104,
265,265,265,265,276,280,281,282,279,283,284,285,104,103,102,95,
265,265,265,265,282,286,287,266,285,288,289,270,95,94,93,92
] ;
var teapotVertices = [
1.4,0,2.4,
1.4,-0.784,2.4,
0.784,-1.4,2.4,
0,-1.4,2.4,
1.3375,0,2.53125,
1.3375,-0.749,2.53125,
0.749,-1.3375,2.53125,
0,-1.3375,2.53125,
1.4375,0,2.53125,
1.4375,-0.805,2.53125,
0.805,-1.4375,2.53125,
0,-1.4375,2.53125,
1.5,0,2.4,
1.5,-0.84,2.4,
0.84,-1.5,2.4,
0,-1.5,2.4,
-0.784,-1.4,2.4,
-1.4,-0.784,2.4,
-1.4,0,2.4,
-0.749,-1.3375,2.53125,
-1.3375,-0.749,2.53125,
-1.3375,0,2.53125,
-0.805,-1.4375,2.53125,
-1.4375,-0.805,2.53125,
-1.4375,0,2.53125,
-0.84,-1.5,2.4,
-1.5,-0.84,2.4,
-1.5,0,2.4,
-1.4,0.784,2.4,
-0.784,1.4,2.4,
0,1.4,2.4,
-1.3375,0.749,2.53125,
-0.749,1.3375,2.53125,
0,1.3375,2.53125,
-1.4375,0.805,2.53125,
-0.805,1.4375,2.53125,
0,1.4375,2.53125,
-1.5,0.84,2.4,
-0.84,1.5,2.4,
0,1.5,2.4,
0.784,1.4,2.4,
1.4,0.784,2.4,
0.749,1.3375,2.53125,
1.3375,0.749,2.53125,
0.805,1.4375,2.53125,
1.4375,0.805,2.53125,
0.84,1.5,2.4,
1.5,0.84,2.4,
1.75,0,1.875,
1.75,-0.98,1.875,
0.98,-1.75,1.875,
0,-1.75,1.875,
2,0,1.35,
2,-1.12,1.35,
1.12,-2,1.35,
0,-2,1.35,
2,0,0.9,
2,-1.12,0.9,
1.12,-2,0.9,
0,-2,0.9,
-0.98,-1.75,1.875,
-1.75,-0.98,1.875,
-1.75,0,1.875,
-1.12,-2,1.35,
-2,-1.12,1.35,
-2,0,1.35,
-1.12,-2,0.9,
-2,-1.12,0.9,
-2,0,0.9,
-1.75,0.98,1.875,
-0.98,1.75,1.875,
0,1.75,1.875,
-2,1.12,1.35,
-1.12,2,1.35,
0,2,1.35,
-2,1.12,0.9,
-1.12,2,0.9,
0,2,0.9,
0.98,1.75,1.875,
1.75,0.98,1.875,
1.12,2,1.35,
2,1.12,1.35,
1.12,2,0.9,
2,1.12,0.9,
2,0,0.45,
2,-1.12,0.45,
1.12,-2,0.45,
0,-2,0.45,
1.5,0,0.225,
1.5,-0.84,0.225,
0.84,-1.5,0.225,
0,-1.5,0.225,
1.5,0,0.15,
1.5,-0.84,0.15,
0.84,-1.5,0.15,
0,-1.5,0.15,
-1.12,-2,0.45,
-2,-1.12,0.45,
-2,0,0.45,
-0.84,-1.5,0.225,
-1.5,-0.84,0.225,
-1.5,0,0.225,
-0.84,-1.5,0.15,
-1.5,-0.84,0.15,
-1.5,0,0.15,
-2,1.12,0.45,
-1.12,2,0.45,
0,2,0.45,
-1.5,0.84,0.225,
-0.84,1.5,0.225,
0,1.5,0.225,
-1.5,0.84,0.15,
-0.84,1.5,0.15,
0,1.5,0.15,
1.12,2,0.45,
2,1.12,0.45,
0.84,1.5,0.225,
1.5,0.84,0.225,
0.84,1.5,0.15,
1.5,0.84,0.15,
-1.6,0,2.025,
-1.6,-0.3,2.025,
-1.5,-0.3,2.25,
-1.5,0,2.25,
-2.3,0,2.025,
-2.3,-0.3,2.025,
-2.5,-0.3,2.25,
-2.5,0,2.25,
-2.7,0,2.025,
-2.7,-0.3,2.025,
-3,-0.3,2.25,
-3,0,2.25,
-2.7,0,1.8,
-2.7,-0.3,1.8,
-3,-0.3,1.8,
-3,0,1.8,
-1.5,0.3,2.25,
-1.6,0.3,2.025,
-2.5,0.3,2.25,
-2.3,0.3,2.025,
-3,0.3,2.25,
-2.7,0.3,2.025,
-3,0.3,1.8,
-2.7,0.3,1.8,
-2.7,0,1.575,
-2.7,-0.3,1.575,
-3,-0.3,1.35,
-3,0,1.35,
-2.5,0,1.125,
-2.5,-0.3,1.125,
-2.65,-0.3,0.9375,
-2.65,0,0.9375,
-2,-0.3,0.9,
-1.9,-0.3,0.6,
-1.9,0,0.6,
-3,0.3,1.35,
-2.7,0.3,1.575,
-2.65,0.3,0.9375,
-2.5,0.3,1.125,
-1.9,0.3,0.6,
-2,0.3,0.9,
1.7,0,1.425,
1.7,-0.66,1.425,
1.7,-0.66,0.6,
1.7,0,0.6,
2.6,0,1.425,
2.6,-0.66,1.425,
3.1,-0.66,0.825,
3.1,0,0.825,
2.3,0,2.1,
2.3,-0.25,2.1,
2.4,-0.25,2.025,
2.4,0,2.025,
2.7,0,2.4,
2.7,-0.25,2.4,
3.3,-0.25,2.4,
3.3,0,2.4,
1.7,0.66,0.6,
1.7,0.66,1.425,
3.1,0.66,0.825,
2.6,0.66,1.425,
2.4,0.25,2.025,
2.3,0.25,2.1,
3.3,0.25,2.4,
2.7,0.25,2.4,
2.8,0,2.475,
2.8,-0.25,2.475,
3.525,-0.25,2.49375,
3.525,0,2.49375,
2.9,0,2.475,
2.9,-0.15,2.475,
3.45,-0.15,2.5125,
3.45,0,2.5125,
2.8,0,2.4,
2.8,-0.15,2.4,
3.2,-0.15,2.4,
3.2,0,2.4,
3.525,0.25,2.49375,
2.8,0.25,2.475,
3.45,0.15,2.5125,
2.9,0.15,2.475,
3.2,0.15,2.4,
2.8,0.15,2.4,
0,0,3.15,
0.8,0,3.15,
0.8,-0.45,3.15,
0.45,-0.8,3.15,
0,-0.8,3.15,
0,0,2.85,
0.2,0,2.7,
0.2,-0.112,2.7,
0.112,-0.2,2.7,
0,-0.2,2.7,
-0.45,-0.8,3.15,
-0.8,-0.45,3.15,
-0.8,0,3.15,
-0.112,-0.2,2.7,
-0.2,-0.112,2.7,
-0.2,0,2.7,
-0.8,0.45,3.15,
-0.45,0.8,3.15,
0,0.8,3.15,
-0.2,0.112,2.7,
-0.112,0.2,2.7,
0,0.2,2.7,
0.45,0.8,3.15,
0.8,0.45,3.15,
0.112,0.2,2.7,
0.2,0.112,2.7,
0.4,0,2.55,
0.4,-0.224,2.55,
0.224,-0.4,2.55,
0,-0.4,2.55,
1.3,0,2.55,
1.3,-0.728,2.55,
0.728,-1.3,2.55,
0,-1.3,2.55,
1.3,0,2.4,
1.3,-0.728,2.4,
0.728,-1.3,2.4,
0,-1.3,2.4,
-0.224,-0.4,2.55,
-0.4,-0.224,2.55,
-0.4,0,2.55,
-0.728,-1.3,2.55,
-1.3,-0.728,2.55,
-1.3,0,2.55,
-0.728,-1.3,2.4,
-1.3,-0.728,2.4,
-1.3,0,2.4,
-0.4,0.224,2.55,
-0.224,0.4,2.55,
0,0.4,2.55,
-1.3,0.728,2.55,
-0.728,1.3,2.55,
0,1.3,2.55,
-1.3,0.728,2.4,
-0.728,1.3,2.4,
0,1.3,2.4,
0.224,0.4,2.55,
0.4,0.224,2.55,
0.728,1.3,2.55,
1.3,0.728,2.55,
0.728,1.3,2.4,
1.3,0.728,2.4,
0,0,0,
1.425,0,0,
1.425,0.798,0,
0.798,1.425,0,
0,1.425,0,
1.5,0,0.075,
1.5,0.84,0.075,
0.84,1.5,0.075,
0,1.5,0.075,
-0.798,1.425,0,
-1.425,0.798,0,
-1.425,0,0,
-0.84,1.5,0.075,
-1.5,0.84,0.075,
-1.5,0,0.075,
-1.425,-0.798,0,
-0.798,-1.425,0,
0,-1.425,0,
-1.5,-0.84,0.075,
-0.84,-1.5,0.075,
0,-1.5,0.075,
0.798,-1.425,0,
1.425,-0.798,0,
0.84,-1.5,0.075,
1.5,-0.84,0.075
] ;
THREE.BufferGeometry.call( this );
this.type = 'TeapotBufferGeometry';
this.parameters = {
size: size,
segments: segments,
bottom: bottom,
lid: lid,
body: body,
fitLid: fitLid,
blinn: blinn
};
size = size || 50;
// number of segments per patch
segments = segments !== undefined ? Math.max( 2, Math.floor( segments ) || 10 ) : 10;
// which parts should be visible
bottom = bottom === undefined ? true : bottom;
lid = lid === undefined ? true : lid;
body = body === undefined ? true : body;
// Should the lid be snug? It's not traditional, but we make it snug by default
fitLid = fitLid === undefined ? true : fitLid;
// Jim Blinn scaled the teapot down in size by about 1.3 for
// some rendering tests. He liked the new proportions that he kept
// the data in this form. The model was distributed with these new
// proportions and became the norm. Trivia: comparing images of the
// real teapot and the computer model, the ratio for the bowl of the
// real teapot is more like 1.25, but since 1.3 is the traditional
// value given, we use it here.
var blinnScale = 1.3;
blinn = blinn === undefined ? true : blinn;
// scale the size to be the real scaling factor
var maxHeight = 3.15 * ( blinn ? 1 : blinnScale );
var maxHeight2 = maxHeight / 2;
var trueSize = size / maxHeight2;
// Number of elements depends on what is needed. Subtract degenerate
// triangles at tip of bottom and lid out in advance.
var numTriangles = bottom ? ( 8 * segments - 4 ) * segments : 0;
numTriangles += lid ? ( 16 * segments - 4 ) * segments : 0;
numTriangles += body ? 40 * segments * segments : 0;
var indices = new Uint32Array( numTriangles * 3 );
var numVertices = bottom ? 4 : 0;
numVertices += lid ? 8 : 0;
numVertices += body ? 20 : 0;
numVertices *= ( segments + 1 ) * ( segments + 1 );
var vertices = new Float32Array( numVertices * 3 );
var normals = new Float32Array( numVertices * 3 );
var uvs = new Float32Array( numVertices * 2 );
// Bezier form
var ms = new THREE.Matrix4();
ms.set( -1.0, 3.0, -3.0, 1.0,
3.0, -6.0, 3.0, 0.0,
-3.0, 3.0, 0.0, 0.0,
1.0, 0.0, 0.0, 0.0 ) ;
var g = [];
var i, r, c;
var sp = [];
var tp = [];
var dsp = [];
var dtp = [];
// M * G * M matrix, sort of see
// http://www.cs.helsinki.fi/group/goa/mallinnus/curves/surfaces.html
var mgm = [];
var vert = [];
var sdir = [];
var tdir = [];
var norm = new THREE.Vector3();
var tcoord;
var sstep, tstep;
var vertPerRow, eps;
var s, t, sval, tval, p;
var dsval = 0;
var dtval = 0;
var normOut = new THREE.Vector3();
var v1, v2, v3, v4;
var gmx = new THREE.Matrix4();
var tmtx = new THREE.Matrix4();
var vsp = new THREE.Vector4();
var vtp = new THREE.Vector4();
var vdsp = new THREE.Vector4();
var vdtp = new THREE.Vector4();
var vsdir = new THREE.Vector3();
var vtdir = new THREE.Vector3();
var mst = ms.clone();
mst.transpose();
// internal function: test if triangle has any matching vertices;
// if so, don't save triangle, since it won't display anything.
var notDegenerate = function ( vtx1, vtx2, vtx3 ) {
// if any vertex matches, return false
return ! ( ( ( vertices[ vtx1 * 3 ] === vertices[ vtx2 * 3 ] ) &&
( vertices[ vtx1 * 3 + 1 ] === vertices[ vtx2 * 3 + 1 ] ) &&
( vertices[ vtx1 * 3 + 2 ] === vertices[ vtx2 * 3 + 2 ] ) ) ||
( ( vertices[ vtx1 * 3 ] === vertices[ vtx3 * 3 ] ) &&
( vertices[ vtx1 * 3 + 1 ] === vertices[ vtx3 * 3 + 1 ] ) &&
( vertices[ vtx1 * 3 + 2 ] === vertices[ vtx3 * 3 + 2 ] ) ) ||
( ( vertices[ vtx2 * 3 ] === vertices[ vtx3 * 3 ] ) &&
( vertices[ vtx2 * 3 + 1 ] === vertices[ vtx3 * 3 + 1 ] ) &&
( vertices[ vtx2 * 3 + 2 ] === vertices[ vtx3 * 3 + 2 ] ) ) );
};
for ( i = 0; i < 3; i ++ )
{
mgm[ i ] = new THREE.Matrix4();
}
var minPatches = body ? 0 : 20;
var maxPatches = bottom ? 32 : 28;
vertPerRow = segments + 1;
eps = 0.0000001;
var surfCount = 0;
var vertCount = 0;
var normCount = 0;
var uvCount = 0;
var indexCount = 0;
for ( var surf = minPatches ; surf < maxPatches ; surf ++ ) {
// lid is in the middle of the data, patches 20-27,
// so ignore it for this part of the loop if the lid is not desired
if ( lid || ( surf < 20 || surf >= 28 ) ) {
// get M * G * M matrix for x,y,z
for ( i = 0 ; i < 3 ; i ++ ) {
// get control patches
for ( r = 0 ; r < 4 ; r ++ ) {
for ( c = 0 ; c < 4 ; c ++ ) {
// transposed
g[ c * 4 + r ] = teapotVertices[ teapotPatches[ surf * 16 + r * 4 + c ] * 3 + i ] ;
// is the lid to be made larger, and is this a point on the lid
// that is X or Y?
if ( fitLid && ( surf >= 20 && surf < 28 ) && ( i !== 2 ) ) {
// increase XY size by 7.7%, found empirically. I don't
// increase Z so that the teapot will continue to fit in the
// space -1 to 1 for Y (Y is up for the final model).
g[ c * 4 + r ] *= 1.077;
}
// Blinn "fixed" the teapot by dividing Z by blinnScale, and that's the
// data we now use. The original teapot is taller. Fix it:
if ( ! blinn && ( i === 2 ) ) {
g[ c * 4 + r ] *= blinnScale;
}
}
}
gmx.set( g[ 0 ], g[ 1 ], g[ 2 ], g[ 3 ], g[ 4 ], g[ 5 ], g[ 6 ], g[ 7 ], g[ 8 ], g[ 9 ], g[ 10 ], g[ 11 ], g[ 12 ], g[ 13 ], g[ 14 ], g[ 15 ] );
tmtx.multiplyMatrices( gmx, ms );
mgm[ i ].multiplyMatrices( mst, tmtx );
}
// step along, get points, and output
for ( sstep = 0 ; sstep <= segments ; sstep ++ ) {
s = sstep / segments;
for ( tstep = 0 ; tstep <= segments ; tstep ++ ) {
t = tstep / segments;
// point from basis
// get power vectors and their derivatives
for ( p = 4, sval = tval = 1.0 ; p -- ; ) {
sp[ p ] = sval ;
tp[ p ] = tval ;
sval *= s ;
tval *= t ;
if ( p === 3 ) {
dsp[ p ] = dtp[ p ] = 0.0 ;
dsval = dtval = 1.0 ;
} else {
dsp[ p ] = dsval * ( 3 - p ) ;
dtp[ p ] = dtval * ( 3 - p ) ;
dsval *= s ;
dtval *= t ;
}
}
vsp.fromArray( sp );
vtp.fromArray( tp );
vdsp.fromArray( dsp );
vdtp.fromArray( dtp );
// do for x,y,z
for ( i = 0 ; i < 3 ; i ++ ) {
// multiply power vectors times matrix to get value
tcoord = vsp.clone();
tcoord.applyMatrix4( mgm[ i ] );
vert[ i ] = tcoord.dot( vtp );
// get s and t tangent vectors
tcoord = vdsp.clone();
tcoord.applyMatrix4( mgm[ i ] );
sdir[ i ] = tcoord.dot( vtp ) ;
tcoord = vsp.clone();
tcoord.applyMatrix4( mgm[ i ] );
tdir[ i ] = tcoord.dot( vdtp ) ;
}
// find normal
vsdir.fromArray( sdir );
vtdir.fromArray( tdir );
norm.crossVectors( vtdir, vsdir );
norm.normalize();
// if X and Z length is 0, at the cusp, so point the normal up or down, depending on patch number
if ( vert[ 0 ] === 0 && vert[ 1 ] === 0 )
{
// if above the middle of the teapot, normal points up, else down
normOut.set( 0, vert[ 2 ] > maxHeight2 ? 1 : - 1, 0 );
}
else
{
// standard output: rotate on X axis
normOut.set( norm.x, norm.z, - norm.y );
}
// store it all
vertices[ vertCount ++ ] = trueSize * vert[ 0 ];
vertices[ vertCount ++ ] = trueSize * ( vert[ 2 ] - maxHeight2 );
vertices[ vertCount ++ ] = - trueSize * vert[ 1 ];
normals[ normCount ++ ] = normOut.x;
normals[ normCount ++ ] = normOut.y;
normals[ normCount ++ ] = normOut.z;
uvs[ uvCount ++ ] = 1 - t;
uvs[ uvCount ++ ] = 1 - s;
}
}
// save the faces
for ( sstep = 0 ; sstep < segments ; sstep ++ ) {
for ( tstep = 0 ; tstep < segments ; tstep ++ ) {
v1 = surfCount * vertPerRow * vertPerRow + sstep * vertPerRow + tstep;
v2 = v1 + 1;
v3 = v2 + vertPerRow;
v4 = v1 + vertPerRow;
// Normals and UVs cannot be shared. Without clone(), you can see the consequences
// of sharing if you call geometry.applyMatrix( matrix ).
if ( notDegenerate ( v1, v2, v3 ) ) {
indices[ indexCount ++ ] = v1;
indices[ indexCount ++ ] = v2;
indices[ indexCount ++ ] = v3;
}
if ( notDegenerate ( v1, v3, v4 ) ) {
indices[ indexCount ++ ] = v1;
indices[ indexCount ++ ] = v3;
indices[ indexCount ++ ] = v4;
}
}
}
// increment only if a surface was used
surfCount ++;
}
}
this.setIndex( new THREE.BufferAttribute( indices, 1 ) );
this.addAttribute( 'position', new THREE.BufferAttribute( vertices, 3 ) );
this.addAttribute( 'normal', new THREE.BufferAttribute( normals, 3 ) );
this.addAttribute( 'uv', new THREE.BufferAttribute( uvs, 2 ) );
this.computeBoundingSphere();
};
THREE.TeapotBufferGeometry.prototype = Object.create( THREE.BufferGeometry.prototype );
THREE.TeapotBufferGeometry.prototype.constructor = THREE.TeapotBufferGeometry;
THREE.TeapotBufferGeometry.prototype.clone = function () {
var bufferGeometry = new THREE.TeapotBufferGeometry(
this.parameters.size,
this.parameters.segments,
this.parameters.bottom,
this.parameters.lid,
this.parameters.body,
this.parameters.fitLid,
this.parameters.blinn
);
return bufferGeometry;
};

63
node_modules/three/examples/js/geometries/hilbert2D.js generated vendored Normal file
View File

@@ -0,0 +1,63 @@
/**
* Hilbert Curve: Generates 2D-Coordinates in a very fast way.
*
* @author Dylan Grafmyre
*
* Based on work by:
* @author Thomas Diewald
* @link http://www.openprocessing.org/sketch/15493
*
* @param center Center of Hilbert curve.
* @param size Total width of Hilbert curve.
* @param iterations Number of subdivisions.
* @param v0 Corner index -X, -Z.
* @param v1 Corner index -X, +Z.
* @param v2 Corner index +X, +Z.
* @param v3 Corner index +X, -Z.
*/
function hilbert2D ( center, size, iterations, v0, v1, v2, v3 ) {
// Default Vars
var center = undefined !== center ? center : new THREE.Vector3( 0, 0, 0 ),
size = undefined !== size ? size : 10,
half = size / 2,
iterations = undefined !== iterations ? iterations : 1,
v0 = undefined !== v0 ? v0 : 0,
v1 = undefined !== v1 ? v1 : 1,
v2 = undefined !== v2 ? v2 : 2,
v3 = undefined !== v3 ? v3 : 3
;
var vec_s = [
new THREE.Vector3( center.x - half, center.y, center.z - half ),
new THREE.Vector3( center.x - half, center.y, center.z + half ),
new THREE.Vector3( center.x + half, center.y, center.z + half ),
new THREE.Vector3( center.x + half, center.y, center.z - half )
];
var vec = [
vec_s[ v0 ],
vec_s[ v1 ],
vec_s[ v2 ],
vec_s[ v3 ]
];
// Recurse iterations
if ( 0 <= -- iterations ) {
var tmp = [];
Array.prototype.push.apply( tmp, hilbert2D ( vec[ 0 ], half, iterations, v0, v3, v2, v1 ) );
Array.prototype.push.apply( tmp, hilbert2D ( vec[ 1 ], half, iterations, v0, v1, v2, v3 ) );
Array.prototype.push.apply( tmp, hilbert2D ( vec[ 2 ], half, iterations, v0, v1, v2, v3 ) );
Array.prototype.push.apply( tmp, hilbert2D ( vec[ 3 ], half, iterations, v2, v1, v0, v3 ) );
// Return recursive call
return tmp;
}
// Return complete Hilbert Curve.
return vec;
}

88
node_modules/three/examples/js/geometries/hilbert3D.js generated vendored Normal file
View File

@@ -0,0 +1,88 @@
/**
* Hilbert Curve: Generates 2D-Coordinates in a very fast way.
*
* @author Dylan Grafmyre
*
* Based on work by:
* @author Thomas Diewald
* @link http://www.openprocessing.org/visuals/?visualID=15599
*
* Based on `examples/canvas_lines_colors.html`:
* @author OpenShift guest
* @link https://github.com/mrdoob/three.js/blob/8413a860aa95ed29c79cbb7f857c97d7880d260f/examples/canvas_lines_colors.html
* @see Line 149 - 186
*
* @param center Center of Hilbert curve.
* @param size Total width of Hilbert curve.
* @param iterations Number of subdivisions.
* @param v0 Corner index -X, +Y, -Z.
* @param v1 Corner index -X, +Y, +Z.
* @param v2 Corner index -X, -Y, +Z.
* @param v3 Corner index -X, -Y, -Z.
* @param v4 Corner index +X, -Y, -Z.
* @param v5 Corner index +X, -Y, +Z.
* @param v6 Corner index +X, +Y, +Z.
* @param v7 Corner index +X, +Y, -Z.
*/
function hilbert3D( center, size, iterations, v0, v1, v2, v3, v4, v5, v6, v7 ) {
// Default Vars
var center = undefined !== center ? center : new THREE.Vector3( 0, 0, 0 ),
size = undefined !== size ? size : 10,
half = size / 2,
iterations = undefined !== iterations ? iterations : 1,
v0 = undefined !== v0 ? v0 : 0,
v1 = undefined !== v1 ? v1 : 1,
v2 = undefined !== v2 ? v2 : 2,
v3 = undefined !== v3 ? v3 : 3,
v4 = undefined !== v4 ? v4 : 4,
v5 = undefined !== v5 ? v5 : 5,
v6 = undefined !== v6 ? v6 : 6,
v7 = undefined !== v7 ? v7 : 7
;
var vec_s = [
new THREE.Vector3( center.x - half, center.y + half, center.z - half ),
new THREE.Vector3( center.x - half, center.y + half, center.z + half ),
new THREE.Vector3( center.x - half, center.y - half, center.z + half ),
new THREE.Vector3( center.x - half, center.y - half, center.z - half ),
new THREE.Vector3( center.x + half, center.y - half, center.z - half ),
new THREE.Vector3( center.x + half, center.y - half, center.z + half ),
new THREE.Vector3( center.x + half, center.y + half, center.z + half ),
new THREE.Vector3( center.x + half, center.y + half, center.z - half )
];
var vec = [
vec_s[ v0 ],
vec_s[ v1 ],
vec_s[ v2 ],
vec_s[ v3 ],
vec_s[ v4 ],
vec_s[ v5 ],
vec_s[ v6 ],
vec_s[ v7 ]
];
// Recurse iterations
if ( -- iterations >= 0 ) {
var tmp = [];
Array.prototype.push.apply( tmp, hilbert3D ( vec[ 0 ], half, iterations, v0, v3, v4, v7, v6, v5, v2, v1 ) );
Array.prototype.push.apply( tmp, hilbert3D ( vec[ 1 ], half, iterations, v0, v7, v6, v1, v2, v5, v4, v3 ) );
Array.prototype.push.apply( tmp, hilbert3D ( vec[ 2 ], half, iterations, v0, v7, v6, v1, v2, v5, v4, v3 ) );
Array.prototype.push.apply( tmp, hilbert3D ( vec[ 3 ], half, iterations, v2, v3, v0, v1, v6, v7, v4, v5 ) );
Array.prototype.push.apply( tmp, hilbert3D ( vec[ 4 ], half, iterations, v2, v3, v0, v1, v6, v7, v4, v5 ) );
Array.prototype.push.apply( tmp, hilbert3D ( vec[ 5 ], half, iterations, v4, v3, v2, v5, v6, v1, v0, v7 ) );
Array.prototype.push.apply( tmp, hilbert3D ( vec[ 6 ], half, iterations, v4, v3, v2, v5, v6, v1, v0, v7 ) );
Array.prototype.push.apply( tmp, hilbert3D ( vec[ 7 ], half, iterations, v6, v5, v2, v1, v0, v3, v4, v7 ) );
// Return recursive call
return tmp;
}
// Return complete Hilbert Curve.
return vec;
}

31
node_modules/three/examples/js/libs/ammo.js generated vendored Normal file

File diff suppressed because one or more lines are too long

14
node_modules/three/examples/js/libs/dat.gui.min.js generated vendored Normal file

File diff suppressed because one or more lines are too long

674
node_modules/three/examples/js/libs/earcut.js generated vendored Normal file
View File

@@ -0,0 +1,674 @@
/**
*
* Earcut https://github.com/mapbox/earcut
*
* Copyright (c) 2015, Mapbox
*
* Permission to use, copy, modify, and/or distribute this software for any purpose
* with or without fee is hereby granted, provided that the above copyright notice
* and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
* THIS SOFTWARE.
*/
'use strict';
//module.exports = earcut;
function earcut(data, holeIndices, dim) {
dim = dim || 2;
var hasHoles = holeIndices && holeIndices.length,
outerLen = hasHoles ? holeIndices[0] * dim : data.length,
outerNode = filterPoints(data, linkedList(data, 0, outerLen, dim, true)),
triangles = [];
if (!outerNode) return triangles;
var minX, minY, maxX, maxY, x, y, size;
if (hasHoles) outerNode = eliminateHoles(data, holeIndices, outerNode, dim);
// if the shape is not too simple, we'll use z-order curve hash later; calculate polygon bbox
if (data.length > 80 * dim) {
minX = maxX = data[0];
minY = maxY = data[1];
for (var i = dim; i < outerLen; i += dim) {
x = data[i];
y = data[i + 1];
if (x < minX) minX = x;
if (y < minY) minY = y;
if (x > maxX) maxX = x;
if (y > maxY) maxY = y;
}
// minX, minY and size are later used to transform coords into integers for z-order calculation
size = Math.max(maxX - minX, maxY - minY);
}
earcutLinked(data, outerNode, triangles, dim, minX, minY, size);
return triangles;
}
// create a circular doubly linked list from polygon points in the specified winding order
function linkedList(data, start, end, dim, clockwise) {
var sum = 0,
i, j, last;
// calculate original winding order of a polygon ring
for (i = start, j = end - dim; i < end; i += dim) {
sum += (data[j] - data[i]) * (data[i + 1] + data[j + 1]);
j = i;
}
// link points into circular doubly-linked list in the specified winding order
if (clockwise === (sum > 0)) {
for (i = start; i < end; i += dim) last = insertNode(i, last);
} else {
for (i = end - dim; i >= start; i -= dim) last = insertNode(i, last);
}
return last;
}
// eliminate colinear or duplicate points
function filterPoints(data, start, end) {
if (!start) return start;
if (!end) end = start;
var node = start,
again;
do {
again = false;
if (!node.steiner && (equals(data, node.i, node.next.i) || orient(data, node.prev.i, node.i, node.next.i) === 0)) {
removeNode(node);
node = end = node.prev;
if (node === node.next) return null;
again = true;
} else {
node = node.next;
}
} while (again || node !== end);
return end;
}
// main ear slicing loop which triangulates a polygon (given as a linked list)
function earcutLinked(data, ear, triangles, dim, minX, minY, size, pass) {
if (!ear) return;
// interlink polygon nodes in z-order
if (!pass && minX !== undefined) indexCurve(data, ear, minX, minY, size);
var stop = ear,
prev, next;
// iterate through ears, slicing them one by one
while (ear.prev !== ear.next) {
prev = ear.prev;
next = ear.next;
if (isEar(data, ear, minX, minY, size)) {
// cut off the triangle
triangles.push(prev.i / dim);
triangles.push(ear.i / dim);
triangles.push(next.i / dim);
removeNode(ear);
// skipping the next vertice leads to less sliver triangles
ear = next.next;
stop = next.next;
continue;
}
ear = next;
// if we looped through the whole remaining polygon and can't find any more ears
if (ear === stop) {
// try filtering points and slicing again
if (!pass) {
earcutLinked(data, filterPoints(data, ear), triangles, dim, minX, minY, size, 1);
// if this didn't work, try curing all small self-intersections locally
} else if (pass === 1) {
ear = cureLocalIntersections(data, ear, triangles, dim);
earcutLinked(data, ear, triangles, dim, minX, minY, size, 2);
// as a last resort, try splitting the remaining polygon into two
} else if (pass === 2) {
splitEarcut(data, ear, triangles, dim, minX, minY, size);
}
break;
}
}
}
// check whether a polygon node forms a valid ear with adjacent nodes
function isEar(data, ear, minX, minY, size) {
var a = ear.prev.i,
b = ear.i,
c = ear.next.i,
ax = data[a], ay = data[a + 1],
bx = data[b], by = data[b + 1],
cx = data[c], cy = data[c + 1],
abd = ax * by - ay * bx,
acd = ax * cy - ay * cx,
cbd = cx * by - cy * bx,
A = abd - acd - cbd;
if (A <= 0) return false; // reflex, can't be an ear
// now make sure we don't have other points inside the potential ear;
// the code below is a bit verbose and repetitive but this is done for performance
var cay = cy - ay,
acx = ax - cx,
aby = ay - by,
bax = bx - ax,
i, px, py, s, t, k, node;
// if we use z-order curve hashing, iterate through the curve
if (minX !== undefined) {
// triangle bbox; min & max are calculated like this for speed
var minTX = ax < bx ? (ax < cx ? ax : cx) : (bx < cx ? bx : cx),
minTY = ay < by ? (ay < cy ? ay : cy) : (by < cy ? by : cy),
maxTX = ax > bx ? (ax > cx ? ax : cx) : (bx > cx ? bx : cx),
maxTY = ay > by ? (ay > cy ? ay : cy) : (by > cy ? by : cy),
// z-order range for the current triangle bbox;
minZ = zOrder(minTX, minTY, minX, minY, size),
maxZ = zOrder(maxTX, maxTY, minX, minY, size);
// first look for points inside the triangle in increasing z-order
node = ear.nextZ;
while (node && node.z <= maxZ) {
i = node.i;
node = node.nextZ;
if (i === a || i === c) continue;
px = data[i];
py = data[i + 1];
s = cay * px + acx * py - acd;
if (s >= 0) {
t = aby * px + bax * py + abd;
if (t >= 0) {
k = A - s - t;
if ((k >= 0) && ((s && t) || (s && k) || (t && k))) return false;
}
}
}
// then look for points in decreasing z-order
node = ear.prevZ;
while (node && node.z >= minZ) {
i = node.i;
node = node.prevZ;
if (i === a || i === c) continue;
px = data[i];
py = data[i + 1];
s = cay * px + acx * py - acd;
if (s >= 0) {
t = aby * px + bax * py + abd;
if (t >= 0) {
k = A - s - t;
if ((k >= 0) && ((s && t) || (s && k) || (t && k))) return false;
}
}
}
// if we don't use z-order curve hash, simply iterate through all other points
} else {
node = ear.next.next;
while (node !== ear.prev) {
i = node.i;
node = node.next;
px = data[i];
py = data[i + 1];
s = cay * px + acx * py - acd;
if (s >= 0) {
t = aby * px + bax * py + abd;
if (t >= 0) {
k = A - s - t;
if ((k >= 0) && ((s && t) || (s && k) || (t && k))) return false;
}
}
}
}
return true;
}
// go through all polygon nodes and cure small local self-intersections
function cureLocalIntersections(data, start, triangles, dim) {
var node = start;
do {
var a = node.prev,
b = node.next.next;
// a self-intersection where edge (v[i-1],v[i]) intersects (v[i+1],v[i+2])
if (a.i !== b.i && intersects(data, a.i, node.i, node.next.i, b.i) &&
locallyInside(data, a, b) && locallyInside(data, b, a) &&
orient(data, a.i, node.i, b.i) && orient(data, a.i, node.next.i, b.i)) {
triangles.push(a.i / dim);
triangles.push(node.i / dim);
triangles.push(b.i / dim);
// remove two nodes involved
removeNode(node);
removeNode(node.next);
node = start = b;
}
node = node.next;
} while (node !== start);
return node;
}
// try splitting polygon into two and triangulate them independently
function splitEarcut(data, start, triangles, dim, minX, minY, size) {
// look for a valid diagonal that divides the polygon into two
var a = start;
do {
var b = a.next.next;
while (b !== a.prev) {
if (a.i !== b.i && isValidDiagonal(data, a, b)) {
// split the polygon in two by the diagonal
var c = splitPolygon(a, b);
// filter colinear points around the cuts
a = filterPoints(data, a, a.next);
c = filterPoints(data, c, c.next);
// run earcut on each half
earcutLinked(data, a, triangles, dim, minX, minY, size);
earcutLinked(data, c, triangles, dim, minX, minY, size);
return;
}
b = b.next;
}
a = a.next;
} while (a !== start);
}
// link every hole into the outer loop, producing a single-ring polygon without holes
function eliminateHoles(data, holeIndices, outerNode, dim) {
var queue = [],
i, len, start, end, list;
for (i = 0, len = holeIndices.length; i < len; i++) {
start = holeIndices[i] * dim;
end = i < len - 1 ? holeIndices[i + 1] * dim : data.length;
list = linkedList(data, start, end, dim, false);
if (list === list.next) list.steiner = true;
list = filterPoints(data, list);
if (list) queue.push(getLeftmost(data, list));
}
queue.sort(function (a, b) {
return data[a.i] - data[b.i];
});
// process holes from left to right
for (i = 0; i < queue.length; i++) {
eliminateHole(data, queue[i], outerNode);
outerNode = filterPoints(data, outerNode, outerNode.next);
}
return outerNode;
}
// find a bridge between vertices that connects hole with an outer ring and and link it
function eliminateHole(data, holeNode, outerNode) {
outerNode = findHoleBridge(data, holeNode, outerNode);
if (outerNode) {
var b = splitPolygon(outerNode, holeNode);
filterPoints(data, b, b.next);
}
}
// David Eberly's algorithm for finding a bridge between hole and outer polygon
function findHoleBridge(data, holeNode, outerNode) {
var node = outerNode,
i = holeNode.i,
px = data[i],
py = data[i + 1],
qMax = -Infinity,
mNode, a, b;
// find a segment intersected by a ray from the hole's leftmost point to the left;
// segment's endpoint with lesser x will be potential connection point
do {
a = node.i;
b = node.next.i;
if (py <= data[a + 1] && py >= data[b + 1]) {
var qx = data[a] + (py - data[a + 1]) * (data[b] - data[a]) / (data[b + 1] - data[a + 1]);
if (qx <= px && qx > qMax) {
qMax = qx;
mNode = data[a] < data[b] ? node : node.next;
}
}
node = node.next;
} while (node !== outerNode);
if (!mNode) return null;
// look for points strictly inside the triangle of hole point, segment intersection and endpoint;
// if there are no points found, we have a valid connection;
// otherwise choose the point of the minimum angle with the ray as connection point
var bx = data[mNode.i],
by = data[mNode.i + 1],
pbd = px * by - py * bx,
pcd = px * py - py * qMax,
cpy = py - py,
pcx = px - qMax,
pby = py - by,
bpx = bx - px,
A = pbd - pcd - (qMax * by - py * bx),
sign = A <= 0 ? -1 : 1,
stop = mNode,
tanMin = Infinity,
mx, my, amx, s, t, tan;
node = mNode.next;
while (node !== stop) {
mx = data[node.i];
my = data[node.i + 1];
amx = px - mx;
if (amx >= 0 && mx >= bx) {
s = (cpy * mx + pcx * my - pcd) * sign;
if (s >= 0) {
t = (pby * mx + bpx * my + pbd) * sign;
if (t >= 0 && A * sign - s - t >= 0) {
tan = Math.abs(py - my) / amx; // tangential
if ((tan < tanMin || (tan === tanMin && mx > bx)) &&
locallyInside(data, node, holeNode)) {
mNode = node;
tanMin = tan;
}
}
}
}
node = node.next;
}
return mNode;
}
// interlink polygon nodes in z-order
function indexCurve(data, start, minX, minY, size) {
var node = start;
do {
if (node.z === null) node.z = zOrder(data[node.i], data[node.i + 1], minX, minY, size);
node.prevZ = node.prev;
node.nextZ = node.next;
node = node.next;
} while (node !== start);
node.prevZ.nextZ = null;
node.prevZ = null;
sortLinked(node);
}
// Simon Tatham's linked list merge sort algorithm
// http://www.chiark.greenend.org.uk/~sgtatham/algorithms/listsort.html
function sortLinked(list) {
var i, p, q, e, tail, numMerges, pSize, qSize,
inSize = 1;
do {
p = list;
list = null;
tail = null;
numMerges = 0;
while (p) {
numMerges++;
q = p;
pSize = 0;
for (i = 0; i < inSize; i++) {
pSize++;
q = q.nextZ;
if (!q) break;
}
qSize = inSize;
while (pSize > 0 || (qSize > 0 && q)) {
if (pSize === 0) {
e = q;
q = q.nextZ;
qSize--;
} else if (qSize === 0 || !q) {
e = p;
p = p.nextZ;
pSize--;
} else if (p.z <= q.z) {
e = p;
p = p.nextZ;
pSize--;
} else {
e = q;
q = q.nextZ;
qSize--;
}
if (tail) tail.nextZ = e;
else list = e;
e.prevZ = tail;
tail = e;
}
p = q;
}
tail.nextZ = null;
inSize *= 2;
} while (numMerges > 1);
return list;
}
// z-order of a point given coords and size of the data bounding box
function zOrder(x, y, minX, minY, size) {
// coords are transformed into non-negative 15-bit integer range
x = 32767 * (x - minX) / size;
y = 32767 * (y - minY) / size;
x = (x | (x << 8)) & 0x00FF00FF;
x = (x | (x << 4)) & 0x0F0F0F0F;
x = (x | (x << 2)) & 0x33333333;
x = (x | (x << 1)) & 0x55555555;
y = (y | (y << 8)) & 0x00FF00FF;
y = (y | (y << 4)) & 0x0F0F0F0F;
y = (y | (y << 2)) & 0x33333333;
y = (y | (y << 1)) & 0x55555555;
return x | (y << 1);
}
// find the leftmost node of a polygon ring
function getLeftmost(data, start) {
var node = start,
leftmost = start;
do {
if (data[node.i] < data[leftmost.i]) leftmost = node;
node = node.next;
} while (node !== start);
return leftmost;
}
// check if a diagonal between two polygon nodes is valid (lies in polygon interior)
function isValidDiagonal(data, a, b) {
return a.next.i !== b.i && a.prev.i !== b.i &&
!intersectsPolygon(data, a, a.i, b.i) &&
locallyInside(data, a, b) && locallyInside(data, b, a) &&
middleInside(data, a, a.i, b.i);
}
// winding order of triangle formed by 3 given points
function orient(data, p, q, r) {
var o = (data[q + 1] - data[p + 1]) * (data[r] - data[q]) - (data[q] - data[p]) * (data[r + 1] - data[q + 1]);
return o > 0 ? 1 :
o < 0 ? -1 : 0;
}
// check if two points are equal
function equals(data, p1, p2) {
return data[p1] === data[p2] && data[p1 + 1] === data[p2 + 1];
}
// check if two segments intersect
function intersects(data, p1, q1, p2, q2) {
return orient(data, p1, q1, p2) !== orient(data, p1, q1, q2) &&
orient(data, p2, q2, p1) !== orient(data, p2, q2, q1);
}
// check if a polygon diagonal intersects any polygon segments
function intersectsPolygon(data, start, a, b) {
var node = start;
do {
var p1 = node.i,
p2 = node.next.i;
if (p1 !== a && p2 !== a && p1 !== b && p2 !== b && intersects(data, p1, p2, a, b)) return true;
node = node.next;
} while (node !== start);
return false;
}
// check if a polygon diagonal is locally inside the polygon
function locallyInside(data, a, b) {
return orient(data, a.prev.i, a.i, a.next.i) === -1 ?
orient(data, a.i, b.i, a.next.i) !== -1 && orient(data, a.i, a.prev.i, b.i) !== -1 :
orient(data, a.i, b.i, a.prev.i) === -1 || orient(data, a.i, a.next.i, b.i) === -1;
}
// check if the middle point of a polygon diagonal is inside the polygon
function middleInside(data, start, a, b) {
var node = start,
inside = false,
px = (data[a] + data[b]) / 2,
py = (data[a + 1] + data[b + 1]) / 2;
do {
var p1 = node.i,
p2 = node.next.i;
if (((data[p1 + 1] > py) !== (data[p2 + 1] > py)) &&
(px < (data[p2] - data[p1]) * (py - data[p1 + 1]) / (data[p2 + 1] - data[p1 + 1]) + data[p1]))
inside = !inside;
node = node.next;
} while (node !== start);
return inside;
}
// link two polygon vertices with a bridge; if the vertices belong to the same ring, it splits polygon into two;
// if one belongs to the outer ring and another to a hole, it merges it into a single ring
function splitPolygon(a, b) {
var a2 = new Node(a.i),
b2 = new Node(b.i),
an = a.next,
bp = b.prev;
a.next = b;
b.prev = a;
a2.next = an;
an.prev = a2;
b2.next = a2;
a2.prev = b2;
bp.next = b2;
b2.prev = bp;
return b2;
}
// create a node and optionally link it with previous one (in a circular doubly linked list)
function insertNode(i, last) {
var node = new Node(i);
if (!last) {
node.prev = node;
node.next = node;
} else {
node.next = last.next;
node.prev = last;
last.next.prev = node;
last.next = node;
}
return node;
}
function removeNode(node) {
node.next.prev = node.prev;
node.prev.next = node.next;
if (node.prevZ) node.prevZ.nextZ = node.nextZ;
if (node.nextZ) node.nextZ.prevZ = node.prevZ;
}
function Node(i) {
// vertex coordinates
this.i = i;
// previous and next vertice nodes in a polygon ring
this.prev = null;
this.next = null;
// z-order curve value
this.z = null;
// previous and next nodes in z-order
this.prevZ = null;
this.nextZ = null;
// indicates whether this is a steiner point
this.steiner = false;
}

15
node_modules/three/examples/js/libs/inflate.min.js generated vendored Normal file
View File

@@ -0,0 +1,15 @@
/** @license zlib.js 2012 - imaya [ https://github.com/imaya/zlib.js ] The MIT License */(function() {'use strict';var m=this;function q(c,d){var a=c.split("."),b=m;!(a[0]in b)&&b.execScript&&b.execScript("var "+a[0]);for(var e;a.length&&(e=a.shift());)!a.length&&void 0!==d?b[e]=d:b=b[e]?b[e]:b[e]={}};var s="undefined"!==typeof Uint8Array&&"undefined"!==typeof Uint16Array&&"undefined"!==typeof Uint32Array&&"undefined"!==typeof DataView;function t(c){var d=c.length,a=0,b=Number.POSITIVE_INFINITY,e,f,g,h,k,l,p,n,r,K;for(n=0;n<d;++n)c[n]>a&&(a=c[n]),c[n]<b&&(b=c[n]);e=1<<a;f=new (s?Uint32Array:Array)(e);g=1;h=0;for(k=2;g<=a;){for(n=0;n<d;++n)if(c[n]===g){l=0;p=h;for(r=0;r<g;++r)l=l<<1|p&1,p>>=1;K=g<<16|n;for(r=l;r<e;r+=k)f[r]=K;++h}++g;h<<=1;k<<=1}return[f,a,b]};function u(c,d){this.g=[];this.h=32768;this.d=this.f=this.a=this.l=0;this.input=s?new Uint8Array(c):c;this.m=!1;this.i=v;this.s=!1;if(d||!(d={}))d.index&&(this.a=d.index),d.bufferSize&&(this.h=d.bufferSize),d.bufferType&&(this.i=d.bufferType),d.resize&&(this.s=d.resize);switch(this.i){case w:this.b=32768;this.c=new (s?Uint8Array:Array)(32768+this.h+258);break;case v:this.b=0;this.c=new (s?Uint8Array:Array)(this.h);this.e=this.A;this.n=this.w;this.j=this.z;break;default:throw Error("invalid inflate mode");
}}var w=0,v=1,x={u:w,t:v};
u.prototype.k=function(){for(;!this.m;){var c=y(this,3);c&1&&(this.m=!0);c>>>=1;switch(c){case 0:var d=this.input,a=this.a,b=this.c,e=this.b,f=d.length,g=void 0,h=void 0,k=b.length,l=void 0;this.d=this.f=0;if(a+1>=f)throw Error("invalid uncompressed block header: LEN");g=d[a++]|d[a++]<<8;if(a+1>=f)throw Error("invalid uncompressed block header: NLEN");h=d[a++]|d[a++]<<8;if(g===~h)throw Error("invalid uncompressed block header: length verify");if(a+g>d.length)throw Error("input buffer is broken");switch(this.i){case w:for(;e+
g>b.length;){l=k-e;g-=l;if(s)b.set(d.subarray(a,a+l),e),e+=l,a+=l;else for(;l--;)b[e++]=d[a++];this.b=e;b=this.e();e=this.b}break;case v:for(;e+g>b.length;)b=this.e({p:2});break;default:throw Error("invalid inflate mode");}if(s)b.set(d.subarray(a,a+g),e),e+=g,a+=g;else for(;g--;)b[e++]=d[a++];this.a=a;this.b=e;this.c=b;break;case 1:this.j(z,A);break;case 2:B(this);break;default:throw Error("unknown BTYPE: "+c);}}return this.n()};
var C=[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],D=s?new Uint16Array(C):C,E=[3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258,258,258],F=s?new Uint16Array(E):E,G=[0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0],H=s?new Uint8Array(G):G,I=[1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577],J=s?new Uint16Array(I):I,L=[0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,
13],M=s?new Uint8Array(L):L,N=new (s?Uint8Array:Array)(288),O,P;O=0;for(P=N.length;O<P;++O)N[O]=143>=O?8:255>=O?9:279>=O?7:8;var z=t(N),Q=new (s?Uint8Array:Array)(30),R,S;R=0;for(S=Q.length;R<S;++R)Q[R]=5;var A=t(Q);function y(c,d){for(var a=c.f,b=c.d,e=c.input,f=c.a,g=e.length,h;b<d;){if(f>=g)throw Error("input buffer is broken");a|=e[f++]<<b;b+=8}h=a&(1<<d)-1;c.f=a>>>d;c.d=b-d;c.a=f;return h}
function T(c,d){for(var a=c.f,b=c.d,e=c.input,f=c.a,g=e.length,h=d[0],k=d[1],l,p;b<k&&!(f>=g);)a|=e[f++]<<b,b+=8;l=h[a&(1<<k)-1];p=l>>>16;c.f=a>>p;c.d=b-p;c.a=f;return l&65535}
function B(c){function d(a,c,b){var d,e=this.q,f,g;for(g=0;g<a;)switch(d=T(this,c),d){case 16:for(f=3+y(this,2);f--;)b[g++]=e;break;case 17:for(f=3+y(this,3);f--;)b[g++]=0;e=0;break;case 18:for(f=11+y(this,7);f--;)b[g++]=0;e=0;break;default:e=b[g++]=d}this.q=e;return b}var a=y(c,5)+257,b=y(c,5)+1,e=y(c,4)+4,f=new (s?Uint8Array:Array)(D.length),g,h,k,l;for(l=0;l<e;++l)f[D[l]]=y(c,3);if(!s){l=e;for(e=f.length;l<e;++l)f[D[l]]=0}g=t(f);h=new (s?Uint8Array:Array)(a);k=new (s?Uint8Array:Array)(b);c.q=0;
c.j(t(d.call(c,a,g,h)),t(d.call(c,b,g,k)))}u.prototype.j=function(c,d){var a=this.c,b=this.b;this.o=c;for(var e=a.length-258,f,g,h,k;256!==(f=T(this,c));)if(256>f)b>=e&&(this.b=b,a=this.e(),b=this.b),a[b++]=f;else{g=f-257;k=F[g];0<H[g]&&(k+=y(this,H[g]));f=T(this,d);h=J[f];0<M[f]&&(h+=y(this,M[f]));b>=e&&(this.b=b,a=this.e(),b=this.b);for(;k--;)a[b]=a[b++-h]}for(;8<=this.d;)this.d-=8,this.a--;this.b=b};
u.prototype.z=function(c,d){var a=this.c,b=this.b;this.o=c;for(var e=a.length,f,g,h,k;256!==(f=T(this,c));)if(256>f)b>=e&&(a=this.e(),e=a.length),a[b++]=f;else{g=f-257;k=F[g];0<H[g]&&(k+=y(this,H[g]));f=T(this,d);h=J[f];0<M[f]&&(h+=y(this,M[f]));b+k>e&&(a=this.e(),e=a.length);for(;k--;)a[b]=a[b++-h]}for(;8<=this.d;)this.d-=8,this.a--;this.b=b};
u.prototype.e=function(){var c=new (s?Uint8Array:Array)(this.b-32768),d=this.b-32768,a,b,e=this.c;if(s)c.set(e.subarray(32768,c.length));else{a=0;for(b=c.length;a<b;++a)c[a]=e[a+32768]}this.g.push(c);this.l+=c.length;if(s)e.set(e.subarray(d,d+32768));else for(a=0;32768>a;++a)e[a]=e[d+a];this.b=32768;return e};
u.prototype.A=function(c){var d,a=this.input.length/this.a+1|0,b,e,f,g=this.input,h=this.c;c&&("number"===typeof c.p&&(a=c.p),"number"===typeof c.v&&(a+=c.v));2>a?(b=(g.length-this.a)/this.o[2],f=258*(b/2)|0,e=f<h.length?h.length+f:h.length<<1):e=h.length*a;s?(d=new Uint8Array(e),d.set(h)):d=h;return this.c=d};
u.prototype.n=function(){var c=0,d=this.c,a=this.g,b,e=new (s?Uint8Array:Array)(this.l+(this.b-32768)),f,g,h,k;if(0===a.length)return s?this.c.subarray(32768,this.b):this.c.slice(32768,this.b);f=0;for(g=a.length;f<g;++f){b=a[f];h=0;for(k=b.length;h<k;++h)e[c++]=b[h]}f=32768;for(g=this.b;f<g;++f)e[c++]=d[f];this.g=[];return this.buffer=e};
u.prototype.w=function(){var c,d=this.b;s?this.s?(c=new Uint8Array(d),c.set(this.c.subarray(0,d))):c=this.c.subarray(0,d):(this.c.length>d&&(this.c.length=d),c=this.c);return this.buffer=c};function U(c,d){var a,b;this.input=c;this.a=0;if(d||!(d={}))d.index&&(this.a=d.index),d.verify&&(this.B=d.verify);a=c[this.a++];b=c[this.a++];switch(a&15){case V:this.method=V;break;default:throw Error("unsupported compression method");}if(0!==((a<<8)+b)%31)throw Error("invalid fcheck flag:"+((a<<8)+b)%31);if(b&32)throw Error("fdict flag is not supported");this.r=new u(c,{index:this.a,bufferSize:d.bufferSize,bufferType:d.bufferType,resize:d.resize})}
U.prototype.k=function(){var c=this.input,d,a;d=this.r.k();this.a=this.r.a;if(this.B){a=(c[this.a++]<<24|c[this.a++]<<16|c[this.a++]<<8|c[this.a++])>>>0;var b=d;if("string"===typeof b){var e=b.split(""),f,g;f=0;for(g=e.length;f<g;f++)e[f]=(e[f].charCodeAt(0)&255)>>>0;b=e}for(var h=1,k=0,l=b.length,p,n=0;0<l;){p=1024<l?1024:l;l-=p;do h+=b[n++],k+=h;while(--p);h%=65521;k%=65521}if(a!==(k<<16|h)>>>0)throw Error("invalid adler-32 checksum");}return d};var V=8;q("Zlib.Inflate",U);q("Zlib.Inflate.prototype.decompress",U.prototype.k);var W={ADAPTIVE:x.t,BLOCK:x.u},X,Y,Z,$;if(Object.keys)X=Object.keys(W);else for(Y in X=[],Z=0,W)X[Z++]=Y;Z=0;for($=X.length;Z<$;++Z)Y=X[Z],q("Zlib.Inflate.BufferType."+Y,W[Y]);}).call(this);

14
node_modules/three/examples/js/libs/jszip.min.js generated vendored Normal file

File diff suppressed because one or more lines are too long

6
node_modules/three/examples/js/libs/mmdparser.min.js generated vendored Normal file

File diff suppressed because one or more lines are too long

600
node_modules/three/examples/js/libs/msgpack-js.js generated vendored Normal file
View File

@@ -0,0 +1,600 @@
( // Module boilerplate to support browser globals and browserify and AMD.
typeof define === "function" ? function (m) { define("msgpack-js", m); } :
typeof exports === "object" ? function (m) { module.exports = m(); } :
function(m){ this.msgpack = m(); }
)(function () {
"use strict";
var exports = {};
exports.inspect = inspect;
function inspect(buffer) {
if (buffer === undefined) return "undefined";
var view;
var type;
if (buffer instanceof ArrayBuffer) {
type = "ArrayBuffer";
view = new DataView(buffer);
}
else if (buffer instanceof DataView) {
type = "DataView";
view = buffer;
}
if (!view) return JSON.stringify(buffer);
var bytes = [];
for (var i = 0; i < buffer.byteLength; i++) {
if (i > 20) {
bytes.push("...");
break;
}
var byte = view.getUint8(i).toString(16);
if (byte.length === 1) byte = "0" + byte;
bytes.push(byte);
}
return "<" + type + " " + bytes.join(" ") + ">";
}
// Encode string as utf8 into dataview at offset
exports.utf8Write = utf8Write;
function utf8Write(view, offset, string) {
var byteLength = view.byteLength;
for(var i = 0, l = string.length; i < l; i++) {
var codePoint = string.charCodeAt(i);
// One byte of UTF-8
if (codePoint < 0x80) {
view.setUint8(offset++, codePoint >>> 0 & 0x7f | 0x00);
continue;
}
// Two bytes of UTF-8
if (codePoint < 0x800) {
view.setUint8(offset++, codePoint >>> 6 & 0x1f | 0xc0);
view.setUint8(offset++, codePoint >>> 0 & 0x3f | 0x80);
continue;
}
// Three bytes of UTF-8.
if (codePoint < 0x10000) {
view.setUint8(offset++, codePoint >>> 12 & 0x0f | 0xe0);
view.setUint8(offset++, codePoint >>> 6 & 0x3f | 0x80);
view.setUint8(offset++, codePoint >>> 0 & 0x3f | 0x80);
continue;
}
// Four bytes of UTF-8
if (codePoint < 0x110000) {
view.setUint8(offset++, codePoint >>> 18 & 0x07 | 0xf0);
view.setUint8(offset++, codePoint >>> 12 & 0x3f | 0x80);
view.setUint8(offset++, codePoint >>> 6 & 0x3f | 0x80);
view.setUint8(offset++, codePoint >>> 0 & 0x3f | 0x80);
continue;
}
throw new Error("bad codepoint " + codePoint);
}
}
exports.utf8Read = utf8Read;
function utf8Read(view, offset, length) {
var string = "";
for (var i = offset, end = offset + length; i < end; i++) {
var byte = view.getUint8(i);
// One byte character
if ((byte & 0x80) === 0x00) {
string += String.fromCharCode(byte);
continue;
}
// Two byte character
if ((byte & 0xe0) === 0xc0) {
string += String.fromCharCode(
((byte & 0x0f) << 6) |
(view.getUint8(++i) & 0x3f)
);
continue;
}
// Three byte character
if ((byte & 0xf0) === 0xe0) {
string += String.fromCharCode(
((byte & 0x0f) << 12) |
((view.getUint8(++i) & 0x3f) << 6) |
((view.getUint8(++i) & 0x3f) << 0)
);
continue;
}
// Four byte character
if ((byte & 0xf8) === 0xf0) {
string += String.fromCharCode(
((byte & 0x07) << 18) |
((view.getUint8(++i) & 0x3f) << 12) |
((view.getUint8(++i) & 0x3f) << 6) |
((view.getUint8(++i) & 0x3f) << 0)
);
continue;
}
throw new Error("Invalid byte " + byte.toString(16));
}
return string;
}
exports.utf8ByteCount = utf8ByteCount;
function utf8ByteCount(string) {
var count = 0;
for(var i = 0, l = string.length; i < l; i++) {
var codePoint = string.charCodeAt(i);
if (codePoint < 0x80) {
count += 1;
continue;
}
if (codePoint < 0x800) {
count += 2;
continue;
}
if (codePoint < 0x10000) {
count += 3;
continue;
}
if (codePoint < 0x110000) {
count += 4;
continue;
}
throw new Error("bad codepoint " + codePoint);
}
return count;
}
exports.encode = function (value) {
var buffer = new ArrayBuffer(sizeof(value));
var view = new DataView(buffer);
encode(value, view, 0);
return buffer;
};
exports.decode = decode;
// http://wiki.msgpack.org/display/MSGPACK/Format+specification
// I've extended the protocol to have two new types that were previously reserved.
// buffer 16 11011000 0xd8
// buffer 32 11011001 0xd9
// These work just like raw16 and raw32 except they are node buffers instead of strings.
//
// Also I've added a type for `undefined`
// undefined 11000100 0xc4
function Decoder(view, offset) {
this.offset = offset || 0;
this.view = view;
}
Decoder.prototype.map = function (length) {
var value = {};
for (var i = 0; i < length; i++) {
var key = this.parse();
value[key] = this.parse();
}
return value;
};
Decoder.prototype.buf = function (length) {
var value = new ArrayBuffer(length);
(new Uint8Array(value)).set(new Uint8Array(this.view.buffer, this.offset, length), 0);
this.offset += length;
return value;
};
Decoder.prototype.raw = function (length) {
var value = utf8Read(this.view, this.offset, length);
this.offset += length;
return value;
};
Decoder.prototype.array = function (length) {
var value = new Array(length);
for (var i = 0; i < length; i++) {
value[i] = this.parse();
}
return value;
};
Decoder.prototype.parse = function () {
var type = this.view.getUint8(this.offset);
var value, length;
// FixRaw
if ((type & 0xe0) === 0xa0) {
length = type & 0x1f;
this.offset++;
return this.raw(length);
}
// FixMap
if ((type & 0xf0) === 0x80) {
length = type & 0x0f;
this.offset++;
return this.map(length);
}
// FixArray
if ((type & 0xf0) === 0x90) {
length = type & 0x0f;
this.offset++;
return this.array(length);
}
// Positive FixNum
if ((type & 0x80) === 0x00) {
this.offset++;
return type;
}
// Negative Fixnum
if ((type & 0xe0) === 0xe0) {
value = this.view.getInt8(this.offset);
this.offset++;
return value;
}
switch (type) {
// raw 16
case 0xda:
length = this.view.getUint16(this.offset + 1);
this.offset += 3;
return this.raw(length);
// raw 32
case 0xdb:
length = this.view.getUint32(this.offset + 1);
this.offset += 5;
return this.raw(length);
// nil
case 0xc0:
this.offset++;
return null;
// false
case 0xc2:
this.offset++;
return false;
// true
case 0xc3:
this.offset++;
return true;
// undefined
case 0xc4:
this.offset++;
return undefined;
// uint8
case 0xcc:
value = this.view.getUint8(this.offset + 1);
this.offset += 2;
return value;
// uint 16
case 0xcd:
value = this.view.getUint16(this.offset + 1);
this.offset += 3;
return value;
// uint 32
case 0xce:
value = this.view.getUint32(this.offset + 1);
this.offset += 5;
return value;
// int 8
case 0xd0:
value = this.view.getInt8(this.offset + 1);
this.offset += 2;
return value;
// int 16
case 0xd1:
value = this.view.getInt16(this.offset + 1);
this.offset += 3;
return value;
// int 32
case 0xd2:
value = this.view.getInt32(this.offset + 1);
this.offset += 5;
return value;
// map 16
case 0xde:
length = this.view.getUint16(this.offset + 1);
this.offset += 3;
return this.map(length);
// map 32
case 0xdf:
length = this.view.getUint32(this.offset + 1);
this.offset += 5;
return this.map(length);
// array 16
case 0xdc:
length = this.view.getUint16(this.offset + 1);
this.offset += 3;
return this.array(length);
// array 32
case 0xdd:
length = this.view.getUint32(this.offset + 1);
this.offset += 5;
return this.array(length);
// buffer 16
case 0xd8:
length = this.view.getUint16(this.offset + 1);
this.offset += 3;
return this.buf(length);
// buffer 32
case 0xd9:
length = this.view.getUint32(this.offset + 1);
this.offset += 5;
return this.buf(length);
// float
case 0xca:
value = this.view.getFloat32(this.offset + 1);
this.offset += 5;
return value;
// double
case 0xcb:
value = this.view.getFloat64(this.offset + 1);
this.offset += 9;
return value;
}
throw new Error("Unknown type 0x" + type.toString(16));
};
function decode(buffer) {
var view = new DataView(buffer);
var decoder = new Decoder(view);
var value = decoder.parse();
if (decoder.offset !== buffer.byteLength) throw new Error((buffer.byteLength - decoder.offset) + " trailing bytes");
return value;
}
function encode(value, view, offset) {
var type = typeof value;
// Strings Bytes
if (type === "string") {
var length = utf8ByteCount(value);
// fix raw
if (length < 0x20) {
view.setUint8(offset, length | 0xa0);
utf8Write(view, offset + 1, value);
return 1 + length;
}
// raw 16
if (length < 0x10000) {
view.setUint8(offset, 0xda);
view.setUint16(offset + 1, length);
utf8Write(view, offset + 3, value);
return 3 + length;
}
// raw 32
if (length < 0x100000000) {
view.setUint8(offset, 0xdb);
view.setUint32(offset + 1, length);
utf8Write(view, offset + 5, value);
return 5 + length;
}
}
if (value instanceof ArrayBuffer) {
var length = value.byteLength;
// buffer 16
if (length < 0x10000) {
view.setUint8(offset, 0xd8);
view.setUint16(offset + 1, length);
(new Uint8Array(view.buffer)).set(new Uint8Array(value), offset + 3);
return 3 + length;
}
// buffer 32
if (length < 0x100000000) {
view.setUint8(offset, 0xd9);
view.setUint32(offset + 1, length);
(new Uint8Array(view.buffer)).set(new Uint8Array(value), offset + 5);
return 5 + length;
}
}
if (type === "number") {
// Floating Point
if ((value << 0) !== value) {
view.setUint8(offset, 0xcb);
view.setFloat64(offset + 1, value);
return 9;
}
// Integers
if (value >=0) {
// positive fixnum
if (value < 0x80) {
view.setUint8(offset, value);
return 1;
}
// uint 8
if (value < 0x100) {
view.setUint8(offset, 0xcc);
view.setUint8(offset + 1, value);
return 2;
}
// uint 16
if (value < 0x10000) {
view.setUint8(offset, 0xcd);
view.setUint16(offset + 1, value);
return 3;
}
// uint 32
if (value < 0x100000000) {
view.setUint8(offset, 0xce);
view.setUint32(offset + 1, value);
return 5;
}
throw new Error("Number too big 0x" + value.toString(16));
}
// negative fixnum
if (value >= -0x20) {
view.setInt8(offset, value);
return 1;
}
// int 8
if (value >= -0x80) {
view.setUint8(offset, 0xd0);
view.setInt8(offset + 1, value);
return 2;
}
// int 16
if (value >= -0x8000) {
view.setUint8(offset, 0xd1);
view.setInt16(offset + 1, value);
return 3;
}
// int 32
if (value >= -0x80000000) {
view.setUint8(offset, 0xd2);
view.setInt32(offset + 1, value);
return 5;
}
throw new Error("Number too small -0x" + (-value).toString(16).substr(1));
}
// undefined
if (type === "undefined") {
view.setUint8(offset, 0xc4);
return 1;
}
// null
if (value === null) {
view.setUint8(offset, 0xc0);
return 1;
}
// Boolean
if (type === "boolean") {
view.setUint8(offset, value ? 0xc3 : 0xc2);
return 1;
}
// Container Types
if (type === "object") {
var length, size = 0;
var isArray = Array.isArray(value);
if (isArray) {
length = value.length;
}
else {
var keys = Object.keys(value);
length = keys.length;
}
var size;
if (length < 0x10) {
view.setUint8(offset, length | (isArray ? 0x90 : 0x80));
size = 1;
}
else if (length < 0x10000) {
view.setUint8(offset, isArray ? 0xdc : 0xde);
view.setUint16(offset + 1, length);
size = 3;
}
else if (length < 0x100000000) {
view.setUint8(offset, isArray ? 0xdd : 0xdf);
view.setUint32(offset + 1, length);
size = 5;
}
if (isArray) {
for (var i = 0; i < length; i++) {
size += encode(value[i], view, offset + size);
}
}
else {
for (var i = 0; i < length; i++) {
var key = keys[i];
size += encode(key, view, offset + size);
size += encode(value[key], view, offset + size);
}
}
return size;
}
throw new Error("Unknown type " + type);
}
function sizeof(value) {
var type = typeof value;
// Raw Bytes
if (type === "string") {
var length = utf8ByteCount(value);
if (length < 0x20) {
return 1 + length;
}
if (length < 0x10000) {
return 3 + length;
}
if (length < 0x100000000) {
return 5 + length;
}
}
if (value instanceof ArrayBuffer) {
var length = value.byteLength;
if (length < 0x10000) {
return 3 + length;
}
if (length < 0x100000000) {
return 5 + length;
}
}
if (type === "number") {
// Floating Point
// double
if (value << 0 !== value) return 9;
// Integers
if (value >=0) {
// positive fixnum
if (value < 0x80) return 1;
// uint 8
if (value < 0x100) return 2;
// uint 16
if (value < 0x10000) return 3;
// uint 32
if (value < 0x100000000) return 5;
// uint 64
if (value < 0x10000000000000000) return 9;
throw new Error("Number too big 0x" + value.toString(16));
}
// negative fixnum
if (value >= -0x20) return 1;
// int 8
if (value >= -0x80) return 2;
// int 16
if (value >= -0x8000) return 3;
// int 32
if (value >= -0x80000000) return 5;
// int 64
if (value >= -0x8000000000000000) return 9;
throw new Error("Number too small -0x" + value.toString(16).substr(1));
}
// Boolean, null, undefined
if (type === "boolean" || type === "undefined" || value === null) return 1;
// Container Types
if (type === "object") {
var length, size = 0;
if (Array.isArray(value)) {
length = value.length;
for (var i = 0; i < length; i++) {
size += sizeof(value[i]);
}
}
else {
var keys = Object.keys(value);
length = keys.length;
for (var i = 0; i < length; i++) {
var key = keys[i];
size += sizeof(key) + sizeof(value[key]);
}
}
if (length < 0x10) {
return 1 + size;
}
if (length < 0x10000) {
return 3 + size;
}
if (length < 0x100000000) {
return 5 + size;
}
throw new Error("Array or object too long 0x" + length.toString(16));
}
throw new Error("Unknown type " + type);
}
return exports;
});

2913
node_modules/three/examples/js/libs/o3dgc.js generated vendored Normal file

File diff suppressed because it is too large Load Diff

118
node_modules/three/examples/js/libs/opentype.min.js generated vendored Normal file

File diff suppressed because one or more lines are too long

19
node_modules/three/examples/js/libs/pnltri.min.js generated vendored Normal file
View File

@@ -0,0 +1,19 @@
// pnltri.js / raw.github.com/jahting/pnltri.js/master/LICENSE
'use strict';var r={ca:"2.0"};r.c={random:Math.random,da:function(b){for(var c=b.length-1;0<c;c--){var l=Math.floor(r.c.random()*(c+1)),k=b[c];b[c]=b[l];b[l]=k}return b},G:function(b,c){var l=b.y-c.y;if(l<r.c.D)return-1;if(l>r.c.n)return 1;l=b.x-c.x;return l<r.c.D?-1:l>r.c.n?1:0},N:function(b,c,l){return(c.x-b.x)*(l.y-b.y)-(c.y-b.y)*(l.x-b.x)}};r.c.n=Math.pow(2,-43);r.c.D=-r.c.n;function u(b){this.U=[];this.r=[];this.X=[];this.L=0;this.F=[];this.R=[];this.T=[];if(b)for(var c=0,l=b.length;c<l;c++){var k=w(this,b[c]);if(3>k.length)console.log("Polygon has < 3 vertices!",k);else{for(var a=void 0,e=void 0,d=void 0,f=0;f<k.length-1;f++)a=x(this,k[f],k[f+1]),d?(a.o=d,d.m=a):e=a,d=a,this.r.push(a);a=x(this,k[k.length-1],k[0]);a.o=d;d.m=a;this.r.push(a);e.o=a;a.m=e;this.F[this.L++]=!0}}}u.prototype={Q:function(){return this.F.concat()}};
function B(b,c,l,k){b.T.push([c.id,l.id,k.id])}
function w(b,c){function l(a,b){return Math.abs(a.x-b.x)<r.c.n&&Math.abs(a.y-b.y)<r.c.n}function k(a,b,c){if(Math.abs(r.c.N(b,a,c))>r.c.n)return!1;var d;Math.abs(a.y-b.y)<r.c.n?(d=b.x,a.x<c.x?(b=a.x,a=c.x):(b=c.x,a=a.x)):(d=b.y,a.y<c.y?(b=a.y,a=c.y):(b=c.y,a=a.y));return b-d<r.c.n&&d-a<r.c.n}for(var a=[],e,d,f,h=0;h<c.length;h++)e=D(b,c[h].x,c[h].y),d=!0,f=a.length-1,0<=f&&(l(e,a[f])?d=!1:0<f&&k(a[f-1],a[f],e)&&a.pop()),d&&a.push(e);f=a.length-1;0<f&&l(a[f],a[0])&&(a.pop(),f--);1<f&&(k(a[f-1],a[f],
a[0])&&(a.pop(),f--),1<f&&k(a[f],a[0],a[1])&&a.shift());return a}function x(b,c,l){return{O:b.L,a:c,i:l,p:1==r.c.G(l,c),o:null,m:null,H:null,I:null,v:!1,J:null,K:null,j:null,g:null,w:!1}}function D(b,c,l){c={id:b.U.length,x:c,y:l};b.U.push(c);return c};function E(b){this.k=b}E.prototype={};function F(b,c,l,k){this.q=b?b:{x:Number.POSITIVE_INFINITY,y:Number.POSITIVE_INFINITY};this.l=c?c:{x:Number.NEGATIVE_INFINITY,y:Number.NEGATIVE_INFINITY};this.t=l;this.s=k;this.depth=-1}F.prototype={};function G(b){var c=new F(b.q,b.l,b.t,b.s);c.e=b.e;c.f=b.f;c.b=b.b;c.d=b.d;c.u=b.u;return c}function H(b){this.A=b;b.u=this}H.prototype={};function I(b){var c=new F(null,null,null,null);this.B=[];J(this,c);this.root=new H(c);if(b)for(b=b.r,c=0;c<b.length;c++)b[c].H=b[c].I=this.root,b[c].v=!1}
I.prototype={P:function(b){var c,l,k=b.U.length,a=Array(k);for(c=0;c<k;c++)a[c]=Array(8);var e=Array(k);c=0;for(l=this.B.length;c<l;c++){var d=this.B[c],f=d.e?d.f?5:7:d.f?4:6,h=d.b?d.d?1:0:d.d?3:2;if(1==d.depth%2){if(5==f||1==h||7==f&&3==h||4==f&&0==h){var g;g={a:d.l,i:d.q,j:null,g:null,w:!1};b.X.push(g);var p;p={a:d.q,i:d.l,aa:g,j:null,g:null,w:!1};b.X.push(p);g.aa=p;a[d.l.id][h]=g;a[d.q.id][f]=p}}else null!=d.q.id&&(e[d.q.id]=f),null!=d.l.id&&(e[d.l.id]=h)}var t;for(c=0;c<k;c++)if(d=a[c],f=e[c],
null!=f){l=f;h=null;do if(7<l++&&(l=0),b=d[l])h?(b.j=h,h.g=b):(t=b.a,t.Y=b),h=b.aa;while(l!=f);h&&(t.Z=h)}}};
function L(b,c){function l(){var a=m.e||m.f;a.b&&a.d?m==a.b?(n.e=null,a.b=q):(q.f=null,a.d=n):(n.e=null,n.f=a,a.d=n)}function k(a){m.l==t.l?(f?m.b?(a.e=q,q.b=a,n.d=null):(a.f=n,q.b=null,n.d=a):(a.e=q,a.f=n,q.b=n.d=a),q.d=n.b=null):(a.e&&a.f&&(a.e==m?(a.C=a.f,a.ba=!0):(a.C=a.e,a.ba=!1)),a.e=q,a.f=n,q.d=n.b=a,q.b=n.d=null)}function a(){var a;if(m.l==t.l&&f)m.b.e=q,m.d.f=n,q.b=m.b,n.d=m.d,a=q.d=n.b=null;else{m.b.e=q;m.d.f=n;var b=M(c,m.l);if(0<b)a=!0;else if(0>b)a=!1;else{a=m.b.s;var d=a.p,b=d?a.a:a.i,
b=M(c,b);0<b?a=!0:0>b?a=!1:(a=d?a.m:a.o,b=d?a.i:a.a,b=M(c,b),a=0<b?!0:!1)}a?(a=m.d,m.d.e=q,q.b=m.b,n.d=null):(a=m.b,m.b.f=n,n.d=m.d,q.b=null);q.d=n.b=a}return a}N(c);var e,d,f,h,g,p;c.p?(e=c.a,h=c.i,d=c.H,g=c.I,f=c.o.v,p=c.m.v):(e=c.i,h=c.a,d=c.I,g=c.H,f=c.m.v,p=c.o.v);p||(p=O(b,g,h,!1),g==d&&(d=p),g=p);g=g.A;if(g.e||g.f)if(g.q!=h)console.log("ERR add_segment: trFirstHigh != segHigh: ",g);else{f||(d=O(b,d,e,!0));var t=d.A,m=g,q,n,y,v;for(e=b.B.length+2;m;){if(0>--e){console.log("ERR add_segment: infinite loop",
m,c,b);return}if(!m.b&&!m.d){console.log("ERR add_segment: missing successors",m,c,b);return}d=m.u;d.h=c;d.A=null;v&&v.s==m.s?(q=m,n=v,n.l=m.l,d.left=new H(q),d.right=v.u):(y&&y.t==m.t?(n=m,q=y,q.l=m.l,d.left=y.u):(q=m,n=P(b,m),d.left=new H(q)),d.right=new H(n));m.e&&m.f?m.C?(m.ba?(n.e=m.f,n.f=m.C,n.e.b=n,n.f.d=n):(q.f=m.e,q.e=m.C,q.e.b=q,q.f.d=q),q.C=n.C=null):m.q==g.q?(n.f.d=n,q.f=n.e=null):n==m?(n.e=n.f,n.f=null,n.e.b=n):(q.f=q.e,q.e=null):l();m.b&&m.d?d=a():(d=m.b?m.b:m.d,k(d));q.s&&(q.s.J=n);
n.t&&(n.t.K=q);q.s=n.t=c;c.J=q;c.K=n;m.l!=t.l?(y=q,v=n,m=d):m=null}c.v=!0}else console.log("ERR add_segment: missing trFirst.uX: ",g)}
function Q(b,c){if(c)var l=b.a,k=b.i,a=b.H;else l=b.i,k=b.a,a=b.I;for(var e;a;)if(a.V)a=-1==r.c.G(l==a.V?k:l,a.V)?a.left:a.right;else if(a.h){if(l==a.h.a||l==a.h.i)if(Math.abs(l.y-k.y)<r.c.n){a=Math.abs(a.h.a.y-a.h.i.y)<r.c.n?l==a.h.a?((e=b.p?k.x>=a.h.i.x:k.x<a.h.i.x)?b.o.p:a.h.m.p)?a.right:a.left:((e=b.p?k.x<a.h.a.x:k.x>=a.h.a.x)?b.m.p:a.h.o.p)?a.left:a.right:k.x<l.x?a.left:a.right;continue}else e=M(a.h,k),0==e&&(e=l==a.h.a?(e=b.p?k.y>=a.h.i.y:k.y<a.h.i.y)?M(a.h,b.o.a):-M(a.h,a.h.m.i):(e=b.p?k.y<
a.h.a.y:k.y>=a.h.a.y)?M(a.h,b.m.i):-M(a.h,a.h.o.a));else e=M(a.h,l),0==e&&(e=M(a.h,k),0==e&&(e=M(a.h,c?b.o.a:b.m.i)));if(0<e)a=a.left;else if(0>e)a=a.right;else break}else{a.A||console.log("ptNode: unknown type",a);c?b.H=a:b.I=a;break}}function N(b){Q(b,!0);Q(b,!1)}function M(b,c){var l;l=b.a.x-c.x;var k=b.i.x-c.x,a=Math.abs(b.a.y-c.y)<r.c.n;if(Math.abs(b.i.y-c.y)<r.c.n){if(a)return 0;l=k}else if(!a)return b.p?r.c.N(b.a,b.i,c):r.c.N(b.i,b.a,c);return Math.abs(l)<r.c.n?0:l}
function O(b,c,l,k){var a=c.A;if(a.q==l||a.l==l)return c;var e=G(a);a.l=e.q=l;a.b=e;e.e=a;a.d=e.f=null;e.b&&(e.b.e=e);e.d&&(e.d.f=e);J(b,e);c.V=l;c.A=null;c.right=new H(a);c.left=new H(e);return k?a.u:e.u}function P(b,c){var l=G(c);J(b,l);return l}function J(b,c){c.fa=b.B.length;b.B.push(c)}function V(b){this.k=b;this.$=new I(this.k)}V.prototype={P:function(){return this.$.P(this.k)}};function W(b){this.k=b;this.S=null}W.prototype={};function X(b){this.k=b}X.prototype={};function Z(){this.M=null}
Z.prototype={W:function(){this.M=null},Q:function(){return this.M?this.M.Q():null},ea:function(b,c){this.W();if(!b||0==b.length)return[];var l=new u(b),k=c?!1:1==l.L;if(k){k=new E(l);a:{var a=k.k,e=a.r[0],d=e,f=e,h=0;do h+=(f.a.x-f.i.x)*(f.a.y+f.i.y),f=f.m;while(f!=e);if(0>h){do d.j=d.m,d=d.g=d.o;while(d!=e);a.F[0]=!1}else{do d.j=d.o,d=d.g=d.m;while(d!=e)}for(e=a=e;a.g!=a.j;){b:{var d=a.j.a.x,f=a.j.a.y,h=a.a.x,g=a.a.y,p=a.g.a.x,t=a.g.a.y,m=p-h,q=t-g,n=d-p,y=f-t,v=h-d,K=g-f;if(r.c.n>v*q-m*K)d=!1;else{for(var Y=
a.j.j,C=a.g;C!=Y;){var C=C.g,z=C.a.x,A=C.a.y,R=z-d,S=A-f;if(0!=R||0!=S){var T=z-h,U=A-g;if(0!=T||0!=U)if(z-=p,A-=t,(0!=z||0!=A)&&m*U-q*T>=r.c.D&&v*S-K*R>=r.c.D&&n*A-y*z>=r.c.D){d=!1;break b}}}d=!0}}if(d)B(k.k,a.j.a,a.a,a.g.a),a.j.g=a.g,a.g.j=a.j,e=a=a.g;else if(a=a.g,a==e){k=!1;break a}}k=!0}}if(!k){k=new W(l);k.S=new V(k.k);e=k.S;a=e.k.r.concat();r.c.da(a);d=0;f=e.k.L;if(1!=f)for(h=Array(f),g=a.concat(),p=0;p<g.length;p++)t=g[p].O,h[t]?a[f++]=g[p]:(a[d++]=g[p],h[t]=!0);d=a.length;f=e.$;h=0;for(g=
d;h<d;){g=Math.log(g)/Math.LN2;for(p=1<g?Math.floor(d/g):d;h<p;h++)L(f,a[h]);for(p=h;p<d;p++)N(a[p])}var e=e.k,f=[f.B[0]],h=[],s,p=0;do{for(t=1==p%2;g=f.pop();)-1==g.depth&&(g.depth=p,g.e&&f.push(g.e),g.f&&f.push(g.f),g.b&&f.push(g.b),g.d&&f.push(g.d),(s=g.t)&&-1==s.J.depth&&h.push(s.J),s=g.s)&&(-1==s.K.depth&&h.push(s.K),s.p!=t&&(e.F[s.O]=!1));f=h;h=[];p++}while(0<f.length);for(p=0;p<d;p++)a[p].J=a[p].K=null;k.S.P();s=k.k;d=0;for(f=s.r.length;d<f;d++){a=s.r[d];s.F[a.O]?(e=a.i,a.j=a.o,a.g=a.m):(e=
a.a,a=a.m,a.j=a.m,a.g=a.o);if(h=a.a.Z)h.g=a,a.j=h,a.a.Z=null;if(h=e.Y)h.j=a,a.g=h,e.Y=null}s=k.k;s.R=[];k=0;for(a=s.r.length;k<a;k++)if(e=s.r[k],!e.w){a:{h=f=d=void 0;g=e;f=h=e.a;e.w=!0;for(e=e.g;d=e.a;){if(e.w){if(d==f)break;console.log("ERR unique_monotone: segment in two chains",f,e);e=null;break a}e.w=!0;1==r.c.G(d,h)&&(h=d,g=e);e=e.g}e=g}e&&s.R.push(e)}s=k=new X(l);k=s.k.R;s.k.T=[];for(a=0;a<k.length;a++)if(f=k[a],e=f.j,d=f.g,d.g==e)B(s.k,f.a,d.a,e.a);else if(e=s,d=f.g,f=f.a,h=[d.a],g=0,d=d.g,
p=d.a,p!=f){for(;p!=f||1<g;)if(0<g)if(t=r.c.N(h[g],p,h[g-1]),Math.abs(t)<=r.c.n&&(p==f||r.c.G(h[g],p)==r.c.G(h[g],h[g-1]))&&(t=1),0<t)B(e.k,h[g-1],h[g],p),g--;else if(h[++g]=p,p==f)for(console.log("ERR uni-y-monotone: only concave angles left",h);1<g;)g--,B(e.k,h[g-1],h[g],h[g+1]);else d=d.g,p=d.a;else h[++g]=p,d=d.g,p=d.a;B(e.k,h[g-1],h[g],p)}}this.M=l;return l.T.concat()}};window.PNLTRI=r;r.REVISION=r.ca;r.Math=r.c;r.Triangulator=Z;Z.prototype.clear_lastData=Z.prototype.W;Z.prototype.get_PolyLeftArr=Z.prototype.Q;Z.prototype.triangulate_polygon=Z.prototype.ea;

Some files were not shown because too many files have changed in this diff Show More