three
Advanced tools
Comparing version 0.145.0 to 0.146.0
@@ -14,3 +14,2 @@ ( function () { | ||
} | ||
static CreateScaleAxisAnimation( period, axis = 'x' ) { | ||
@@ -25,3 +24,2 @@ | ||
} | ||
static CreateShakeAnimation( duration, shakeScale ) { | ||
@@ -32,3 +30,2 @@ | ||
tmp = new THREE.Vector3(); | ||
for ( let i = 0; i < duration * 10; i ++ ) { | ||
@@ -46,3 +43,2 @@ | ||
} | ||
static CreatePulsationAnimation( duration, pulseScale ) { | ||
@@ -53,3 +49,2 @@ | ||
tmp = new THREE.Vector3(); | ||
for ( let i = 0; i < duration * 10; i ++ ) { | ||
@@ -68,3 +63,2 @@ | ||
} | ||
static CreateVisibilityAnimation( duration ) { | ||
@@ -79,3 +73,2 @@ | ||
} | ||
static CreateMaterialColorAnimation( duration, colors ) { | ||
@@ -86,3 +79,2 @@ | ||
timeStep = duration / colors.length; | ||
for ( let i = 0; i <= colors.length; i ++ ) { | ||
@@ -89,0 +81,0 @@ |
( function () { | ||
const _q = new THREE.Quaternion(); | ||
const _targetPos = new THREE.Vector3(); | ||
const _targetVec = new THREE.Vector3(); | ||
const _effectorPos = new THREE.Vector3(); | ||
const _effectorVec = new THREE.Vector3(); | ||
const _linkPos = new THREE.Vector3(); | ||
const _invLinkQ = new THREE.Quaternion(); | ||
const _linkScale = new THREE.Vector3(); | ||
const _axis = new THREE.Vector3(); | ||
const _vector = new THREE.Vector3(); | ||
const _matrix = new THREE.Matrix4(); | ||
const _matrix = new THREE.Matrix4(); | ||
/** | ||
@@ -44,3 +35,2 @@ * CCD Algorithm | ||
class CCDIKSolver { | ||
@@ -56,6 +46,6 @@ | ||
this.iks = iks; | ||
this._valid(); | ||
} | ||
/** | ||
@@ -66,8 +56,5 @@ * Update all IK bones. | ||
*/ | ||
update() { | ||
const iks = this.iks; | ||
for ( let i = 0, il = iks.length; i < il; i ++ ) { | ||
@@ -82,2 +69,3 @@ | ||
} | ||
/** | ||
@@ -89,54 +77,44 @@ * Update one IK bone | ||
*/ | ||
updateOne( ik ) { | ||
const bones = this.mesh.skeleton.bones; // for reference overhead reduction in loop | ||
const bones = this.mesh.skeleton.bones; | ||
// for reference overhead reduction in loop | ||
const math = Math; | ||
const effector = bones[ ik.effector ]; | ||
const target = bones[ ik.target ]; // don't use getWorldPosition() here for the performance | ||
const target = bones[ ik.target ]; | ||
// don't use getWorldPosition() here for the performance | ||
// because it calls updateMatrixWorld( true ) inside. | ||
_targetPos.setFromMatrixPosition( target.matrixWorld ); | ||
const links = ik.links; | ||
const iteration = ik.iteration !== undefined ? ik.iteration : 1; | ||
for ( let i = 0; i < iteration; i ++ ) { | ||
let rotated = false; | ||
for ( let j = 0, jl = links.length; j < jl; j ++ ) { | ||
const link = bones[ links[ j ].index ]; // skip this link and following links. | ||
const link = bones[ links[ j ].index ]; | ||
// skip this link and following links. | ||
// this skip is used for MMD performance optimization. | ||
if ( links[ j ].enabled === false ) break; | ||
const limitation = links[ j ].limitation; | ||
const rotationMin = links[ j ].rotationMin; | ||
const rotationMax = links[ j ].rotationMax; // don't use getWorldPosition/Quaternion() here for the performance | ||
const rotationMax = links[ j ].rotationMax; | ||
// don't use getWorldPosition/Quaternion() here for the performance | ||
// because they call updateMatrixWorld( true ) inside. | ||
link.matrixWorld.decompose( _linkPos, _invLinkQ, _linkScale ); | ||
_invLinkQ.invert(); | ||
_effectorPos.setFromMatrixPosition( effector.matrixWorld ); | ||
_effectorPos.setFromMatrixPosition( effector.matrixWorld ); // work in link world | ||
// work in link world | ||
_effectorVec.subVectors( _effectorPos, _linkPos ); | ||
_effectorVec.applyQuaternion( _invLinkQ ); | ||
_effectorVec.normalize(); | ||
_targetVec.subVectors( _targetPos, _linkPos ); | ||
_targetVec.applyQuaternion( _invLinkQ ); | ||
_targetVec.normalize(); | ||
let angle = _targetVec.dot( _effectorVec ); | ||
if ( angle > 1.0 ) { | ||
@@ -152,6 +130,6 @@ | ||
angle = math.acos( angle ); // skip if changing angle is too small to prevent vibration of bone | ||
angle = math.acos( angle ); | ||
// skip if changing angle is too small to prevent vibration of bone | ||
if ( angle < 1e-5 ) continue; | ||
if ( ik.minAngle !== undefined && angle < ik.minAngle ) { | ||
@@ -170,9 +148,7 @@ | ||
_axis.crossVectors( _effectorVec, _targetVec ); | ||
_axis.normalize(); | ||
_q.setFromAxisAngle( _axis, angle ); | ||
link.quaternion.multiply( _q ); | ||
link.quaternion.multiply( _q ); // TODO: re-consider the limitation specification | ||
// TODO: re-consider the limitation specification | ||
if ( limitation !== undefined ) { | ||
@@ -211,2 +187,3 @@ | ||
} | ||
/** | ||
@@ -217,4 +194,2 @@ * Creates Helper | ||
*/ | ||
createHelper() { | ||
@@ -224,4 +199,5 @@ | ||
} // private methods | ||
} | ||
// private methods | ||
@@ -232,3 +208,2 @@ _valid() { | ||
const bones = this.mesh.skeleton.bones; | ||
for ( let i = 0, il = iks.length; i < il; i ++ ) { | ||
@@ -241,7 +216,5 @@ | ||
link0 = effector; | ||
for ( let j = 0, jl = links.length; j < jl; j ++ ) { | ||
link1 = bones[ links[ j ].index ]; | ||
if ( link0.parent !== link1 ) { | ||
@@ -262,3 +235,2 @@ | ||
} | ||
function getPosition( bone, matrixWorldInv ) { | ||
@@ -278,2 +250,3 @@ | ||
} | ||
/** | ||
@@ -285,7 +258,5 @@ * Visualize IK bones | ||
*/ | ||
class CCDIKHelper extends THREE.Object3D { | ||
constructor( mesh, iks = [] ) { | ||
constructor( mesh, iks = [], sphereSize = 0.25 ) { | ||
@@ -297,3 +268,3 @@ super(); | ||
this.matrixAutoUpdate = false; | ||
this.sphereGeometry = new THREE.SphereGeometry( 0.25, 16, 8 ); | ||
this.sphereGeometry = new THREE.SphereGeometry( sphereSize, 16, 8 ); | ||
this.targetSphereMaterial = new THREE.MeshBasicMaterial( { | ||
@@ -323,15 +294,12 @@ color: new THREE.Color( 0xff8888 ), | ||
} ); | ||
this._init(); | ||
} | ||
/** | ||
* Updates IK bones visualization. | ||
*/ | ||
updateMatrixWorld( force ) { | ||
const mesh = this.root; | ||
if ( this.visible ) { | ||
@@ -342,5 +310,3 @@ | ||
const bones = mesh.skeleton.bones; | ||
_matrix.copy( mesh.matrixWorld ).invert(); | ||
for ( let i = 0, il = iks.length; i < il; i ++ ) { | ||
@@ -355,3 +321,2 @@ | ||
effectorMesh.position.copy( getPosition( effectorBone, _matrix ) ); | ||
for ( let j = 0, jl = ik.links.length; j < jl; j ++ ) { | ||
@@ -370,3 +335,2 @@ | ||
setPositionOfBoneToAttributeArray( array, 1, effectorBone, _matrix ); | ||
for ( let j = 0, jl = ik.links.length; j < jl; j ++ ) { | ||
@@ -389,5 +353,26 @@ | ||
} // private method | ||
} | ||
/** | ||
* Frees the GPU-related resources allocated by this instance. Call this method whenever this instance is no longer used in your app. | ||
*/ | ||
dispose() { | ||
this.sphereGeometry.dispose(); | ||
this.targetSphereMaterial.dispose(); | ||
this.effectorSphereMaterial.dispose(); | ||
this.linkSphereMaterial.dispose(); | ||
this.lineMaterial.dispose(); | ||
const children = this.children; | ||
for ( let i = 0; i < children.length; i ++ ) { | ||
const child = children[ i ]; | ||
if ( child.isLine ) child.geometry.dispose(); | ||
} | ||
} | ||
// private method | ||
_init() { | ||
@@ -397,3 +382,2 @@ | ||
const iks = this.iks; | ||
function createLineGeometry( ik ) { | ||
@@ -437,3 +421,2 @@ | ||
this.add( createEffectorMesh() ); | ||
for ( let j = 0, jl = ik.links.length; j < jl; j ++ ) { | ||
@@ -440,0 +423,0 @@ |
@@ -15,3 +15,2 @@ ( function () { | ||
*/ | ||
class MMDAnimationHelper { | ||
@@ -47,8 +46,5 @@ | ||
}; | ||
this.onBeforePhysics = function /* mesh */ () {}; | ||
this.onBeforePhysics = function | ||
/* mesh */ | ||
() {}; // experimental | ||
// experimental | ||
this.sharedPhysics = false; | ||
@@ -58,2 +54,3 @@ this.masterPhysics = null; | ||
} | ||
/** | ||
@@ -75,4 +72,2 @@ * Adds an Three.js Object to helper and setups animation. | ||
*/ | ||
add( object, params = {} ) { | ||
@@ -102,2 +97,3 @@ | ||
} | ||
/** | ||
@@ -109,4 +105,2 @@ * Removes an Three.js Object from helper. | ||
*/ | ||
remove( object ) { | ||
@@ -136,2 +130,3 @@ | ||
} | ||
/** | ||
@@ -143,8 +138,5 @@ * Updates the animation. | ||
*/ | ||
update( delta ) { | ||
if ( this.audioManager !== null ) this.audioManager.control( delta ); | ||
for ( let i = 0; i < this.meshes.length; i ++ ) { | ||
@@ -161,2 +153,3 @@ | ||
} | ||
/** | ||
@@ -173,4 +166,2 @@ * Changes the pose of SkinnedMesh as VPD specifies. | ||
*/ | ||
pose( mesh, vpd, params = {} ) { | ||
@@ -182,3 +173,2 @@ | ||
const boneNameDictionary = {}; | ||
for ( let i = 0, il = bones.length; i < il; i ++ ) { | ||
@@ -192,3 +182,2 @@ | ||
const quaternion = new THREE.Quaternion(); | ||
for ( let i = 0, il = boneParams.length; i < il; i ++ ) { | ||
@@ -205,11 +194,10 @@ | ||
mesh.updateMatrixWorld( true ); // PMX animation system special path | ||
mesh.updateMatrixWorld( true ); | ||
// PMX animation system special path | ||
if ( this.configuration.pmxAnimation && mesh.geometry.userData.MMD && mesh.geometry.userData.MMD.format === 'pmx' ) { | ||
const sortedBonesData = this._sortBoneDataArray( mesh.geometry.userData.MMD.bones.slice() ); | ||
const ikSolver = params.ik !== false ? this._createCCDIKSolver( mesh ) : null; | ||
const grantSolver = params.grant !== false ? this.createGrantSolver( mesh ) : null; | ||
this._animatePMXMesh( mesh, sortedBonesData, ikSolver, grantSolver ); | ||
@@ -236,2 +224,3 @@ | ||
} | ||
/** | ||
@@ -244,4 +233,2 @@ * Enabes/Disables an animation feature. | ||
*/ | ||
enable( key, enabled ) { | ||
@@ -256,3 +243,2 @@ | ||
this.enabled[ key ] = enabled; | ||
if ( key === 'physics' ) { | ||
@@ -271,2 +257,3 @@ | ||
} | ||
/** | ||
@@ -278,4 +265,2 @@ * Creates an GrantSolver instance. | ||
*/ | ||
createGrantSolver( mesh ) { | ||
@@ -285,4 +270,5 @@ | ||
} // private methods | ||
} | ||
// private methods | ||
@@ -301,5 +287,3 @@ _addMesh( mesh, params ) { | ||
} ); | ||
this._setupMeshAnimation( mesh, params.animation ); | ||
if ( params.physics !== false ) { | ||
@@ -314,3 +298,2 @@ | ||
} | ||
_setupCamera( camera, params ) { | ||
@@ -328,3 +311,2 @@ | ||
this.objects.set( camera, {} ); | ||
if ( params.animation !== undefined ) { | ||
@@ -339,3 +321,2 @@ | ||
} | ||
_setupAudio( audio, params ) { | ||
@@ -358,3 +339,2 @@ | ||
} | ||
_removeMesh( mesh ) { | ||
@@ -364,3 +344,2 @@ | ||
let writeIndex = 0; | ||
for ( let i = 0, il = this.meshes.length; i < il; i ++ ) { | ||
@@ -390,3 +369,2 @@ | ||
} | ||
_clearCamera( camera ) { | ||
@@ -406,3 +384,2 @@ | ||
} | ||
_clearAudio( audio ) { | ||
@@ -422,7 +399,5 @@ | ||
} | ||
_setupMeshAnimation( mesh, animation ) { | ||
const objects = this.objects.get( mesh ); | ||
if ( animation !== undefined ) { | ||
@@ -432,3 +407,2 @@ | ||
objects.mixer = new THREE.AnimationMixer( mesh ); | ||
for ( let i = 0, il = animations.length; i < il; i ++ ) { | ||
@@ -438,5 +412,5 @@ | ||
} // TODO: find a workaround not to access ._clip looking like a private property | ||
} | ||
// TODO: find a workaround not to access ._clip looking like a private property | ||
objects.mixer.addEventListener( 'loop', function ( event ) { | ||
@@ -457,3 +431,2 @@ | ||
} | ||
_setupCameraAnimation( camera, animation ) { | ||
@@ -464,3 +437,2 @@ | ||
objects.mixer = new THREE.AnimationMixer( camera ); | ||
for ( let i = 0, il = animations.length; i < il; i ++ ) { | ||
@@ -473,11 +445,11 @@ | ||
} | ||
_setupMeshPhysics( mesh, params ) { | ||
const objects = this.objects.get( mesh ); // shared physics is experimental | ||
const objects = this.objects.get( mesh ); | ||
// shared physics is experimental | ||
if ( params.world === undefined && this.sharedPhysics ) { | ||
const masterPhysics = this._getMasterPhysics(); | ||
if ( masterPhysics !== null ) world = masterPhysics.world; // eslint-disable-line no-undef | ||
@@ -488,7 +460,5 @@ | ||
objects.physics = this._createMMDPhysics( mesh, params ); | ||
if ( objects.mixer && params.animationWarmup !== false ) { | ||
this._animateMesh( mesh, 0 ); | ||
objects.physics.reset(); | ||
@@ -499,7 +469,5 @@ | ||
objects.physics.warmup( params.warmup !== undefined ? params.warmup : 60 ); | ||
this._optimizeIK( mesh, true ); | ||
} | ||
_animateMesh( mesh, delta ) { | ||
@@ -513,3 +481,2 @@ | ||
const looped = objects.looped; | ||
if ( mixer && this.enabled.animation ) { | ||
@@ -520,13 +487,11 @@ | ||
//this._updatePropertyMixersBuffer( mesh ); | ||
this._restoreBones( mesh ); | ||
mixer.update( delta ); | ||
this._saveBones( mesh ); | ||
this._saveBones( mesh ); // PMX animation system special path | ||
// PMX animation system special path | ||
if ( this.configuration.pmxAnimation && mesh.geometry.userData.MMD && mesh.geometry.userData.MMD.format === 'pmx' ) { | ||
if ( ! objects.sortedBonesData ) objects.sortedBonesData = this._sortBoneDataArray( mesh.geometry.userData.MMD.bones.slice() ); | ||
this._animatePMXMesh( mesh, objects.sortedBonesData, ikSolver && this.enabled.ik ? ikSolver : null, grantSolver && this.enabled.grant ? grantSolver : null ); | ||
@@ -567,7 +532,7 @@ | ||
} // Sort bones in order by 1. transformationClass and 2. bone index. | ||
} | ||
// Sort bones in order by 1. transformationClass and 2. bone index. | ||
// In PMX animation system, bone transformations should be processed | ||
// in this order. | ||
_sortBoneDataArray( boneDataArray ) { | ||
@@ -589,3 +554,5 @@ | ||
} // PMX Animation system is a bit too complex and doesn't great match to | ||
} | ||
// PMX Animation system is a bit too complex and doesn't great match to | ||
// Three.js Animation system. This method attempts to simulate it as much as | ||
@@ -597,10 +564,6 @@ // possible but doesn't perfectly simulate. | ||
// If you need better method you would be required to write your own. | ||
_animatePMXMesh( mesh, sortedBonesData, ikSolver, grantSolver ) { | ||
_quaternionIndex = 0; | ||
_grantResultMap.clear(); | ||
for ( let i = 0, il = sortedBonesData.length; i < il; i ++ ) { | ||
@@ -616,7 +579,5 @@ | ||
} | ||
_animateCamera( camera, delta ) { | ||
const mixer = this.objects.get( camera ).mixer; | ||
if ( mixer && this.enabled.cameraAnimation ) { | ||
@@ -633,3 +594,2 @@ | ||
} | ||
_optimizeIK( mesh, physicsEnabled ) { | ||
@@ -639,3 +599,2 @@ | ||
const bones = mesh.geometry.userData.MMD.bones; | ||
for ( let i = 0, il = iks.length; i < il; i ++ ) { | ||
@@ -645,7 +604,5 @@ | ||
const links = ik.links; | ||
for ( let j = 0, jl = links.length; j < jl; j ++ ) { | ||
const link = links[ j ]; | ||
if ( physicsEnabled === true ) { | ||
@@ -668,3 +625,2 @@ | ||
} | ||
_createCCDIKSolver( mesh ) { | ||
@@ -681,3 +637,2 @@ | ||
} | ||
_createMMDPhysics( mesh, params ) { | ||
@@ -694,2 +649,3 @@ | ||
} | ||
/* | ||
@@ -699,4 +655,2 @@ * Detects the longest duration and then sets it to them to sync. | ||
*/ | ||
_syncDuration() { | ||
@@ -708,4 +662,6 @@ | ||
const camera = this.camera; | ||
const audioManager = this.audioManager; // get the longest duration | ||
const audioManager = this.audioManager; | ||
// get the longest duration | ||
for ( let i = 0, il = meshes.length; i < il; i ++ ) { | ||
@@ -715,7 +671,5 @@ | ||
if ( mixer === undefined ) continue; | ||
for ( let j = 0; j < mixer._actions.length; j ++ ) { | ||
const clip = mixer._actions[ j ]._clip; | ||
if ( ! objects.has( clip ) ) { | ||
@@ -738,3 +692,2 @@ | ||
const mixer = this.objects.get( camera ).mixer; | ||
if ( mixer !== undefined ) { | ||
@@ -745,3 +698,2 @@ | ||
const clip = mixer._actions[ i ]._clip; | ||
if ( ! objects.has( clip ) ) { | ||
@@ -769,4 +721,6 @@ | ||
max += this.configuration.afterglow; // update the duration | ||
max += this.configuration.afterglow; | ||
// update the duration | ||
for ( let i = 0, il = this.meshes.length; i < il; i ++ ) { | ||
@@ -776,3 +730,2 @@ | ||
if ( mixer === undefined ) continue; | ||
for ( let j = 0, jl = mixer._actions.length; j < jl; j ++ ) { | ||
@@ -789,3 +742,2 @@ | ||
const mixer = this.objects.get( camera ).mixer; | ||
if ( mixer !== undefined ) { | ||
@@ -809,4 +761,5 @@ | ||
} // workaround | ||
} | ||
// workaround | ||
@@ -818,3 +771,2 @@ _updatePropertyMixersBuffer( mesh ) { | ||
const accuIndex = mixer._accuIndex; | ||
for ( let i = 0, il = propertyMixers.length; i < il; i ++ ) { | ||
@@ -831,2 +783,3 @@ | ||
} | ||
/* | ||
@@ -841,4 +794,2 @@ * Avoiding these two issues by restore/save bones before/after mixer animation. | ||
*/ | ||
_saveBones( mesh ) { | ||
@@ -849,3 +800,2 @@ | ||
let backupBones = objects.backupBones; | ||
if ( backupBones === undefined ) { | ||
@@ -867,3 +817,2 @@ | ||
} | ||
_restoreBones( mesh ) { | ||
@@ -875,3 +824,2 @@ | ||
const bones = mesh.skeleton.bones; | ||
for ( let i = 0, il = bones.length; i < il; i ++ ) { | ||
@@ -885,4 +833,5 @@ | ||
} // experimental | ||
} | ||
// experimental | ||
@@ -892,7 +841,5 @@ _getMasterPhysics() { | ||
if ( this.masterPhysics !== null ) return this.masterPhysics; | ||
for ( let i = 0, il = this.meshes.length; i < il; i ++ ) { | ||
const physics = this.meshes[ i ].physics; | ||
if ( physics !== undefined && physics !== null ) { | ||
@@ -910,15 +857,10 @@ | ||
} | ||
_updateSharedPhysics( delta ) { | ||
if ( this.meshes.length === 0 || ! this.enabled.physics || ! this.sharedPhysics ) return; | ||
const physics = this._getMasterPhysics(); | ||
if ( physics === null ) return; | ||
for ( let i = 0, il = this.meshes.length; i < il; i ++ ) { | ||
const p = this.meshes[ i ].physics; | ||
if ( p !== null && p !== undefined ) { | ||
@@ -933,7 +875,5 @@ | ||
physics.stepSimulation( delta ); | ||
for ( let i = 0, il = this.meshes.length; i < il; i ++ ) { | ||
const p = this.meshes[ i ].physics; | ||
if ( p !== null && p !== undefined ) { | ||
@@ -949,8 +889,7 @@ | ||
} // Keep working quaternions for less GC | ||
} | ||
// Keep working quaternions for less GC | ||
const _quaternions = []; | ||
let _quaternionIndex = 0; | ||
function getQuaternion() { | ||
@@ -966,8 +905,7 @@ | ||
} // Save rotation whose grant and IK are already applied | ||
} | ||
// Save rotation whose grant and IK are already applied | ||
// used by grant children | ||
const _grantResultMap = new Map(); | ||
function updateOne( mesh, boneIndex, ikSolver, grantSolver ) { | ||
@@ -978,13 +916,15 @@ | ||
const boneData = bonesData[ boneIndex ]; | ||
const bone = bones[ boneIndex ]; // Return if already updated by being referred as a grant parent. | ||
const bone = bones[ boneIndex ]; | ||
// Return if already updated by being referred as a grant parent. | ||
if ( _grantResultMap.has( boneIndex ) ) return; | ||
const quaternion = getQuaternion(); // Initialize grant result here to prevent infinite loop. | ||
const quaternion = getQuaternion(); | ||
// Initialize grant result here to prevent infinite loop. | ||
// If it's referred before updating with actual result later | ||
// result without applyting IK or grant is gotten | ||
// but better than composing of infinite loop. | ||
_grantResultMap.set( boneIndex, quaternion.copy( bone.quaternion ) ); | ||
_grantResultMap.set( boneIndex, quaternion.copy( bone.quaternion ) ); // @TODO: Support global grant and grant position | ||
// @TODO: Support global grant and grant position | ||
if ( grantSolver && boneData.grant && ! boneData.grant.isLocal && boneData.grant.affectRotation ) { | ||
@@ -994,3 +934,2 @@ | ||
const ratio = boneData.grant.ratio; | ||
if ( ! _grantResultMap.has( parentIndex ) ) { | ||
@@ -1011,6 +950,6 @@ | ||
mesh.updateMatrixWorld( true ); | ||
ikSolver.updateOne( boneData.ik ); // No confident, but it seems the grant results with ik links should be updated? | ||
ikSolver.updateOne( boneData.ik ); | ||
// No confident, but it seems the grant results with ik links should be updated? | ||
const links = boneData.ik.links; | ||
for ( let i = 0, il = links.length; i < il; i ++ ) { | ||
@@ -1021,3 +960,2 @@ | ||
const linkIndex = link.index; | ||
if ( _grantResultMap.has( linkIndex ) ) { | ||
@@ -1031,9 +969,10 @@ | ||
} // Update with the actual result here | ||
} | ||
// Update with the actual result here | ||
quaternion.copy( bone.quaternion ); | ||
} // | ||
} | ||
// | ||
@@ -1057,2 +996,3 @@ class AudioManager { | ||
} | ||
/** | ||
@@ -1062,4 +1002,2 @@ * @param {Number} delta | ||
*/ | ||
control( delta ) { | ||
@@ -1073,4 +1011,5 @@ | ||
} // private methods | ||
} | ||
// private methods | ||
@@ -1080,3 +1019,2 @@ _shouldStartAudio() { | ||
if ( this.audio.isPlaying ) return false; | ||
while ( this.currentTime >= this.duration ) { | ||
@@ -1088,4 +1026,5 @@ | ||
if ( this.currentTime < this.delayTime ) return false; // 'duration' can be bigger than 'audioDuration + delayTime' because of sync configuration | ||
if ( this.currentTime < this.delayTime ) return false; | ||
// 'duration' can be bigger than 'audioDuration + delayTime' because of sync configuration | ||
if ( this.currentTime - this.delayTime > this.audioDuration ) return false; | ||
@@ -1095,3 +1034,2 @@ return true; | ||
} | ||
_shouldStopAudio() { | ||
@@ -1104,4 +1042,4 @@ | ||
} | ||
const _q = new THREE.Quaternion(); | ||
const _q = new THREE.Quaternion(); | ||
/** | ||
@@ -1115,4 +1053,2 @@ * Solver for Grant (Fuyo in Japanese. I just google translated because | ||
*/ | ||
class GrantSolver { | ||
@@ -1126,2 +1062,3 @@ | ||
} | ||
/** | ||
@@ -1131,8 +1068,5 @@ * Solve all the grant bones | ||
*/ | ||
update() { | ||
const grants = this.grants; | ||
for ( let i = 0, il = grants.length; i < il; i ++ ) { | ||
@@ -1147,2 +1081,3 @@ | ||
} | ||
/** | ||
@@ -1153,4 +1088,2 @@ * Solve a grant bone | ||
*/ | ||
updateOne( grant ) { | ||
@@ -1161,9 +1094,8 @@ | ||
const parentBone = bones[ grant.parentIndex ]; | ||
if ( grant.isLocal ) { | ||
// TODO: implement | ||
if ( grant.affectPosition ) {} // TODO: implement | ||
if ( grant.affectPosition ) {} | ||
// TODO: implement | ||
if ( grant.affectRotation ) {} | ||
@@ -1187,9 +1119,6 @@ | ||
} | ||
addGrantRotation( bone, q, ratio ) { | ||
_q.set( 0, 0, 0, 1 ); | ||
_q.slerp( q, ratio ); | ||
bone.quaternion.multiply( _q ); | ||
@@ -1196,0 +1125,0 @@ return this; |
@@ -37,2 +37,3 @@ ( function () { | ||
this.mesh = mesh; | ||
/* | ||
@@ -44,3 +45,2 @@ * I don't know why but 1/60 unitStep easily breaks models | ||
*/ | ||
this.unitStep = params.unitStep !== undefined ? params.unitStep : 1 / 65; | ||
@@ -54,6 +54,6 @@ this.maxStepNum = params.maxStepNum !== undefined ? params.maxStepNum : 3; | ||
this.constraints = []; | ||
this._init( mesh, rigidBodyParams, constraintParams ); | ||
} | ||
/** | ||
@@ -65,8 +65,8 @@ * Advances Physics calculation and updates bones. | ||
*/ | ||
update( delta ) { | ||
const manager = this.manager; | ||
const mesh = this.mesh; // rigid bodies and constrains are for | ||
const mesh = this.mesh; | ||
// rigid bodies and constrains are for | ||
// mesh's world scale (1, 1, 1). | ||
@@ -80,3 +80,2 @@ // Convert to (1, 1, 1) if it isn't. | ||
mesh.matrixWorld.decompose( position, quaternion, scale ); | ||
if ( scale.x !== 1 || scale.y !== 1 || scale.z !== 1 ) { | ||
@@ -89,3 +88,2 @@ | ||
let parent; | ||
if ( isNonDefaultScale ) { | ||
@@ -99,12 +97,12 @@ | ||
} // calculate physics and update bones | ||
} | ||
// calculate physics and update bones | ||
this._updateRigidBodies(); | ||
this._stepSimulation( delta ); | ||
this._updateBones(); | ||
this._updateBones(); // restore mesh if converted above | ||
// restore mesh if converted above | ||
if ( isNonDefaultScale ) { | ||
@@ -123,2 +121,3 @@ | ||
} | ||
/** | ||
@@ -129,4 +128,2 @@ * Resets rigid bodies transorm to current bone's. | ||
*/ | ||
reset() { | ||
@@ -143,2 +140,3 @@ | ||
} | ||
/** | ||
@@ -150,4 +148,2 @@ * Warm ups Rigid bodies. Calculates cycles steps. | ||
*/ | ||
warmup( cycles ) { | ||
@@ -164,2 +160,3 @@ | ||
} | ||
/** | ||
@@ -171,4 +168,2 @@ * Sets gravity. | ||
*/ | ||
setGravity( gravity ) { | ||
@@ -181,2 +176,3 @@ | ||
} | ||
/** | ||
@@ -187,4 +183,2 @@ * Creates MMDPhysicsHelper | ||
*/ | ||
createHelper() { | ||
@@ -194,8 +188,11 @@ | ||
} // private methods | ||
} | ||
// private methods | ||
_init( mesh, rigidBodyParams, constraintParams ) { | ||
const manager = this.manager; // rigid body/constraint parameters are for | ||
const manager = this.manager; | ||
// rigid body/constraint parameters are for | ||
// mesh's default world transform as position(0, 0, 0), | ||
@@ -216,3 +213,2 @@ // quaternion(0, 0, 0, 1) and scale(0, 0, 0) | ||
mesh.updateMatrixWorld( true ); | ||
if ( this.world === null ) { | ||
@@ -226,5 +222,3 @@ | ||
this._initRigidBodies( rigidBodyParams ); | ||
this._initConstraints( constraintParams ); | ||
if ( parent !== null ) mesh.parent = parent; | ||
@@ -241,3 +235,2 @@ mesh.position.copy( currentPosition ); | ||
} | ||
_createWorld() { | ||
@@ -253,3 +246,2 @@ | ||
} | ||
_initRigidBodies( rigidBodies ) { | ||
@@ -264,3 +256,2 @@ | ||
} | ||
_initConstraints( constraints ) { | ||
@@ -278,3 +269,2 @@ | ||
} | ||
_stepSimulation( delta ) { | ||
@@ -285,3 +275,2 @@ | ||
let maxStepNum = ( delta / unitStep | 0 ) + 1; | ||
if ( stepTime < unitStep ) { | ||
@@ -303,3 +292,2 @@ | ||
} | ||
_updateRigidBodies() { | ||
@@ -314,3 +302,2 @@ | ||
} | ||
_updateBones() { | ||
@@ -327,2 +314,3 @@ | ||
} | ||
/** | ||
@@ -337,4 +325,2 @@ * This manager's responsibilies are | ||
*/ | ||
class ResourceManager { | ||
@@ -348,4 +334,5 @@ | ||
this.threeQuaternions = []; | ||
this.threeEulers = []; // for Ammo.js | ||
this.threeEulers = []; | ||
// for Ammo.js | ||
this.transforms = []; | ||
@@ -356,3 +343,2 @@ this.quaternions = []; | ||
} | ||
allocThreeVector3() { | ||
@@ -363,3 +349,2 @@ | ||
} | ||
freeThreeVector3( v ) { | ||
@@ -370,3 +355,2 @@ | ||
} | ||
allocThreeMatrix4() { | ||
@@ -377,3 +361,2 @@ | ||
} | ||
freeThreeMatrix4( m ) { | ||
@@ -384,3 +367,2 @@ | ||
} | ||
allocThreeQuaternion() { | ||
@@ -391,3 +373,2 @@ | ||
} | ||
freeThreeQuaternion( q ) { | ||
@@ -398,3 +379,2 @@ | ||
} | ||
allocThreeEuler() { | ||
@@ -405,3 +385,2 @@ | ||
} | ||
freeThreeEuler( e ) { | ||
@@ -412,3 +391,2 @@ | ||
} | ||
allocTransform() { | ||
@@ -419,3 +397,2 @@ | ||
} | ||
freeTransform( t ) { | ||
@@ -426,3 +403,2 @@ | ||
} | ||
allocQuaternion() { | ||
@@ -433,3 +409,2 @@ | ||
} | ||
freeQuaternion( q ) { | ||
@@ -440,3 +415,2 @@ | ||
} | ||
allocVector3() { | ||
@@ -447,3 +421,2 @@ | ||
} | ||
freeVector3( v ) { | ||
@@ -454,3 +427,2 @@ | ||
} | ||
setIdentity( t ) { | ||
@@ -461,3 +433,2 @@ | ||
} | ||
getBasis( t ) { | ||
@@ -470,3 +441,2 @@ | ||
} | ||
getBasisAsMatrix3( t ) { | ||
@@ -480,3 +450,2 @@ | ||
} | ||
getOrigin( t ) { | ||
@@ -487,3 +456,2 @@ | ||
} | ||
setOrigin( t, v ) { | ||
@@ -494,3 +462,2 @@ | ||
} | ||
copyOrigin( t1, t2 ) { | ||
@@ -502,3 +469,2 @@ | ||
} | ||
setBasis( t, q ) { | ||
@@ -509,3 +475,2 @@ | ||
} | ||
setBasisFromMatrix3( t, m ) { | ||
@@ -518,3 +483,2 @@ | ||
} | ||
setOriginFromArray3( t, a ) { | ||
@@ -525,3 +489,2 @@ | ||
} | ||
setOriginFromThreeVector3( t, v ) { | ||
@@ -532,3 +495,2 @@ | ||
} | ||
setBasisFromArray3( t, a ) { | ||
@@ -544,3 +506,2 @@ | ||
} | ||
setBasisFromThreeQuaternion( t, a ) { | ||
@@ -557,3 +518,2 @@ | ||
} | ||
multiplyTransforms( t1, t2 ) { | ||
@@ -577,3 +537,2 @@ | ||
} | ||
inverseTransform( t ) { | ||
@@ -594,3 +553,2 @@ | ||
} | ||
multiplyMatrices3( m1, m2 ) { | ||
@@ -623,3 +581,2 @@ | ||
} | ||
addVector3( v1, v2 ) { | ||
@@ -632,3 +589,2 @@ | ||
} | ||
dotVectors3( v1, v2 ) { | ||
@@ -639,3 +595,2 @@ | ||
} | ||
rowOfMatrix3( m, i ) { | ||
@@ -648,3 +603,2 @@ | ||
} | ||
columnOfMatrix3( m, i ) { | ||
@@ -657,3 +611,2 @@ | ||
} | ||
negativeVector3( v ) { | ||
@@ -666,3 +619,2 @@ | ||
} | ||
multiplyMatrix3ByVector3( m, v ) { | ||
@@ -684,3 +636,2 @@ | ||
} | ||
transposeMatrix3( m ) { | ||
@@ -701,3 +652,2 @@ | ||
} | ||
quaternionToMatrix3( q ) { | ||
@@ -731,3 +681,2 @@ | ||
} | ||
matrix3ToQuaternion( m ) { | ||
@@ -737,3 +686,2 @@ | ||
var s, x, y, z, w; | ||
if ( t > 0 ) { | ||
@@ -783,2 +731,3 @@ | ||
} | ||
/** | ||
@@ -790,4 +739,2 @@ * @param {THREE.SkinnedMesh} mesh | ||
*/ | ||
class RigidBody { | ||
@@ -805,6 +752,6 @@ | ||
this.boneOffsetFormInverse = null; | ||
this._init(); | ||
} | ||
/** | ||
@@ -815,11 +762,9 @@ * Resets rigid body transform to the current bone's. | ||
*/ | ||
reset() { | ||
this._setTransformFromBone(); | ||
return this; | ||
} | ||
/** | ||
@@ -830,4 +775,2 @@ * Updates rigid body's transform from the current bone. | ||
*/ | ||
updateFromBone() { | ||
@@ -844,2 +787,3 @@ | ||
} | ||
/** | ||
@@ -850,4 +794,2 @@ * Updates bone from the current ridid body's transform. | ||
*/ | ||
updateBone() { | ||
@@ -862,3 +804,2 @@ | ||
this._updateBoneRotation(); | ||
if ( this.params.type === 1 ) { | ||
@@ -871,3 +812,2 @@ | ||
this.bone.updateMatrixWorld( true ); | ||
if ( this.params.type === 2 ) { | ||
@@ -881,4 +821,5 @@ | ||
} // private methods | ||
} | ||
// private methods | ||
@@ -893,9 +834,6 @@ _init() { | ||
return new Ammo.btSphereShape( p.width ); | ||
case 1: | ||
return new Ammo.btBoxShape( new Ammo.btVector3( p.width, p.height, p.depth ) ); | ||
case 2: | ||
return new Ammo.btCapsuleShape( p.width, p.height ); | ||
default: | ||
@@ -916,3 +854,2 @@ throw new Error( 'unknown shape type ' + p.shapeType ); | ||
localInertia.setValue( 0, 0, 0 ); | ||
if ( weight !== 0 ) { | ||
@@ -938,6 +875,6 @@ | ||
const body = new Ammo.btRigidBody( info ); | ||
if ( params.type === 0 ) { | ||
body.setCollisionFlags( body.getCollisionFlags() | 2 ); | ||
/* | ||
@@ -948,3 +885,2 @@ * It'd be better to comment out this line though in general I should call this method | ||
*/ | ||
body.setActivationState( 4 ); | ||
@@ -967,3 +903,2 @@ | ||
} | ||
_getBoneTransform() { | ||
@@ -987,3 +922,2 @@ | ||
} | ||
_getWorldTransformForBone() { | ||
@@ -996,11 +930,9 @@ | ||
} | ||
_setTransformFromBone() { | ||
const manager = this.manager; | ||
const form = this._getBoneTransform(); | ||
const form = this._getBoneTransform(); // TODO: check the most appropriate way to set | ||
// TODO: check the most appropriate way to set | ||
//this.body.setWorldTransform( form ); | ||
this.body.setCenterOfMassTransform( form ); | ||
@@ -1011,14 +943,12 @@ this.body.getMotionState().setWorldTransform( form ); | ||
} | ||
_setPositionFromBone() { | ||
const manager = this.manager; | ||
const form = this._getBoneTransform(); | ||
const tr = manager.allocTransform(); | ||
this.body.getMotionState().getWorldTransform( tr ); | ||
manager.copyOrigin( tr, form ); // TODO: check the most appropriate way to set | ||
manager.copyOrigin( tr, form ); | ||
// TODO: check the most appropriate way to set | ||
//this.body.setWorldTransform( tr ); | ||
this.body.setCenterOfMassTransform( tr ); | ||
@@ -1030,9 +960,6 @@ this.body.getMotionState().setWorldTransform( tr ); | ||
} | ||
_updateBoneRotation() { | ||
const manager = this.manager; | ||
const tr = this._getWorldTransformForBone(); | ||
const q = manager.getBasis( tr ); | ||
@@ -1045,8 +972,11 @@ const thQ = manager.allocThreeQuaternion(); | ||
thQ2.conjugate(); | ||
thQ2.multiply( thQ ); //this.bone.quaternion.multiply( thQ2 ); | ||
thQ2.multiply( thQ ); | ||
thQ3.setFromRotationMatrix( this.bone.matrix ); // Renormalizing quaternion here because repeatedly transforming | ||
//this.bone.quaternion.multiply( thQ2 ); | ||
thQ3.setFromRotationMatrix( this.bone.matrix ); | ||
// Renormalizing quaternion here because repeatedly transforming | ||
// quaternion continuously accumulates floating point error and | ||
// can end up being overflow. See #15335 | ||
this.bone.quaternion.copy( thQ2.multiply( thQ3 ).normalize() ); | ||
@@ -1060,13 +990,9 @@ manager.freeThreeQuaternion( thQ ); | ||
} | ||
_updateBonePosition() { | ||
const manager = this.manager; | ||
const tr = this._getWorldTransformForBone(); | ||
const thV = manager.allocThreeVector3(); | ||
const o = manager.getOrigin( tr ); | ||
thV.set( o.x(), o.y(), o.z() ); | ||
if ( this.bone.parent ) { | ||
@@ -1084,4 +1010,5 @@ | ||
} // | ||
} | ||
// | ||
@@ -1107,7 +1034,7 @@ class Constraint { | ||
this.constraint = null; | ||
this._init(); | ||
} // private method | ||
} | ||
// private method | ||
@@ -1145,3 +1072,2 @@ _init() { | ||
constraint.setAngularUpperLimit( aul ); | ||
for ( let i = 0; i < 3; i ++ ) { | ||
@@ -1168,2 +1094,3 @@ | ||
} | ||
/* | ||
@@ -1175,4 +1102,2 @@ * Currently(10/31/2016) official ammo.js doesn't support | ||
*/ | ||
if ( constraint.setParam !== undefined ) { | ||
@@ -1204,13 +1129,10 @@ | ||
} // | ||
} | ||
// | ||
const _position = new THREE.Vector3(); | ||
const _quaternion = new THREE.Quaternion(); | ||
const _scale = new THREE.Vector3(); | ||
const _matrixWorldInv = new THREE.Matrix4(); | ||
class MMDPhysicsHelper extends THREE.Object3D { | ||
@@ -1256,21 +1178,38 @@ | ||
} ) ); | ||
this._init(); | ||
} | ||
/** | ||
* Updates Rigid Bodies visualization. | ||
* Frees the GPU-related resources allocated by this instance. Call this method whenever this instance is no longer used in your app. | ||
*/ | ||
dispose() { | ||
const materials = this.materials; | ||
const children = this.children; | ||
for ( let i = 0; i < materials.length; i ++ ) { | ||
materials[ i ].dispose(); | ||
} | ||
for ( let i = 0; i < children.length; i ++ ) { | ||
const child = children[ i ]; | ||
if ( child.isMesh ) child.geometry.dispose(); | ||
} | ||
} | ||
/** | ||
* Updates Rigid Bodies visualization. | ||
*/ | ||
updateMatrixWorld( force ) { | ||
var mesh = this.root; | ||
if ( this.visible ) { | ||
var bodies = this.physics.bodies; | ||
_matrixWorldInv.copy( mesh.matrixWorld ).decompose( _position, _quaternion, _scale ).compose( _position, _quaternion, _scale.set( 1, 1, 1 ) ).invert(); | ||
for ( var i = 0, il = bodies.length; i < il; i ++ ) { | ||
@@ -1293,4 +1232,5 @@ | ||
} // private method | ||
} | ||
// private method | ||
@@ -1300,3 +1240,2 @@ _init() { | ||
var bodies = this.physics.bodies; | ||
function createGeometry( param ) { | ||
@@ -1308,9 +1247,6 @@ | ||
return new THREE.SphereGeometry( param.width, 16, 8 ); | ||
case 1: | ||
return new THREE.BoxGeometry( param.width * 2, param.height * 2, param.depth * 2, 8, 8, 8 ); | ||
case 2: | ||
return new THREE.CapsuleGeometry( param.width, param.height, 8, 16 ); | ||
default: | ||
@@ -1317,0 +1253,0 @@ return null; |
@@ -23,12 +23,13 @@ ( function () { | ||
this.materialDepth.uniforms[ 'mNear' ].value = near; | ||
this.materialDepth.uniforms[ 'mFar' ].value = far; // In case of cinematicCamera, having a default lens set is important | ||
this.materialDepth.uniforms[ 'mFar' ].value = far; | ||
// In case of cinematicCamera, having a default lens set is important | ||
this.setLens(); | ||
this.initPostProcessing(); | ||
} // providing fnumber and coc(Circle of Confusion) as extra arguments | ||
} | ||
// providing fnumber and coc(Circle of Confusion) as extra arguments | ||
// In case of cinematicCamera, having a default lens set is important | ||
// if fnumber and coc are not provided, cinematicCamera tries to act as a basic THREE.PerspectiveCamera | ||
setLens( focalLength = 35, filmGauge = 35, fNumber = 8, coc = 0.019 ) { | ||
@@ -39,10 +40,11 @@ | ||
this.fNumber = fNumber; | ||
this.coc = coc; // fNumber is focalLength by aperture | ||
this.coc = coc; | ||
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 | ||
// 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 ); | ||
} | ||
linearize( depth ) { | ||
@@ -55,3 +57,2 @@ | ||
} | ||
smoothstep( near, far, depth ) { | ||
@@ -63,3 +64,2 @@ | ||
} | ||
saturate( x ) { | ||
@@ -69,17 +69,22 @@ | ||
} // function for focusing at a distance from the camera | ||
} | ||
// function for focusing at a distance from the camera | ||
focusAt( focusDistance = 20 ) { | ||
const focalLength = this.getFocalLength(); // distance from the camera (normal to frustrum) to focus on | ||
const focalLength = this.getFocalLength(); | ||
this.focus = focusDistance; // the nearest point from the camera which is in focus (unused) | ||
// distance from the camera (normal to frustrum) to focus on | ||
this.focus = focusDistance; | ||
this.nearPoint = this.hyperFocal * this.focus / ( this.hyperFocal + ( this.focus - focalLength ) ); // the farthest point from the camera which is in focus (unused) | ||
// the nearest point from the camera which is in focus (unused) | ||
this.nearPoint = this.hyperFocal * this.focus / ( this.hyperFocal + ( this.focus - focalLength ) ); | ||
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) | ||
// the farthest point from the camera which is in focus (unused) | ||
this.farPoint = this.hyperFocal * this.focus / ( this.hyperFocal - ( this.focus - focalLength ) ); | ||
this.depthOfField = this.farPoint - this.nearPoint; // Considering minimum distance of focus for a standard lens (unused) | ||
// 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; | ||
@@ -91,3 +96,2 @@ this.sdistance = this.smoothstep( this.near, this.far, this.focus ); | ||
} | ||
initPostProcessing() { | ||
@@ -110,4 +114,6 @@ | ||
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[ 'focalDepth' ].value = 0.1; | ||
//console.log( this.postprocessing.bokeh_uniforms[ "focalDepth" ].value ); | ||
this.postprocessing.bokeh_uniforms[ 'znear' ].value = this.near; | ||
@@ -134,3 +140,2 @@ this.postprocessing.bokeh_uniforms[ 'zfar' ].value = this.near; | ||
} | ||
renderCinematic( scene, renderer ) { | ||
@@ -141,14 +146,20 @@ | ||
const currentRenderTarget = renderer.getRenderTarget(); | ||
renderer.clear(); // Render scene into texture | ||
renderer.clear(); | ||
// Render scene into texture | ||
scene.overrideMaterial = null; | ||
renderer.setRenderTarget( this.postprocessing.rtTextureColor ); | ||
renderer.clear(); | ||
renderer.render( scene, this ); // Render depth into texture | ||
renderer.render( scene, this ); | ||
// Render depth into texture | ||
scene.overrideMaterial = this.materialDepth; | ||
renderer.setRenderTarget( this.postprocessing.rtTextureDepth ); | ||
renderer.clear(); | ||
renderer.render( scene, this ); // Render bokeh composite | ||
renderer.render( scene, this ); | ||
// Render bokeh composite | ||
renderer.setRenderTarget( null ); | ||
@@ -155,0 +166,0 @@ renderer.render( this.postprocessing.scene, this.postprocessing.camera ); |
( function () { | ||
const _plane = new THREE.Plane(); | ||
const _raycaster = new THREE.Raycaster(); | ||
const _pointer = new THREE.Vector2(); | ||
const _offset = new THREE.Vector3(); | ||
const _intersection = new THREE.Vector3(); | ||
const _worldPosition = new THREE.Vector3(); | ||
const _inverseMatrix = new THREE.Matrix4(); | ||
class DragControls extends THREE.EventDispatcher { | ||
@@ -26,14 +19,12 @@ | ||
_hovered = null; | ||
const _intersections = []; // | ||
const _intersections = []; | ||
// | ||
const scope = this; | ||
function activate() { | ||
_domElement.addEventListener( 'pointermove', onPointerMove ); | ||
_domElement.addEventListener( 'pointerdown', onPointerDown ); | ||
_domElement.addEventListener( 'pointerup', onPointerCancel ); | ||
_domElement.addEventListener( 'pointerleave', onPointerCancel ); | ||
@@ -46,9 +37,5 @@ | ||
_domElement.removeEventListener( 'pointermove', onPointerMove ); | ||
_domElement.removeEventListener( 'pointerdown', onPointerDown ); | ||
_domElement.removeEventListener( 'pointerup', onPointerCancel ); | ||
_domElement.removeEventListener( 'pointerleave', onPointerCancel ); | ||
_domElement.style.cursor = ''; | ||
@@ -80,5 +67,3 @@ | ||
updatePointer( event ); | ||
_raycaster.setFromCamera( _pointer, _camera ); | ||
if ( _selected ) { | ||
@@ -98,4 +83,5 @@ | ||
} // hover support | ||
} | ||
// hover support | ||
@@ -105,13 +91,8 @@ if ( event.pointerType === 'mouse' || event.pointerType === 'pen' ) { | ||
_intersections.length = 0; | ||
_raycaster.setFromCamera( _pointer, _camera ); | ||
_raycaster.intersectObjects( _objects, true, _intersections ); | ||
if ( _intersections.length > 0 ) { | ||
const object = _intersections[ 0 ].object; | ||
_plane.setFromNormalAndCoplanarPoint( _camera.getWorldDirection( _plane.normal ), _worldPosition.setFromMatrixPosition( object.matrixWorld ) ); | ||
if ( _hovered !== object && _hovered !== null ) { | ||
@@ -163,17 +144,11 @@ | ||
_intersections.length = 0; | ||
_raycaster.setFromCamera( _pointer, _camera ); | ||
_raycaster.intersectObjects( _objects, true, _intersections ); | ||
if ( _intersections.length > 0 ) { | ||
_selected = scope.transformGroup === true ? _objects[ 0 ] : _intersections[ 0 ].object; | ||
_plane.setFromNormalAndCoplanarPoint( _camera.getWorldDirection( _plane.normal ), _worldPosition.setFromMatrixPosition( _selected.matrixWorld ) ); | ||
if ( _raycaster.ray.intersectPlane( _plane, _intersection ) ) { | ||
_inverseMatrix.copy( _selected.parent.matrixWorld ).invert(); | ||
_offset.copy( _intersection ).sub( _worldPosition.setFromMatrixPosition( _selected.matrixWorld ) ); | ||
@@ -196,3 +171,2 @@ | ||
if ( scope.enabled === false ) return; | ||
if ( _selected ) { | ||
@@ -215,3 +189,2 @@ | ||
const rect = _domElement.getBoundingClientRect(); | ||
_pointer.x = ( event.clientX - rect.left ) / rect.width * 2 - 1; | ||
@@ -222,4 +195,6 @@ _pointer.y = - ( event.clientY - rect.top ) / rect.height * 2 + 1; | ||
activate(); // API | ||
activate(); | ||
// API | ||
this.enabled = true; | ||
@@ -226,0 +201,0 @@ this.transformGroup = false; |
( function () { | ||
const _lookDirection = new THREE.Vector3(); | ||
const _spherical = new THREE.Spherical(); | ||
const _target = new THREE.Vector3(); | ||
class FirstPersonControls { | ||
@@ -14,4 +11,6 @@ | ||
this.object = object; | ||
this.domElement = domElement; // API | ||
this.domElement = domElement; | ||
// API | ||
this.enabled = true; | ||
@@ -30,7 +29,9 @@ this.movementSpeed = 1.0; | ||
this.verticalMax = Math.PI; | ||
this.mouseDragOn = false; // internals | ||
this.mouseDragOn = false; | ||
// internals | ||
this.autoSpeedFactor = 0.0; | ||
this.mouseX = 0; | ||
this.mouseY = 0; | ||
this.pointerX = 0; | ||
this.pointerY = 0; | ||
this.moveForward = false; | ||
@@ -41,7 +42,11 @@ this.moveBackward = false; | ||
this.viewHalfX = 0; | ||
this.viewHalfY = 0; // private variables | ||
this.viewHalfY = 0; | ||
// private variables | ||
let lat = 0; | ||
let lon = 0; // | ||
let lon = 0; | ||
// | ||
this.handleResize = function () { | ||
@@ -63,3 +68,3 @@ | ||
this.onMouseDown = function ( event ) { | ||
this.onPointerDown = function ( event ) { | ||
@@ -79,3 +84,2 @@ if ( this.domElement !== document ) { | ||
break; | ||
case 2: | ||
@@ -93,3 +97,3 @@ this.moveBackward = true; | ||
this.onMouseUp = function ( event ) { | ||
this.onPointerUp = function ( event ) { | ||
@@ -103,3 +107,2 @@ if ( this.activeLook ) { | ||
break; | ||
case 2: | ||
@@ -117,13 +120,13 @@ this.moveBackward = false; | ||
this.onMouseMove = function ( event ) { | ||
this.onPointerMove = function ( event ) { | ||
if ( this.domElement === document ) { | ||
this.mouseX = event.pageX - this.viewHalfX; | ||
this.mouseY = event.pageY - this.viewHalfY; | ||
this.pointerX = event.pageX - this.viewHalfX; | ||
this.pointerY = event.pageY - this.viewHalfY; | ||
} else { | ||
this.mouseX = event.pageX - this.domElement.offsetLeft - this.viewHalfX; | ||
this.mouseY = event.pageY - this.domElement.offsetTop - this.viewHalfY; | ||
this.pointerX = event.pageX - this.domElement.offsetLeft - this.viewHalfX; | ||
this.pointerY = event.pageY - this.domElement.offsetTop - this.viewHalfY; | ||
@@ -142,3 +145,2 @@ } | ||
break; | ||
case 'ArrowLeft': | ||
@@ -148,3 +150,2 @@ case 'KeyA': | ||
break; | ||
case 'ArrowDown': | ||
@@ -154,3 +155,2 @@ case 'KeyS': | ||
break; | ||
case 'ArrowRight': | ||
@@ -160,7 +160,5 @@ case 'KeyD': | ||
break; | ||
case 'KeyR': | ||
this.moveUp = true; | ||
break; | ||
case 'KeyF': | ||
@@ -182,3 +180,2 @@ this.moveDown = true; | ||
break; | ||
case 'ArrowLeft': | ||
@@ -188,3 +185,2 @@ case 'KeyA': | ||
break; | ||
case 'ArrowDown': | ||
@@ -194,3 +190,2 @@ case 'KeyS': | ||
break; | ||
case 'ArrowRight': | ||
@@ -200,7 +195,5 @@ case 'KeyD': | ||
break; | ||
case 'KeyR': | ||
this.moveUp = false; | ||
break; | ||
case 'KeyF': | ||
@@ -238,3 +231,2 @@ this.moveDown = false; | ||
if ( this.enabled === false ) return; | ||
if ( this.heightSpeed ) { | ||
@@ -260,3 +252,2 @@ | ||
let actualLookSpeed = delta * this.lookSpeed; | ||
if ( ! this.activeLook ) { | ||
@@ -269,3 +260,2 @@ | ||
let verticalLookRatio = 1; | ||
if ( this.constrainVertical ) { | ||
@@ -277,8 +267,7 @@ | ||
lon -= this.mouseX * actualLookSpeed; | ||
if ( this.lookVertical ) lat -= this.mouseY * actualLookSpeed * verticalLookRatio; | ||
lon -= this.pointerX * actualLookSpeed; | ||
if ( this.lookVertical ) lat -= this.pointerY * actualLookSpeed * verticalLookRatio; | ||
lat = Math.max( - 85, Math.min( 85, lat ) ); | ||
let phi = THREE.MathUtils.degToRad( 90 - lat ); | ||
const theta = THREE.MathUtils.degToRad( lon ); | ||
if ( this.constrainVertical ) { | ||
@@ -297,9 +286,8 @@ | ||
}(); | ||
this.dispose = function () { | ||
this.domElement.removeEventListener( 'contextmenu', contextmenu ); | ||
this.domElement.removeEventListener( 'mousedown', _onMouseDown ); | ||
this.domElement.removeEventListener( 'mousemove', _onMouseMove ); | ||
this.domElement.removeEventListener( 'mouseup', _onMouseUp ); | ||
this.domElement.removeEventListener( 'pointerdown', _onPointerDown ); | ||
this.domElement.removeEventListener( 'pointermove', _onPointerMove ); | ||
this.domElement.removeEventListener( 'pointerup', _onPointerUp ); | ||
window.removeEventListener( 'keydown', _onKeyDown ); | ||
@@ -310,27 +298,18 @@ window.removeEventListener( 'keyup', _onKeyUp ); | ||
const _onMouseMove = this.onMouseMove.bind( this ); | ||
const _onMouseDown = this.onMouseDown.bind( this ); | ||
const _onMouseUp = this.onMouseUp.bind( this ); | ||
const _onPointerMove = this.onPointerMove.bind( this ); | ||
const _onPointerDown = this.onPointerDown.bind( this ); | ||
const _onPointerUp = this.onPointerUp.bind( this ); | ||
const _onKeyDown = this.onKeyDown.bind( this ); | ||
const _onKeyUp = this.onKeyUp.bind( this ); | ||
this.domElement.addEventListener( 'contextmenu', contextmenu ); | ||
this.domElement.addEventListener( 'mousemove', _onMouseMove ); | ||
this.domElement.addEventListener( 'mousedown', _onMouseDown ); | ||
this.domElement.addEventListener( 'mouseup', _onMouseUp ); | ||
this.domElement.addEventListener( 'pointerdown', _onPointerDown ); | ||
this.domElement.addEventListener( 'pointermove', _onPointerMove ); | ||
this.domElement.addEventListener( 'pointerup', _onPointerUp ); | ||
window.addEventListener( 'keydown', _onKeyDown ); | ||
window.addEventListener( 'keyup', _onKeyUp ); | ||
function setOrientation( controls ) { | ||
const quaternion = controls.object.quaternion; | ||
_lookDirection.set( 0, 0, - 1 ).applyQuaternion( quaternion ); | ||
_spherical.setFromVector3( _lookDirection ); | ||
lat = 90 - THREE.MathUtils.radToDeg( _spherical.phi ); | ||
@@ -347,3 +326,2 @@ lon = THREE.MathUtils.radToDeg( _spherical.theta ); | ||
} | ||
function contextmenu( event ) { | ||
@@ -350,0 +328,0 @@ |
@@ -6,3 +6,2 @@ ( function () { | ||
}; | ||
class FlyControls extends THREE.EventDispatcher { | ||
@@ -14,8 +13,13 @@ | ||
this.object = object; | ||
this.domElement = domElement; // API | ||
this.domElement = domElement; | ||
// API | ||
this.movementSpeed = 1.0; | ||
this.rollSpeed = 0.005; | ||
this.dragToLook = false; | ||
this.autoForward = false; // disable default target object behavior | ||
this.autoForward = false; | ||
// disable default target object behavior | ||
// internals | ||
@@ -28,3 +32,3 @@ | ||
this.tmpQuaternion = new THREE.Quaternion(); | ||
this.mouseStatus = 0; | ||
this.status = 0; | ||
this.moveState = { | ||
@@ -46,3 +50,2 @@ up: 0, | ||
this.rotationVector = new THREE.Vector3( 0, 0, 0 ); | ||
this.keydown = function ( event ) { | ||
@@ -62,47 +65,35 @@ | ||
break; | ||
case 'KeyW': | ||
this.moveState.forward = 1; | ||
break; | ||
case 'KeyS': | ||
this.moveState.back = 1; | ||
break; | ||
case 'KeyA': | ||
this.moveState.left = 1; | ||
break; | ||
case 'KeyD': | ||
this.moveState.right = 1; | ||
break; | ||
case 'KeyR': | ||
this.moveState.up = 1; | ||
break; | ||
case 'KeyF': | ||
this.moveState.down = 1; | ||
break; | ||
case 'ArrowUp': | ||
this.moveState.pitchUp = 1; | ||
break; | ||
case 'ArrowDown': | ||
this.moveState.pitchDown = 1; | ||
break; | ||
case 'ArrowLeft': | ||
this.moveState.yawLeft = 1; | ||
break; | ||
case 'ArrowRight': | ||
this.moveState.yawRight = 1; | ||
break; | ||
case 'KeyQ': | ||
this.moveState.rollLeft = 1; | ||
break; | ||
case 'KeyE': | ||
@@ -127,47 +118,35 @@ this.moveState.rollRight = 1; | ||
break; | ||
case 'KeyW': | ||
this.moveState.forward = 0; | ||
break; | ||
case 'KeyS': | ||
this.moveState.back = 0; | ||
break; | ||
case 'KeyA': | ||
this.moveState.left = 0; | ||
break; | ||
case 'KeyD': | ||
this.moveState.right = 0; | ||
break; | ||
case 'KeyR': | ||
this.moveState.up = 0; | ||
break; | ||
case 'KeyF': | ||
this.moveState.down = 0; | ||
break; | ||
case 'ArrowUp': | ||
this.moveState.pitchUp = 0; | ||
break; | ||
case 'ArrowDown': | ||
this.moveState.pitchDown = 0; | ||
break; | ||
case 'ArrowLeft': | ||
this.moveState.yawLeft = 0; | ||
break; | ||
case 'ArrowRight': | ||
this.moveState.yawRight = 0; | ||
break; | ||
case 'KeyQ': | ||
this.moveState.rollLeft = 0; | ||
break; | ||
case 'KeyE': | ||
@@ -184,7 +163,7 @@ this.moveState.rollRight = 0; | ||
this.mousedown = function ( event ) { | ||
this.pointerdown = function ( event ) { | ||
if ( this.dragToLook ) { | ||
this.mouseStatus ++; | ||
this.status ++; | ||
@@ -198,3 +177,2 @@ } else { | ||
break; | ||
case 2: | ||
@@ -212,5 +190,5 @@ this.moveState.back = 1; | ||
this.mousemove = function ( event ) { | ||
this.pointermove = function ( event ) { | ||
if ( ! this.dragToLook || this.mouseStatus > 0 ) { | ||
if ( ! this.dragToLook || this.status > 0 ) { | ||
@@ -228,7 +206,7 @@ const container = this.getContainerDimensions(); | ||
this.mouseup = function ( event ) { | ||
this.pointerup = function ( event ) { | ||
if ( this.dragToLook ) { | ||
this.mouseStatus --; | ||
this.status --; | ||
this.moveState.yawLeft = this.moveState.pitchDown = 0; | ||
@@ -243,3 +221,2 @@ | ||
break; | ||
case 2: | ||
@@ -268,3 +245,2 @@ this.moveState.back = 0; | ||
scope.object.quaternion.multiply( scope.tmpQuaternion ); | ||
if ( lastPosition.distanceToSquared( scope.object.position ) > EPS || 8 * ( 1 - lastQuaternion.dot( scope.object.quaternion ) ) > EPS ) { | ||
@@ -285,4 +261,6 @@ | ||
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.moveVector.z = - forward + this.moveState.back; | ||
//console.log( 'move:', [ this.moveVector.x, this.moveVector.y, this.moveVector.z ] ); | ||
}; | ||
@@ -294,4 +272,6 @@ | ||
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.rotationVector.z = - this.moveState.rollRight + this.moveState.rollLeft; | ||
//console.log( 'rotate:', [ this.rotationVector.x, this.rotationVector.y, this.rotationVector.z ] ); | ||
}; | ||
@@ -322,5 +302,5 @@ | ||
this.domElement.removeEventListener( 'contextmenu', contextmenu ); | ||
this.domElement.removeEventListener( 'mousedown', _mousedown ); | ||
this.domElement.removeEventListener( 'mousemove', _mousemove ); | ||
this.domElement.removeEventListener( 'mouseup', _mouseup ); | ||
this.domElement.removeEventListener( 'pointerdown', _pointerdown ); | ||
this.domElement.removeEventListener( 'pointermove', _pointermove ); | ||
this.domElement.removeEventListener( 'pointerup', _pointerup ); | ||
window.removeEventListener( 'keydown', _keydown ); | ||
@@ -331,16 +311,11 @@ window.removeEventListener( 'keyup', _keyup ); | ||
const _mousemove = this.mousemove.bind( this ); | ||
const _mousedown = this.mousedown.bind( this ); | ||
const _mouseup = this.mouseup.bind( this ); | ||
const _pointermove = this.pointermove.bind( this ); | ||
const _pointerdown = this.pointerdown.bind( this ); | ||
const _pointerup = this.pointerup.bind( this ); | ||
const _keydown = this.keydown.bind( this ); | ||
const _keyup = this.keyup.bind( this ); | ||
this.domElement.addEventListener( 'contextmenu', contextmenu ); | ||
this.domElement.addEventListener( 'mousemove', _mousemove ); | ||
this.domElement.addEventListener( 'mousedown', _mousedown ); | ||
this.domElement.addEventListener( 'mouseup', _mouseup ); | ||
this.domElement.addEventListener( 'pointerdown', _pointerdown ); | ||
this.domElement.addEventListener( 'pointermove', _pointermove ); | ||
this.domElement.addEventListener( 'pointerup', _pointerup ); | ||
window.addEventListener( 'keydown', _keydown ); | ||
@@ -354,3 +329,2 @@ window.addEventListener( 'keyup', _keyup ); | ||
} | ||
function contextmenu( event ) { | ||
@@ -357,0 +331,0 @@ |
( function () { | ||
// This set of controls performs orbiting, dollying (zooming), and panning. | ||
// Unlike TrackballControls, it maintains the "up" direction object.up (+Y by default). | ||
@@ -18,3 +19,2 @@ // | ||
}; | ||
class OrbitControls extends THREE.EventDispatcher { | ||
@@ -28,49 +28,53 @@ | ||
this.domElement.style.touchAction = 'none'; // disable touch scroll | ||
// Set to false to disable this control | ||
this.enabled = true; | ||
this.enabled = true; // "target" sets the location of focus, where the object orbits around | ||
// "target" sets the location of focus, where the object orbits around | ||
this.target = new THREE.Vector3(); | ||
this.target = new THREE.Vector3(); // How far you can dolly in and out ( PerspectiveCamera only ) | ||
// How far you can dolly in and out ( PerspectiveCamera only ) | ||
this.minDistance = 0; | ||
this.maxDistance = Infinity; // How far you can zoom in and out ( OrthographicCamera only ) | ||
this.maxDistance = Infinity; | ||
// How far you can zoom in and out ( OrthographicCamera only ) | ||
this.minZoom = 0; | ||
this.maxZoom = Infinity; // How far you can orbit vertically, upper and lower limits. | ||
this.maxZoom = Infinity; | ||
// How far you can orbit vertically, upper and lower limits. | ||
// Range is 0 to Math.PI radians. | ||
this.minPolarAngle = 0; // radians | ||
this.maxPolarAngle = Math.PI; // radians | ||
this.maxPolarAngle = Math.PI; // radians | ||
// How far you can orbit horizontally, upper and lower limits. | ||
// If set, the interval [ min, max ] must be a sub-interval of [ - 2 PI, 2 PI ], with ( max - min < 2 PI ) | ||
this.minAzimuthAngle = - Infinity; // radians | ||
this.maxAzimuthAngle = Infinity; // radians | ||
this.maxAzimuthAngle = Infinity; // radians | ||
// Set to true to enable damping (inertia) | ||
// If damping is enabled, you must call controls.update() in your animation loop | ||
this.enableDamping = false; | ||
this.dampingFactor = 0.05; | ||
this.enableDamping = false; | ||
this.dampingFactor = 0.05; // This option actually enables dollying in and out; left as "zoom" for backwards compatibility. | ||
// This option actually enables dollying in and out; left as "zoom" for backwards compatibility. | ||
// Set to false to disable zooming | ||
this.enableZoom = true; | ||
this.zoomSpeed = 1.0; // Set to false to disable rotating | ||
this.zoomSpeed = 1.0; | ||
// Set to false to disable rotating | ||
this.enableRotate = true; | ||
this.rotateSpeed = 1.0; // Set to false to disable panning | ||
this.rotateSpeed = 1.0; | ||
// Set to false to disable panning | ||
this.enablePan = true; | ||
this.panSpeed = 1.0; | ||
this.screenSpacePanning = true; // if false, pan orthogonal to world-space direction camera.up | ||
this.keyPanSpeed = 7.0; // pixels moved per arrow key push | ||
this.keyPanSpeed = 7.0; // pixels moved per arrow key push | ||
// Set to true to automatically rotate around the target | ||
// If auto-rotate is enabled, you must call controls.update() in your animation loop | ||
this.autoRotate = false; | ||
this.autoRotateSpeed = 2.0; // 30 seconds per orbit when fps is 60 | ||
// The four arrow keys | ||
this.keys = { | ||
@@ -81,4 +85,5 @@ LEFT: 'ArrowLeft', | ||
BOTTOM: 'ArrowDown' | ||
}; // Mouse buttons | ||
}; | ||
// Mouse buttons | ||
this.mouseButtons = { | ||
@@ -88,14 +93,19 @@ LEFT: THREE.MOUSE.ROTATE, | ||
RIGHT: THREE.MOUSE.PAN | ||
}; // Touch fingers | ||
}; | ||
// Touch fingers | ||
this.touches = { | ||
ONE: THREE.TOUCH.ROTATE, | ||
TWO: THREE.TOUCH.DOLLY_PAN | ||
}; // for reset | ||
}; | ||
// for reset | ||
this.target0 = this.target.clone(); | ||
this.position0 = this.object.position.clone(); | ||
this.zoom0 = this.object.zoom; // the target DOM element for key events | ||
this.zoom0 = this.object.zoom; | ||
this._domElementKeyEvents = null; // | ||
// the target DOM element for key events | ||
this._domElementKeyEvents = null; | ||
// | ||
// public methods | ||
@@ -147,9 +157,10 @@ // | ||
}; // this method is exposed, but perhaps it would be better if we can make it private... | ||
}; | ||
// this method is exposed, but perhaps it would be better if we can make it private... | ||
this.update = function () { | ||
const offset = new THREE.Vector3(); // so camera.up is the orbit axis | ||
const offset = new THREE.Vector3(); | ||
// so camera.up is the orbit axis | ||
const quat = new THREE.Quaternion().setFromUnitVectors( object.up, new THREE.Vector3( 0, 1, 0 ) ); | ||
@@ -163,8 +174,9 @@ const quatInverse = quat.clone().invert(); | ||
const position = scope.object.position; | ||
offset.copy( position ).sub( scope.target ); // rotate offset to "y-axis-is-up" space | ||
offset.copy( position ).sub( scope.target ); | ||
offset.applyQuaternion( quat ); // angle from z-axis around y-axis | ||
// rotate offset to "y-axis-is-up" space | ||
offset.applyQuaternion( quat ); | ||
// angle from z-axis around y-axis | ||
spherical.setFromVector3( offset ); | ||
if ( scope.autoRotate && state === STATE.NONE ) { | ||
@@ -186,8 +198,8 @@ | ||
} // restrict theta to be between desired limits | ||
} | ||
// restrict theta to be between desired limits | ||
let min = scope.minAzimuthAngle; | ||
let max = scope.maxAzimuthAngle; | ||
if ( isFinite( min ) && isFinite( max ) ) { | ||
@@ -197,3 +209,2 @@ | ||
if ( max < - Math.PI ) max += twoPI; else if ( max > Math.PI ) max -= twoPI; | ||
if ( min <= max ) { | ||
@@ -209,11 +220,14 @@ | ||
} // restrict phi to be between desired limits | ||
} | ||
// restrict phi to be between desired limits | ||
spherical.phi = Math.max( scope.minPolarAngle, Math.min( scope.maxPolarAngle, spherical.phi ) ); | ||
spherical.makeSafe(); | ||
spherical.radius *= scale; // restrict radius to be between desired limits | ||
spherical.radius *= scale; | ||
spherical.radius = Math.max( scope.minDistance, Math.min( scope.maxDistance, spherical.radius ) ); // move target to panned location | ||
// restrict radius to be between desired limits | ||
spherical.radius = Math.max( scope.minDistance, Math.min( scope.maxDistance, spherical.radius ) ); | ||
// move target to panned location | ||
if ( scope.enableDamping === true ) { | ||
@@ -229,8 +243,8 @@ | ||
offset.setFromSpherical( spherical ); // rotate offset back to "camera-up-vector-is-up" space | ||
offset.setFromSpherical( spherical ); | ||
// rotate offset back to "camera-up-vector-is-up" space | ||
offset.applyQuaternion( quatInverse ); | ||
position.copy( scope.target ).add( offset ); | ||
scope.object.lookAt( scope.target ); | ||
if ( scope.enableDamping === true ) { | ||
@@ -249,3 +263,5 @@ | ||
scale = 1; // update condition is: | ||
scale = 1; | ||
// update condition is: | ||
// min(camera displacement, camera rotation in radians)^2 > EPS | ||
@@ -269,3 +285,2 @@ // using small-angle approximation cos(x/2) = 1 - x^2 / 8 | ||
}(); | ||
this.dispose = function () { | ||
@@ -279,3 +294,2 @@ | ||
scope.domElement.removeEventListener( 'pointerup', onPointerUp ); | ||
if ( scope._domElementKeyEvents !== null ) { | ||
@@ -285,9 +299,12 @@ | ||
} //scope.dispatchEvent( { type: 'dispose' } ); // should this be added here? | ||
} | ||
}; // | ||
//scope.dispatchEvent( { type: 'dispose' } ); // should this be added here? | ||
}; | ||
// | ||
// internals | ||
// | ||
const scope = this; | ||
@@ -305,4 +322,5 @@ const STATE = { | ||
let state = STATE.NONE; | ||
const EPS = 0.000001; // current position in spherical coordinates | ||
const EPS = 0.000001; | ||
// current position in spherical coordinates | ||
const spherical = new THREE.Spherical(); | ||
@@ -324,3 +342,2 @@ const sphericalDelta = new THREE.Spherical(); | ||
const pointerPositions = {}; | ||
function getAutoRotationAngle() { | ||
@@ -356,3 +373,2 @@ | ||
v.setFromMatrixColumn( objectMatrix, 0 ); // get X column of objectMatrix | ||
v.multiplyScalar( - distance ); | ||
@@ -364,3 +380,2 @@ panOffset.add( v ); | ||
}(); | ||
const panUp = function () { | ||
@@ -387,5 +402,5 @@ | ||
}(); // deltaX and deltaY are in pixels; right and down are positive | ||
}(); | ||
// deltaX and deltaY are in pixels; right and down are positive | ||
const pan = function () { | ||
@@ -397,3 +412,2 @@ | ||
const element = scope.domElement; | ||
if ( scope.object.isPerspectiveCamera ) { | ||
@@ -404,6 +418,8 @@ | ||
offset.copy( position ).sub( scope.target ); | ||
let targetDistance = offset.length(); // half of the fov is center to top of screen | ||
let targetDistance = offset.length(); | ||
targetDistance *= Math.tan( scope.object.fov / 2 * Math.PI / 180.0 ); // we use only clientHeight here so aspect ratio does not distort speed | ||
// half of the fov is center to top of screen | ||
targetDistance *= Math.tan( scope.object.fov / 2 * Math.PI / 180.0 ); | ||
// we use only clientHeight here so aspect ratio does not distort speed | ||
panLeft( 2 * deltaX * targetDistance / element.clientHeight, scope.object.matrix ); | ||
@@ -429,3 +445,2 @@ panUp( 2 * deltaY * targetDistance / element.clientHeight, scope.object.matrix ); | ||
}(); | ||
function dollyOut( dollyScale ) { | ||
@@ -471,7 +486,8 @@ | ||
} // | ||
} | ||
// | ||
// event callbacks - update the object state | ||
// | ||
function handleMouseDownRotate( event ) { | ||
@@ -512,3 +528,2 @@ | ||
dollyDelta.subVectors( dollyEnd, dollyStart ); | ||
if ( dollyDelta.y > 0 ) { | ||
@@ -558,3 +573,2 @@ | ||
let needsUpdate = false; | ||
switch ( event.code ) { | ||
@@ -566,3 +580,2 @@ | ||
break; | ||
case scope.keys.BOTTOM: | ||
@@ -572,3 +585,2 @@ pan( 0, - scope.keyPanSpeed ); | ||
break; | ||
case scope.keys.LEFT: | ||
@@ -578,3 +590,2 @@ pan( scope.keyPanSpeed, 0 ); | ||
break; | ||
case scope.keys.RIGHT: | ||
@@ -722,11 +733,11 @@ pan( - scope.keyPanSpeed, 0 ); | ||
} // | ||
} | ||
// | ||
// event handlers - FSM: listen for events and reset state | ||
// | ||
function onPointerDown( event ) { | ||
if ( scope.enabled === false ) return; | ||
if ( pointers.length === 0 ) { | ||
@@ -738,7 +749,7 @@ | ||
} // | ||
} | ||
// | ||
addPointer( event ); | ||
if ( event.pointerType === 'touch' ) { | ||
@@ -759,3 +770,2 @@ | ||
if ( scope.enabled === false ) return; | ||
if ( event.pointerType === 'touch' ) { | ||
@@ -776,3 +786,2 @@ | ||
removePointer( event ); | ||
if ( pointers.length === 0 ) { | ||
@@ -800,3 +809,2 @@ | ||
let mouseAction; | ||
switch ( event.button ) { | ||
@@ -807,11 +815,8 @@ | ||
break; | ||
case 1: | ||
mouseAction = scope.mouseButtons.MIDDLE; | ||
break; | ||
case 2: | ||
mouseAction = scope.mouseButtons.RIGHT; | ||
break; | ||
default: | ||
@@ -829,3 +834,2 @@ mouseAction = - 1; | ||
break; | ||
case THREE.MOUSE.ROTATE: | ||
@@ -847,3 +851,2 @@ if ( event.ctrlKey || event.metaKey || event.shiftKey ) { | ||
break; | ||
case THREE.MOUSE.PAN: | ||
@@ -865,3 +868,2 @@ if ( event.ctrlKey || event.metaKey || event.shiftKey ) { | ||
break; | ||
default: | ||
@@ -888,3 +890,2 @@ state = STATE.NONE; | ||
break; | ||
case STATE.DOLLY: | ||
@@ -894,3 +895,2 @@ if ( scope.enableZoom === false ) return; | ||
break; | ||
case STATE.PAN: | ||
@@ -925,3 +925,2 @@ if ( scope.enablePan === false ) return; | ||
trackPointer( event ); | ||
switch ( pointers.length ) { | ||
@@ -937,3 +936,2 @@ | ||
break; | ||
case THREE.TOUCH.PAN: | ||
@@ -944,3 +942,2 @@ if ( scope.enablePan === false ) return; | ||
break; | ||
default: | ||
@@ -952,3 +949,2 @@ state = STATE.NONE; | ||
break; | ||
case 2: | ||
@@ -962,3 +958,2 @@ switch ( scope.touches.TWO ) { | ||
break; | ||
case THREE.TOUCH.DOLLY_ROTATE: | ||
@@ -969,3 +964,2 @@ if ( scope.enableZoom === false && scope.enableRotate === false ) return; | ||
break; | ||
default: | ||
@@ -977,3 +971,2 @@ state = STATE.NONE; | ||
break; | ||
default: | ||
@@ -995,3 +988,2 @@ state = STATE.NONE; | ||
trackPointer( event ); | ||
switch ( state ) { | ||
@@ -1004,3 +996,2 @@ | ||
break; | ||
case STATE.TOUCH_PAN: | ||
@@ -1011,3 +1002,2 @@ if ( scope.enablePan === false ) return; | ||
break; | ||
case STATE.TOUCH_DOLLY_PAN: | ||
@@ -1018,3 +1008,2 @@ if ( scope.enableZoom === false && scope.enablePan === false ) return; | ||
break; | ||
case STATE.TOUCH_DOLLY_ROTATE: | ||
@@ -1025,3 +1014,2 @@ if ( scope.enableZoom === false && scope.enableRotate === false ) return; | ||
break; | ||
default: | ||
@@ -1050,3 +1038,2 @@ state = STATE.NONE; | ||
delete pointerPositions[ event.pointerId ]; | ||
for ( let i = 0; i < pointers.length; i ++ ) { | ||
@@ -1068,3 +1055,2 @@ | ||
let position = pointerPositions[ event.pointerId ]; | ||
if ( position === undefined ) { | ||
@@ -1086,4 +1072,5 @@ | ||
} // | ||
} | ||
// | ||
@@ -1095,4 +1082,6 @@ scope.domElement.addEventListener( 'contextmenu', onContextMenu ); | ||
passive: false | ||
} ); // force an update at start | ||
} ); | ||
// force an update at start | ||
this.update(); | ||
@@ -1102,3 +1091,5 @@ | ||
} // This set of controls performs orbiting, dollying (zooming), and panning. | ||
} | ||
// This set of controls performs orbiting, dollying (zooming), and panning. | ||
// Unlike TrackballControls, it maintains the "up" direction object.up (+Y by default). | ||
@@ -1111,3 +1102,2 @@ // This is very similar to OrbitControls, another set of touch behavior | ||
class MapControls extends OrbitControls { | ||
@@ -1114,0 +1104,0 @@ |
( function () { | ||
const _euler = new THREE.Euler( 0, 0, 0, 'YXZ' ); | ||
const _vector = new THREE.Vector3(); | ||
const _changeEvent = { | ||
@@ -16,5 +14,3 @@ type: 'change' | ||
}; | ||
const _PI_2 = Math.PI / 2; | ||
class PointerLockControls extends THREE.EventDispatcher { | ||
@@ -26,7 +22,7 @@ | ||
this.domElement = domElement; | ||
this.isLocked = false; // Set to constrain the pitch of the camera | ||
this.isLocked = false; | ||
// Set to constrain the pitch of the camera | ||
// Range is 0 to Math.PI radians | ||
this.minPolarAngle = 0; // radians | ||
this.maxPolarAngle = Math.PI; // radians | ||
@@ -36,3 +32,2 @@ | ||
const scope = this; | ||
function onMouseMove( event ) { | ||
@@ -43,5 +38,3 @@ | ||
const movementY = event.movementY || event.mozMovementY || event.webkitMovementY || 0; | ||
_euler.setFromQuaternion( camera.quaternion ); | ||
_euler.y -= movementX * 0.002 * scope.pointerSpeed; | ||
@@ -102,2 +95,3 @@ _euler.x -= movementY * 0.002 * scope.pointerSpeed; | ||
// retaining this method for backward compatibility | ||
return camera; | ||
@@ -117,3 +111,2 @@ | ||
}(); | ||
this.moveForward = function ( distance ) { | ||
@@ -123,6 +116,5 @@ | ||
// assumes camera.up is y-up | ||
_vector.setFromMatrixColumn( camera.matrix, 0 ); | ||
_vector.crossVectors( camera.up, _vector ); | ||
camera.position.addScaledVector( _vector, distance ); | ||
@@ -135,3 +127,2 @@ | ||
_vector.setFromMatrixColumn( camera.matrix, 0 ); | ||
camera.position.addScaledVector( _vector, distance ); | ||
@@ -138,0 +129,0 @@ |
@@ -12,3 +12,2 @@ ( function () { | ||
}; | ||
class TrackballControls extends THREE.EventDispatcher { | ||
@@ -31,2 +30,3 @@ | ||
this.domElement.style.touchAction = 'none'; // disable touch scroll | ||
// API | ||
@@ -51,9 +51,4 @@ | ||
this.maxDistance = Infinity; | ||
this.keys = [ 'KeyA', | ||
/*A*/ | ||
'KeyS', | ||
/*S*/ | ||
'KeyD' | ||
/*D*/ | ||
]; | ||
this.keys = [ 'KeyA' /*A*/, 'KeyS' /*S*/, 'KeyD' /*D*/]; | ||
this.mouseButtons = { | ||
@@ -63,4 +58,6 @@ LEFT: THREE.MOUSE.ROTATE, | ||
RIGHT: THREE.MOUSE.PAN | ||
}; // internals | ||
}; | ||
// internals | ||
this.target = new THREE.Vector3(); | ||
@@ -75,3 +72,2 @@ const EPS = 0.000001; | ||
_lastAngle = 0; | ||
const _eye = new THREE.Vector3(), | ||
@@ -86,4 +82,5 @@ _movePrev = new THREE.Vector2(), | ||
_pointers = [], | ||
_pointerPositions = {}; // for reset | ||
_pointerPositions = {}; | ||
// for reset | ||
@@ -93,8 +90,10 @@ this.target0 = this.target.clone(); | ||
this.up0 = this.object.up.clone(); | ||
this.zoom0 = this.object.zoom; // methods | ||
this.zoom0 = this.object.zoom; | ||
// methods | ||
this.handleResize = function () { | ||
const box = scope.domElement.getBoundingClientRect(); // adjustments come from similar code in the jquery offset() function | ||
const box = scope.domElement.getBoundingClientRect(); | ||
// adjustments come from similar code in the jquery offset() function | ||
const d = scope.domElement.ownerDocument.documentElement; | ||
@@ -119,3 +118,2 @@ scope.screen.left = box.left + window.pageXOffset - d.clientLeft; | ||
}(); | ||
const getMouseOnCircle = function () { | ||
@@ -128,2 +126,3 @@ | ||
); | ||
return vector; | ||
@@ -134,3 +133,2 @@ | ||
}(); | ||
this.rotateCamera = function () { | ||
@@ -148,7 +146,5 @@ | ||
let angle = moveDirection.length(); | ||
if ( angle ) { | ||
_eye.copy( scope.object.position ).sub( scope.target ); | ||
eyeDirection.copy( _eye ).normalize(); | ||
@@ -163,9 +159,5 @@ objectUpDirection.copy( scope.object.up ).normalize(); | ||
quaternion.setFromAxisAngle( axis, angle ); | ||
_eye.applyQuaternion( quaternion ); | ||
scope.object.up.applyQuaternion( quaternion ); | ||
_lastAxis.copy( axis ); | ||
_lastAngle = angle; | ||
@@ -176,9 +168,5 @@ | ||
_lastAngle *= Math.sqrt( 1.0 - scope.dynamicDampingFactor ); | ||
_eye.copy( scope.object.position ).sub( scope.target ); | ||
quaternion.setFromAxisAngle( _lastAxis, _lastAngle ); | ||
_eye.applyQuaternion( quaternion ); | ||
scope.object.up.applyQuaternion( quaternion ); | ||
@@ -193,7 +181,5 @@ | ||
}(); | ||
this.zoomCamera = function () { | ||
let factor; | ||
if ( _state === STATE.TOUCH_ZOOM_PAN ) { | ||
@@ -203,3 +189,2 @@ | ||
_touchZoomDistanceStart = _touchZoomDistanceEnd; | ||
if ( scope.object.isPerspectiveCamera ) { | ||
@@ -223,3 +208,2 @@ | ||
factor = 1.0 + ( _zoomEnd.y - _zoomStart.y ) * scope.zoomSpeed; | ||
if ( factor !== 1.0 && factor > 0.0 ) { | ||
@@ -266,3 +250,2 @@ | ||
mouseChange.copy( _panEnd ).sub( _panStart ); | ||
if ( mouseChange.lengthSq() ) { | ||
@@ -284,3 +267,2 @@ | ||
scope.target.add( pan ); | ||
if ( scope.staticMoving ) { | ||
@@ -301,3 +283,2 @@ | ||
}(); | ||
this.checkDistances = function () { | ||
@@ -310,3 +291,2 @@ | ||
scope.object.position.addVectors( scope.target, _eye.setLength( scope.maxDistance ) ); | ||
_zoomStart.copy( _zoomEnd ); | ||
@@ -319,3 +299,2 @@ | ||
scope.object.position.addVectors( scope.target, _eye.setLength( scope.minDistance ) ); | ||
_zoomStart.copy( _zoomEnd ); | ||
@@ -332,3 +311,2 @@ | ||
_eye.subVectors( scope.object.position, scope.target ); | ||
if ( ! scope.noRotate ) { | ||
@@ -353,3 +331,2 @@ | ||
scope.object.position.addVectors( scope.target, _eye ); | ||
if ( scope.object.isPerspectiveCamera ) { | ||
@@ -359,3 +336,2 @@ | ||
scope.object.lookAt( scope.target ); | ||
if ( lastPosition.distanceToSquared( scope.object.position ) > EPS ) { | ||
@@ -371,3 +347,2 @@ | ||
scope.object.lookAt( scope.target ); | ||
if ( lastPosition.distanceToSquared( scope.object.position ) > EPS || lastZoom !== scope.object.zoom ) { | ||
@@ -398,5 +373,3 @@ | ||
scope.object.updateProjectionMatrix(); | ||
_eye.subVectors( scope.object.position, scope.target ); | ||
scope.object.lookAt( scope.target ); | ||
@@ -407,4 +380,5 @@ scope.dispatchEvent( _changeEvent ); | ||
}; // listeners | ||
}; | ||
// listeners | ||
@@ -414,3 +388,2 @@ function onPointerDown( event ) { | ||
if ( scope.enabled === false ) return; | ||
if ( _pointers.length === 0 ) { | ||
@@ -422,7 +395,7 @@ | ||
} // | ||
} | ||
// | ||
addPointer( event ); | ||
if ( event.pointerType === 'touch' ) { | ||
@@ -443,3 +416,2 @@ | ||
if ( scope.enabled === false ) return; | ||
if ( event.pointerType === 'touch' ) { | ||
@@ -460,3 +432,2 @@ | ||
if ( scope.enabled === false ) return; | ||
if ( event.pointerType === 'touch' ) { | ||
@@ -470,7 +441,7 @@ | ||
} // | ||
} | ||
// | ||
removePointer( event ); | ||
if ( _pointers.length === 0 ) { | ||
@@ -496,3 +467,2 @@ | ||
window.removeEventListener( 'keydown', keydown ); | ||
if ( _keyState !== STATE.NONE ) { | ||
@@ -535,7 +505,5 @@ | ||
break; | ||
case scope.mouseButtons.MIDDLE: | ||
_state = STATE.ZOOM; | ||
break; | ||
case scope.mouseButtons.RIGHT: | ||
@@ -550,7 +518,5 @@ _state = STATE.PAN; | ||
const state = _keyState !== STATE.NONE ? _keyState : _state; | ||
if ( state === STATE.ROTATE && ! scope.noRotate ) { | ||
_moveCurr.copy( getMouseOnCircle( event.pageX, event.pageY ) ); | ||
_movePrev.copy( _moveCurr ); | ||
@@ -561,3 +527,2 @@ | ||
_zoomStart.copy( getMouseOnScreen( event.pageX, event.pageY ) ); | ||
_zoomEnd.copy( _zoomStart ); | ||
@@ -568,3 +533,2 @@ | ||
_panStart.copy( getMouseOnScreen( event.pageX, event.pageY ) ); | ||
_panEnd.copy( _panStart ); | ||
@@ -581,7 +545,5 @@ | ||
const state = _keyState !== STATE.NONE ? _keyState : _state; | ||
if ( state === STATE.ROTATE && ! scope.noRotate ) { | ||
_movePrev.copy( _moveCurr ); | ||
_moveCurr.copy( getMouseOnCircle( event.pageX, event.pageY ) ); | ||
@@ -613,3 +575,2 @@ | ||
event.preventDefault(); | ||
switch ( event.deltaMode ) { | ||
@@ -621,3 +582,2 @@ | ||
break; | ||
case 1: | ||
@@ -627,3 +587,2 @@ // Zoom in lines | ||
break; | ||
default: | ||
@@ -644,3 +603,2 @@ // undefined, 0, assume pixels | ||
trackPointer( event ); | ||
switch ( _pointers.length ) { | ||
@@ -650,9 +608,5 @@ | ||
_state = STATE.TOUCH_ROTATE; | ||
_moveCurr.copy( getMouseOnCircle( _pointers[ 0 ].pageX, _pointers[ 0 ].pageY ) ); | ||
_movePrev.copy( _moveCurr ); | ||
break; | ||
default: | ||
@@ -666,7 +620,4 @@ // 2 or more | ||
const y = ( _pointers[ 0 ].pageY + _pointers[ 1 ].pageY ) / 2; | ||
_panStart.copy( getMouseOnScreen( x, y ) ); | ||
_panEnd.copy( _panStart ); | ||
break; | ||
@@ -683,3 +634,2 @@ | ||
trackPointer( event ); | ||
switch ( _pointers.length ) { | ||
@@ -689,9 +639,7 @@ | ||
_movePrev.copy( _moveCurr ); | ||
_moveCurr.copy( getMouseOnCircle( event.pageX, event.pageY ) ); | ||
break; | ||
default: | ||
// 2 or more | ||
const position = getSecondPointerPosition( event ); | ||
@@ -703,5 +651,3 @@ const dx = event.pageX - position.x; | ||
const y = ( event.pageY + position.y ) / 2; | ||
_panEnd.copy( getMouseOnScreen( x, y ) ); | ||
break; | ||
@@ -720,19 +666,22 @@ | ||
break; | ||
case 1: | ||
_state = STATE.TOUCH_ROTATE; | ||
_moveCurr.copy( getMouseOnCircle( event.pageX, event.pageY ) ); | ||
_movePrev.copy( _moveCurr ); | ||
break; | ||
case 2: | ||
_state = STATE.TOUCH_ZOOM_PAN; | ||
for ( let i = 0; i < _pointers.length; i ++ ) { | ||
_moveCurr.copy( getMouseOnCircle( event.pageX - _movePrev.x, event.pageY - _movePrev.y ) ); | ||
if ( _pointers[ i ].pointerId !== event.pointerId ) { | ||
_movePrev.copy( _moveCurr ); | ||
const position = _pointerPositions[ _pointers[ i ].pointerId ]; | ||
_moveCurr.copy( getMouseOnCircle( position.x, position.y ) ); | ||
_movePrev.copy( _moveCurr ); | ||
break; | ||
} | ||
} | ||
break; | ||
@@ -762,3 +711,2 @@ | ||
delete _pointerPositions[ event.pointerId ]; | ||
for ( let i = 0; i < _pointers.length; i ++ ) { | ||
@@ -769,3 +717,2 @@ | ||
_pointers.splice( i, 1 ); | ||
return; | ||
@@ -782,3 +729,2 @@ | ||
let position = _pointerPositions[ event.pointerId ]; | ||
if ( position === undefined ) { | ||
@@ -823,4 +769,5 @@ | ||
window.addEventListener( 'keyup', keyup ); | ||
this.handleResize(); // force an update at start | ||
this.handleResize(); | ||
// force an update at start | ||
this.update(); | ||
@@ -827,0 +774,0 @@ |
( function () { | ||
const _raycaster = new THREE.Raycaster(); | ||
const _tempVector = new THREE.Vector3(); | ||
const _tempVector2 = new THREE.Vector3(); | ||
const _tempQuaternion = new THREE.Quaternion(); | ||
const _unit = { | ||
@@ -29,3 +25,2 @@ X: new THREE.Vector3( 1, 0, 0 ), | ||
}; | ||
class TransformControls extends THREE.Object3D { | ||
@@ -36,3 +31,2 @@ | ||
super(); | ||
if ( domElement === undefined ) { | ||
@@ -51,12 +45,10 @@ | ||
const _gizmo = new TransformControlsGizmo(); | ||
this._gizmo = _gizmo; | ||
this.add( _gizmo ); | ||
const _plane = new TransformControlsPlane(); | ||
this._plane = _plane; | ||
this.add( _plane ); | ||
const scope = this; // Defined getter, setter and store for a property | ||
const scope = this; | ||
// Defined getter, setter and store for a property | ||
function defineProperty( propName, defaultValue ) { | ||
@@ -92,7 +84,8 @@ | ||
} // Define properties with getters/setter | ||
} | ||
// Define properties with getters/setter | ||
// Setting the defined property will automatically trigger change event | ||
// Defined properties are passed down to gizmo and plane | ||
defineProperty( 'camera', camera ); | ||
@@ -111,4 +104,6 @@ defineProperty( 'object', undefined ); | ||
defineProperty( 'showY', true ); | ||
defineProperty( 'showZ', true ); // Reusable utility variables | ||
defineProperty( 'showZ', true ); | ||
// Reusable utility variables | ||
const worldPosition = new THREE.Vector3(); | ||
@@ -124,4 +119,6 @@ const worldPositionStart = new THREE.Vector3(); | ||
const rotationAngle = 0; | ||
const eye = new THREE.Vector3(); // TODO: remove properties unused in plane and gizmo | ||
const eye = new THREE.Vector3(); | ||
// TODO: remove properties unused in plane and gizmo | ||
defineProperty( 'worldPosition', worldPosition ); | ||
@@ -161,5 +158,5 @@ defineProperty( 'worldPositionStart', worldPositionStart ); | ||
} // updateMatrixWorld updates key transformation variables | ||
} | ||
// updateMatrixWorld updates key transformation variables | ||
updateMatrixWorld() { | ||
@@ -170,3 +167,2 @@ | ||
this.object.updateMatrixWorld(); | ||
if ( this.object.parent === null ) { | ||
@@ -183,5 +179,3 @@ | ||
this.object.matrixWorld.decompose( this.worldPosition, this.worldQuaternion, this._worldScale ); | ||
this._parentQuaternionInv.copy( this._parentQuaternion ).invert(); | ||
this._worldQuaternionInv.copy( this.worldQuaternion ).invert(); | ||
@@ -193,3 +187,2 @@ | ||
this.camera.matrixWorld.decompose( this.cameraPosition, this.cameraQuaternion, this._cameraScale ); | ||
if ( this.camera.isOrthographicCamera ) { | ||
@@ -208,11 +201,7 @@ | ||
} | ||
pointerHover( pointer ) { | ||
if ( this.object === undefined || this.dragging === true ) return; | ||
_raycaster.setFromCamera( pointer, this.camera ); | ||
const intersect = intersectObjectWithRay( this._gizmo.picker[ this.mode ], _raycaster ); | ||
if ( intersect ) { | ||
@@ -229,13 +218,9 @@ | ||
} | ||
pointerDown( pointer ) { | ||
if ( this.object === undefined || this.dragging === true || pointer.button !== 0 ) return; | ||
if ( this.axis !== null ) { | ||
_raycaster.setFromCamera( pointer, this.camera ); | ||
const planeIntersect = intersectObjectWithRay( this._plane, _raycaster, true ); | ||
if ( planeIntersect ) { | ||
@@ -245,9 +230,5 @@ | ||
this.object.parent.updateMatrixWorld(); | ||
this._positionStart.copy( this.object.position ); | ||
this._quaternionStart.copy( this.object.quaternion ); | ||
this._scaleStart.copy( this.object.scale ); | ||
this.object.matrixWorld.decompose( this.worldPositionStart, this.worldQuaternionStart, this._worldScaleStart ); | ||
@@ -265,3 +246,2 @@ this.pointStart.copy( planeIntersect.point ).sub( this.worldPositionStart ); | ||
} | ||
pointerMove( pointer ) { | ||
@@ -273,3 +253,2 @@ | ||
let space = this.space; | ||
if ( mode === 'scale' ) { | ||
@@ -286,14 +265,11 @@ | ||
if ( object === undefined || axis === null || this.dragging === false || pointer.button !== - 1 ) return; | ||
_raycaster.setFromCamera( pointer, this.camera ); | ||
const planeIntersect = intersectObjectWithRay( this._plane, _raycaster, true ); | ||
if ( ! planeIntersect ) return; | ||
this.pointEnd.copy( planeIntersect.point ).sub( this.worldPositionStart ); | ||
if ( mode === 'translate' ) { | ||
// Apply translate | ||
this._offset.copy( this.pointEnd ).sub( this.pointStart ); | ||
if ( space === 'local' && axis !== 'XYZ' ) { | ||
@@ -308,3 +284,2 @@ | ||
if ( axis.indexOf( 'Z' ) === - 1 ) this._offset.z = 0; | ||
if ( space === 'local' && axis !== 'XYZ' ) { | ||
@@ -320,4 +295,6 @@ | ||
object.position.copy( this._offset ).add( this._positionStart ); // Apply translation snap | ||
object.position.copy( this._offset ).add( this._positionStart ); | ||
// Apply translation snap | ||
if ( this.translationSnap ) { | ||
@@ -328,3 +305,2 @@ | ||
object.position.applyQuaternion( _tempQuaternion.copy( this._quaternionStart ).invert() ); | ||
if ( axis.search( 'X' ) !== - 1 ) { | ||
@@ -394,3 +370,2 @@ | ||
if ( this.pointEnd.dot( this.pointStart ) < 0 ) d *= - 1; | ||
_tempVector2.set( d, d, d ); | ||
@@ -401,11 +376,6 @@ | ||
_tempVector.copy( this.pointStart ); | ||
_tempVector2.copy( this.pointEnd ); | ||
_tempVector.applyQuaternion( this._worldQuaternionInv ); | ||
_tempVector2.applyQuaternion( this._worldQuaternionInv ); | ||
_tempVector2.divide( _tempVector ); | ||
if ( axis.search( 'X' ) === - 1 ) { | ||
@@ -429,7 +399,7 @@ | ||
} // Apply scale | ||
} | ||
// Apply scale | ||
object.scale.copy( this._scaleStart ).multiply( _tempVector2 ); | ||
if ( this.scaleSnap ) { | ||
@@ -460,5 +430,3 @@ | ||
this._offset.copy( this.pointEnd ).sub( this.pointStart ); | ||
const ROTATION_SPEED = 20 / this.worldPosition.distanceTo( _tempVector.setFromMatrixPosition( this.camera.matrixWorld ) ); | ||
if ( axis === 'E' ) { | ||
@@ -468,7 +436,4 @@ | ||
this.rotationAngle = this.pointEnd.angleTo( this.pointStart ); | ||
this._startNorm.copy( this.pointStart ).normalize(); | ||
this._endNorm.copy( this.pointEnd ).normalize(); | ||
this.rotationAngle *= this._endNorm.cross( this._startNorm ).dot( this.eye ) < 0 ? 1 : - 1; | ||
@@ -484,5 +449,3 @@ | ||
this.rotationAxis.copy( _unit[ axis ] ); | ||
_tempVector.copy( _unit[ axis ] ); | ||
if ( space === 'local' ) { | ||
@@ -496,7 +459,9 @@ | ||
} // Apply rotation snap | ||
} | ||
// Apply rotation snap | ||
if ( this.rotationSnap ) this.rotationAngle = Math.round( this.rotationAngle / this.rotationSnap ) * this.rotationSnap; // Apply rotate | ||
if ( this.rotationSnap ) this.rotationAngle = Math.round( this.rotationAngle / this.rotationSnap ) * this.rotationSnap; | ||
// Apply rotate | ||
if ( space === 'local' && axis !== 'E' && axis !== 'XYZE' ) { | ||
@@ -521,7 +486,5 @@ | ||
} | ||
pointerUp( pointer ) { | ||
if ( pointer.button !== 0 ) return; | ||
if ( this.dragging && this.axis !== null ) { | ||
@@ -538,3 +501,2 @@ | ||
} | ||
dispose() { | ||
@@ -553,5 +515,5 @@ | ||
} // Set current object | ||
} | ||
// Set current object | ||
attach( object ) { | ||
@@ -563,5 +525,5 @@ | ||
} // Detach from object | ||
} | ||
// Detach from object | ||
detach() { | ||
@@ -575,7 +537,5 @@ | ||
} | ||
reset() { | ||
if ( ! this.enabled ) return; | ||
if ( this.dragging ) { | ||
@@ -593,3 +553,2 @@ | ||
} | ||
getRaycaster() { | ||
@@ -599,4 +558,5 @@ | ||
} // TODO: deprecate | ||
} | ||
// TODO: deprecate | ||
@@ -608,3 +568,2 @@ getMode() { | ||
} | ||
setMode( mode ) { | ||
@@ -615,3 +574,2 @@ | ||
} | ||
setTranslationSnap( translationSnap ) { | ||
@@ -622,3 +580,2 @@ | ||
} | ||
setRotationSnap( rotationSnap ) { | ||
@@ -629,3 +586,2 @@ | ||
} | ||
setScaleSnap( scaleSnap ) { | ||
@@ -636,3 +592,2 @@ | ||
} | ||
setSize( size ) { | ||
@@ -643,3 +598,2 @@ | ||
} | ||
setSpace( space ) { | ||
@@ -651,4 +605,5 @@ | ||
} // mouse / touch event handlers | ||
} | ||
// mouse / touch event handlers | ||
@@ -681,3 +636,2 @@ function getPointer( event ) { | ||
if ( ! this.enabled ) return; | ||
switch ( event.pointerType ) { | ||
@@ -697,3 +651,2 @@ | ||
if ( ! this.enabled ) return; | ||
if ( ! document.pointerLockElement ) { | ||
@@ -730,3 +683,2 @@ | ||
const allIntersections = raycaster.intersectObject( object, true ); | ||
for ( let i = 0; i < allIntersections.length; i ++ ) { | ||
@@ -744,34 +696,22 @@ | ||
} // | ||
} | ||
// | ||
// Reusable utility variables | ||
const _tempEuler = new THREE.Euler(); | ||
const _alignVector = new THREE.Vector3( 0, 1, 0 ); | ||
const _zeroVector = new THREE.Vector3( 0, 0, 0 ); | ||
const _lookAtMatrix = new THREE.Matrix4(); | ||
const _tempQuaternion2 = new THREE.Quaternion(); | ||
const _identityQuaternion = new THREE.Quaternion(); | ||
const _dirVector = new THREE.Vector3(); | ||
const _tempMatrix = new THREE.Matrix4(); | ||
const _unitX = new THREE.Vector3( 1, 0, 0 ); | ||
const _unitY = new THREE.Vector3( 0, 1, 0 ); | ||
const _unitZ = new THREE.Vector3( 0, 0, 1 ); | ||
const _v1 = new THREE.Vector3(); | ||
const _v2 = new THREE.Vector3(); | ||
const _v3 = new THREE.Vector3(); | ||
class TransformControlsGizmo extends THREE.Object3D { | ||
@@ -783,4 +723,6 @@ | ||
this.isTransformControlsGizmo = true; | ||
this.type = 'TransformControlsGizmo'; // shared materials | ||
this.type = 'TransformControlsGizmo'; | ||
// shared materials | ||
const gizmoMaterial = new THREE.MeshBasicMaterial( { | ||
@@ -799,4 +741,6 @@ depthTest: false, | ||
transparent: true | ||
} ); // Make unique material for each axis/color | ||
} ); | ||
// Make unique material for each axis/color | ||
const matInvisible = gizmoMaterial.clone(); | ||
@@ -829,4 +773,6 @@ matInvisible.opacity = 0.15; | ||
const matGray = gizmoMaterial.clone(); | ||
matGray.color.setHex( 0x787878 ); // reusable geometry | ||
matGray.color.setHex( 0x787878 ); | ||
// reusable geometry | ||
const arrowGeometry = new THREE.CylinderGeometry( 0, 0.04, 0.1, 12 ); | ||
@@ -840,3 +786,2 @@ arrowGeometry.translate( 0, 0.05, 0 ); | ||
lineGeometry2.translate( 0, 0.25, 0 ); | ||
function CircleGeometry( radius, arc ) { | ||
@@ -849,4 +794,5 @@ | ||
} // Special geometry for transform helper. If scaled with position vector it spans from [0,0,0] to position | ||
} | ||
// Special geometry for transform helper. If scaled with position vector it spans from [0,0,0] to position | ||
@@ -859,4 +805,5 @@ function TranslateHelperGeometry() { | ||
} // Gizmo definitions - custom hierarchy definitions for setupGizmo() function | ||
} | ||
// Gizmo definitions - custom hierarchy definitions for setupGizmo() function | ||
@@ -928,8 +875,9 @@ const gizmoTranslate = { | ||
Z: [[ new THREE.Line( lineGeometry, matHelper.clone() ), [ 0, 0, - 1e3 ], [ 0, - Math.PI / 2, 0 ], [ 1e6, 1, 1 ], 'helper' ]] | ||
}; // Creates an THREE.Object3D with gizmos described in custom hierarchy definition. | ||
}; | ||
// Creates an THREE.Object3D with gizmos described in custom hierarchy definition. | ||
function setupGizmo( gizmoMap ) { | ||
const gizmo = new THREE.Object3D(); | ||
for ( const name in gizmoMap ) { | ||
@@ -943,7 +891,7 @@ | ||
const scale = gizmoMap[ name ][ i ][ 3 ]; | ||
const tag = gizmoMap[ name ][ i ][ 4 ]; // name and tag properties are essential for picking and updating logic. | ||
const tag = gizmoMap[ name ][ i ][ 4 ]; | ||
// name and tag properties are essential for picking and updating logic. | ||
object.name = name; | ||
object.tag = tag; | ||
if ( position ) { | ||
@@ -983,4 +931,5 @@ | ||
} // Gizmo creation | ||
} | ||
// Gizmo creation | ||
@@ -998,4 +947,6 @@ this.gizmo = {}; | ||
this.add( this.helper[ 'rotate' ] = setupGizmo( helperRotate ) ); | ||
this.add( this.helper[ 'scale' ] = setupGizmo( helperScale ) ); // Pickers should be hidden always | ||
this.add( this.helper[ 'scale' ] = setupGizmo( helperScale ) ); | ||
// Pickers should be hidden always | ||
this.picker[ 'translate' ].visible = false; | ||
@@ -1005,4 +956,5 @@ this.picker[ 'rotate' ].visible = false; | ||
} // updateMatrixWorld will update transformations and appearance of individual handles | ||
} | ||
// updateMatrixWorld will update transformations and appearance of individual handles | ||
@@ -1013,4 +965,6 @@ updateMatrixWorld( force ) { | ||
const quaternion = space === 'local' ? this.worldQuaternion : _identityQuaternion; // Show only gizmos for current transform mode | ||
const quaternion = space === 'local' ? this.worldQuaternion : _identityQuaternion; | ||
// Show only gizmos for current transform mode | ||
this.gizmo[ 'translate' ].visible = this.mode === 'translate'; | ||
@@ -1026,7 +980,8 @@ this.gizmo[ 'rotate' ].visible = this.mode === 'rotate'; | ||
handles = handles.concat( this.helper[ this.mode ].children ); | ||
for ( let i = 0; i < handles.length; i ++ ) { | ||
const handle = handles[ i ]; // hide aligned to camera | ||
const handle = handles[ i ]; | ||
// hide aligned to camera | ||
handle.visible = true; | ||
@@ -1036,3 +991,2 @@ handle.rotation.set( 0, 0, 0 ); | ||
let factor; | ||
if ( this.camera.isOrthographicCamera ) { | ||
@@ -1048,8 +1002,9 @@ | ||
handle.scale.set( 1, 1, 1 ).multiplyScalar( factor * this.size / 4 ); // TODO: simplify helpers and consider decoupling from gizmo | ||
handle.scale.set( 1, 1, 1 ).multiplyScalar( factor * this.size / 4 ); | ||
// TODO: simplify helpers and consider decoupling from gizmo | ||
if ( handle.tag === 'helper' ) { | ||
handle.visible = false; | ||
if ( handle.name === 'AXIS' ) { | ||
@@ -1059,9 +1014,6 @@ | ||
handle.visible = !! this.axis; | ||
if ( this.axis === 'X' ) { | ||
_tempQuaternion.setFromEuler( _tempEuler.set( 0, 0, 0 ) ); | ||
handle.quaternion.copy( quaternion ).multiply( _tempQuaternion ); | ||
if ( Math.abs( _alignVector.copy( _unitX ).applyQuaternion( quaternion ).dot( this.eye ) ) > 0.9 ) { | ||
@@ -1078,5 +1030,3 @@ | ||
_tempQuaternion.setFromEuler( _tempEuler.set( 0, 0, Math.PI / 2 ) ); | ||
handle.quaternion.copy( quaternion ).multiply( _tempQuaternion ); | ||
if ( Math.abs( _alignVector.copy( _unitY ).applyQuaternion( quaternion ).dot( this.eye ) ) > 0.9 ) { | ||
@@ -1093,5 +1043,3 @@ | ||
_tempQuaternion.setFromEuler( _tempEuler.set( 0, Math.PI / 2, 0 ) ); | ||
handle.quaternion.copy( quaternion ).multiply( _tempQuaternion ); | ||
if ( Math.abs( _alignVector.copy( _unitZ ).applyQuaternion( quaternion ).dot( this.eye ) ) > 0.9 ) { | ||
@@ -1108,5 +1056,3 @@ | ||
_tempQuaternion.setFromEuler( _tempEuler.set( 0, Math.PI / 2, 0 ) ); | ||
_alignVector.copy( this.rotationAxis ); | ||
handle.quaternion.setFromRotationMatrix( _lookAtMatrix.lookAt( _zeroVector, _alignVector, _unitY ) ); | ||
@@ -1138,7 +1084,4 @@ handle.quaternion.multiply( _tempQuaternion ); | ||
handle.quaternion.copy( this.worldQuaternionStart ); | ||
_tempVector.set( 1e-10, 1e-10, 1e-10 ).add( this.worldPositionStart ).sub( this.worldPosition ).multiplyScalar( - 1 ); | ||
_tempVector.applyQuaternion( this.worldQuaternionStart.clone().invert() ); | ||
handle.scale.copy( _tempVector ); | ||
@@ -1150,3 +1093,2 @@ handle.visible = this.dragging; | ||
handle.quaternion.copy( quaternion ); | ||
if ( this.dragging ) { | ||
@@ -1168,18 +1110,18 @@ | ||
} // If updating helper, skip rest of the loop | ||
} | ||
// If updating helper, skip rest of the loop | ||
continue; | ||
} // Align handles to current local or world rotation | ||
} | ||
// Align handles to current local or world rotation | ||
handle.quaternion.copy( quaternion ); | ||
if ( this.mode === 'translate' || this.mode === 'scale' ) { | ||
// Hide translate and scale axis facing the camera | ||
const AXIS_HIDE_THRESHOLD = 0.99; | ||
const PLANE_HIDE_THRESHOLD = 0.2; | ||
if ( handle.name === 'X' ) { | ||
@@ -1254,6 +1196,5 @@ | ||
// Align handles to current local or world rotation | ||
_tempQuaternion2.copy( quaternion ); | ||
_alignVector.copy( this.eye ).applyQuaternion( _tempQuaternion.copy( quaternion ).invert() ); | ||
if ( handle.name.search( 'E' ) !== - 1 ) { | ||
@@ -1268,5 +1209,3 @@ | ||
_tempQuaternion.setFromAxisAngle( _unitX, Math.atan2( - _alignVector.y, _alignVector.z ) ); | ||
_tempQuaternion.multiplyQuaternions( _tempQuaternion2, _tempQuaternion ); | ||
handle.quaternion.copy( _tempQuaternion ); | ||
@@ -1279,5 +1218,3 @@ | ||
_tempQuaternion.setFromAxisAngle( _unitY, Math.atan2( _alignVector.x, _alignVector.z ) ); | ||
_tempQuaternion.multiplyQuaternions( _tempQuaternion2, _tempQuaternion ); | ||
handle.quaternion.copy( _tempQuaternion ); | ||
@@ -1290,5 +1227,3 @@ | ||
_tempQuaternion.setFromAxisAngle( _unitZ, Math.atan2( _alignVector.y, _alignVector.x ) ); | ||
_tempQuaternion.multiplyQuaternions( _tempQuaternion2, _tempQuaternion ); | ||
handle.quaternion.copy( _tempQuaternion ); | ||
@@ -1298,10 +1233,12 @@ | ||
} // Hide disabled axes | ||
} | ||
// Hide disabled axes | ||
handle.visible = handle.visible && ( handle.name.indexOf( 'X' ) === - 1 || this.showX ); | ||
handle.visible = handle.visible && ( handle.name.indexOf( 'Y' ) === - 1 || this.showY ); | ||
handle.visible = handle.visible && ( handle.name.indexOf( 'Z' ) === - 1 || this.showZ ); | ||
handle.visible = handle.visible && ( handle.name.indexOf( 'E' ) === - 1 || this.showX && this.showY && this.showZ ); // highlight selected axis | ||
handle.visible = handle.visible && ( handle.name.indexOf( 'E' ) === - 1 || this.showX && this.showY && this.showZ ); | ||
// highlight selected axis | ||
handle.material._color = handle.material._color || handle.material.color.clone(); | ||
@@ -1311,3 +1248,2 @@ handle.material._opacity = handle.material._opacity || handle.material.opacity; | ||
handle.material.opacity = handle.material._opacity; | ||
if ( this.enabled && this.axis ) { | ||
@@ -1339,4 +1275,5 @@ | ||
} // | ||
} | ||
// | ||
@@ -1359,3 +1296,2 @@ class TransformControlsPlane extends THREE.Mesh { | ||
} | ||
updateMatrixWorld( force ) { | ||
@@ -1368,10 +1304,8 @@ | ||
_v1.copy( _unitX ).applyQuaternion( space === 'local' ? this.worldQuaternion : _identityQuaternion ); | ||
_v2.copy( _unitY ).applyQuaternion( space === 'local' ? this.worldQuaternion : _identityQuaternion ); | ||
_v3.copy( _unitZ ).applyQuaternion( space === 'local' ? this.worldQuaternion : _identityQuaternion ); | ||
_v3.copy( _unitZ ).applyQuaternion( space === 'local' ? this.worldQuaternion : _identityQuaternion ); // Align the plane for current transform mode, axis and space. | ||
// Align the plane for current transform mode, axis and space. | ||
_alignVector.copy( _v2 ); | ||
switch ( this.mode ) { | ||
@@ -1385,42 +1319,25 @@ | ||
_alignVector.copy( this.eye ).cross( _v1 ); | ||
_dirVector.copy( _v1 ).cross( _alignVector ); | ||
break; | ||
case 'Y': | ||
_alignVector.copy( this.eye ).cross( _v2 ); | ||
_dirVector.copy( _v2 ).cross( _alignVector ); | ||
break; | ||
case 'Z': | ||
_alignVector.copy( this.eye ).cross( _v3 ); | ||
_dirVector.copy( _v3 ).cross( _alignVector ); | ||
break; | ||
case 'XY': | ||
_dirVector.copy( _v3 ); | ||
break; | ||
case 'YZ': | ||
_dirVector.copy( _v1 ); | ||
break; | ||
case 'XZ': | ||
_alignVector.copy( _v3 ); | ||
_dirVector.copy( _v2 ); | ||
break; | ||
case 'XYZ': | ||
case 'E': | ||
_dirVector.set( 0, 0, 0 ); | ||
break; | ||
@@ -1431,3 +1348,2 @@ | ||
break; | ||
case 'rotate': | ||
@@ -1448,3 +1364,2 @@ default: | ||
_tempMatrix.lookAt( _tempVector.set( 0, 0, 0 ), _dirVector, _alignVector ); | ||
this.quaternion.setFromRotationMatrix( _tempMatrix ); | ||
@@ -1451,0 +1366,0 @@ |
( function () { | ||
const _cameraToLightMatrix = new THREE.Matrix4(); | ||
const _lightSpaceFrustum = new THREE.CSMFrustum(); | ||
const _center = new THREE.Vector3(); | ||
const _bbox = new THREE.Box3(); | ||
const _uniformArray = []; | ||
@@ -42,3 +38,2 @@ const _logArray = []; | ||
} | ||
createLights() { | ||
@@ -62,3 +57,2 @@ | ||
} | ||
initCascades() { | ||
@@ -72,7 +66,5 @@ | ||
} | ||
updateShadowBounds() { | ||
const frustums = this.frustums; | ||
for ( let i = 0; i < frustums.length; i ++ ) { | ||
@@ -82,6 +74,7 @@ | ||
const shadowCam = light.shadow.camera; | ||
const frustum = this.frustums[ i ]; // Get the two points that represent that furthest points on the frustum assuming | ||
const frustum = this.frustums[ i ]; | ||
// Get the two points that represent that furthest points on the frustum assuming | ||
// that's either the diagonal across the far plane or the diagonal across the whole | ||
// frustum itself. | ||
const nearVerts = frustum.vertices.near; | ||
@@ -91,3 +84,2 @@ const farVerts = frustum.vertices.far; | ||
let point2; | ||
if ( point1.distanceTo( farVerts[ 2 ] ) > point1.distanceTo( nearVerts[ 2 ] ) ) { | ||
@@ -104,3 +96,2 @@ | ||
let squaredBBWidth = point1.distanceTo( point2 ); | ||
if ( this.fade ) { | ||
@@ -126,3 +117,2 @@ | ||
} | ||
getBreaks() { | ||
@@ -133,3 +123,2 @@ | ||
this.breaks.length = 0; | ||
switch ( this.mode ) { | ||
@@ -140,11 +129,8 @@ | ||
break; | ||
case 'logarithmic': | ||
logarithmicSplit( this.cascades, camera.near, far, this.breaks ); | ||
break; | ||
case 'practical': | ||
practicalSplit( this.cascades, camera.near, far, 0.5, this.breaks ); | ||
break; | ||
case 'custom': | ||
@@ -187,3 +173,2 @@ if ( this.customSplitsCallback === undefined ) console.error( 'CSM: Custom split scheme callback not defined.' ); | ||
uniformSplit( amount, near, far, _uniformArray ); | ||
for ( let i = 1; i < amount; i ++ ) { | ||
@@ -200,3 +185,2 @@ | ||
} | ||
update() { | ||
@@ -206,3 +190,2 @@ | ||
const frustums = this.frustums; | ||
for ( let i = 0; i < frustums.length; i ++ ) { | ||
@@ -215,15 +198,10 @@ | ||
light.shadow.camera.updateMatrixWorld( true ); | ||
_cameraToLightMatrix.multiplyMatrices( light.shadow.camera.matrixWorldInverse, camera.matrixWorld ); | ||
frustums[ i ].toSpace( _cameraToLightMatrix, _lightSpaceFrustum ); | ||
const nearVerts = _lightSpaceFrustum.vertices.near; | ||
const farVerts = _lightSpaceFrustum.vertices.far; | ||
_bbox.makeEmpty(); | ||
for ( let j = 0; j < 4; j ++ ) { | ||
_bbox.expandByPoint( nearVerts[ j ] ); | ||
_bbox.expandByPoint( farVerts[ j ] ); | ||
@@ -234,9 +212,6 @@ | ||
_bbox.getCenter( _center ); | ||
_center.z = _bbox.max.z + this.lightMargin; | ||
_center.x = Math.floor( _center.x / texelWidth ) * texelWidth; | ||
_center.y = Math.floor( _center.y / texelHeight ) * texelHeight; | ||
_center.applyMatrix4( light.shadow.camera.matrixWorld ); | ||
light.position.copy( _center ); | ||
@@ -251,3 +226,2 @@ light.target.position.copy( _center ); | ||
} | ||
injectInclude() { | ||
@@ -259,3 +233,2 @@ | ||
} | ||
setupMaterial( material ) { | ||
@@ -266,3 +239,2 @@ | ||
material.defines.CSM_CASCADES = this.cascades; | ||
if ( this.fade ) { | ||
@@ -277,3 +249,2 @@ | ||
const shaders = this.shaders; | ||
material.onBeforeCompile = function ( shader ) { | ||
@@ -299,3 +270,2 @@ | ||
} | ||
updateUniforms() { | ||
@@ -331,3 +301,2 @@ | ||
} | ||
getExtendedBreaks( target ) { | ||
@@ -342,3 +311,2 @@ | ||
target.length = this.breaks.length; | ||
for ( let i = 0; i < this.cascades; i ++ ) { | ||
@@ -354,3 +322,2 @@ | ||
} | ||
updateFrustums() { | ||
@@ -364,3 +331,2 @@ | ||
} | ||
remove() { | ||
@@ -370,2 +336,3 @@ | ||
this.parent.remove( this.lights[ i ].target ); | ||
this.parent.remove( this.lights[ i ] ); | ||
@@ -376,3 +343,2 @@ | ||
} | ||
dispose() { | ||
@@ -387,3 +353,2 @@ | ||
delete material.defines.CSM_FADE; | ||
if ( shader !== null ) { | ||
@@ -390,0 +355,0 @@ |
( function () { | ||
const inverseProjectionMatrix = new THREE.Matrix4(); | ||
class CSMFrustum { | ||
@@ -14,3 +13,2 @@ | ||
}; | ||
if ( data.projectionMatrix !== undefined ) { | ||
@@ -23,7 +21,8 @@ | ||
} | ||
setFromProjectionMatrix( projectionMatrix, maxFar ) { | ||
const isOrthographic = projectionMatrix.elements[ 2 * 4 + 3 ] === 0; | ||
inverseProjectionMatrix.copy( projectionMatrix ).invert(); // 3 --- 0 vertices.near/far order | ||
inverseProjectionMatrix.copy( projectionMatrix ).invert(); | ||
// 3 --- 0 vertices.near/far order | ||
// | | | ||
@@ -50,3 +49,2 @@ // 2 --- 1 | ||
const absZ = Math.abs( v.z ); | ||
if ( isOrthographic ) { | ||
@@ -66,3 +64,2 @@ | ||
} | ||
split( breaks, target ) { | ||
@@ -77,7 +74,5 @@ | ||
target.length = breaks.length; | ||
for ( let i = 0; i < breaks.length; i ++ ) { | ||
const cascade = target[ i ]; | ||
if ( i === 0 ) { | ||
@@ -122,3 +117,2 @@ | ||
} | ||
toSpace( cameraMatrix, target ) { | ||
@@ -125,0 +119,0 @@ |
@@ -25,3 +25,2 @@ ( function () { | ||
} | ||
updateVisibility() { | ||
@@ -36,3 +35,2 @@ | ||
const shadowLines = this.shadowLines; | ||
for ( let i = 0, l = cascadeLines.length; i < l; i ++ ) { | ||
@@ -52,3 +50,2 @@ | ||
} | ||
update() { | ||
@@ -71,3 +68,2 @@ | ||
this.updateMatrixWorld( true ); | ||
while ( cascadeLines.length > cascades ) { | ||
@@ -144,3 +140,27 @@ | ||
} | ||
dispose() { | ||
const frustumLines = this.frustumLines; | ||
const cascadeLines = this.cascadeLines; | ||
const cascadePlanes = this.cascadePlanes; | ||
const shadowLines = this.shadowLines; | ||
frustumLines.geometry.dispose(); | ||
frustumLines.material.dispose(); | ||
const cascades = this.csm.cascades; | ||
for ( let i = 0; i < cascades; i ++ ) { | ||
const cascadeLine = cascadeLines[ i ]; | ||
const cascadePlane = cascadePlanes[ i ]; | ||
const shadowLineGroup = shadowLines[ i ]; | ||
const shadowLine = shadowLineGroup.children[ 0 ]; | ||
cascadeLine.dispose(); // THREE.Box3Helper | ||
cascadePlane.geometry.dispose(); | ||
cascadePlane.material.dispose(); | ||
shadowLine.dispose(); // THREE.Box3Helper | ||
} | ||
} | ||
} | ||
@@ -147,0 +167,0 @@ |
( function () { | ||
const CSMShader = { | ||
lights_fragment_begin: | ||
/* glsl */ | ||
` | ||
lights_fragment_begin: /* glsl */` | ||
GeometricContext geometry; | ||
@@ -244,5 +242,3 @@ | ||
`, | ||
lights_pars_begin: | ||
/* glsl */ | ||
` | ||
lights_pars_begin: /* glsl */` | ||
#if defined( USE_CSM ) && defined( CSM_CASCADES ) | ||
@@ -249,0 +245,0 @@ uniform vec2 CSM_cascades[CSM_CASCADES]; |
@@ -12,2 +12,3 @@ ( function () { | ||
*/ | ||
// GrannyKnot | ||
@@ -28,4 +29,5 @@ | ||
} // HeartCurve | ||
} | ||
// HeartCurve | ||
@@ -40,3 +42,2 @@ class HeartCurve extends THREE.Curve { | ||
} | ||
getPoint( t, optionalTarget = new THREE.Vector3() ) { | ||
@@ -53,4 +54,5 @@ | ||
} // Viviani's THREE.Curve | ||
} | ||
// Viviani's THREE.Curve | ||
@@ -65,3 +67,2 @@ class VivianiCurve extends THREE.Curve { | ||
} | ||
getPoint( t, optionalTarget = new THREE.Vector3() ) { | ||
@@ -71,3 +72,2 @@ | ||
t = t * 4 * Math.PI; // normalized to 0..1 | ||
const a = this.scale / 2; | ||
@@ -81,4 +81,5 @@ const x = a * ( 1 + Math.cos( t ) ); | ||
} // KnotCurve | ||
} | ||
// KnotCurve | ||
@@ -100,4 +101,5 @@ class KnotCurve extends THREE.Curve { | ||
} // HelixCurve | ||
} | ||
// HelixCurve | ||
@@ -110,3 +112,2 @@ class HelixCurve extends THREE.Curve { | ||
const a = 30; // radius | ||
const b = 150; // height | ||
@@ -122,4 +123,5 @@ | ||
} // TrefoilKnot | ||
} | ||
// TrefoilKnot | ||
@@ -134,3 +136,2 @@ class TrefoilKnot extends THREE.Curve { | ||
} | ||
getPoint( t, optionalTarget = new THREE.Vector3() ) { | ||
@@ -147,4 +148,5 @@ | ||
} // TorusKnot | ||
} | ||
// TorusKnot | ||
@@ -159,3 +161,2 @@ class TorusKnot extends THREE.Curve { | ||
} | ||
getPoint( t, optionalTarget = new THREE.Vector3() ) { | ||
@@ -174,4 +175,5 @@ | ||
} // CinquefoilKnot | ||
} | ||
// CinquefoilKnot | ||
@@ -186,3 +188,2 @@ class CinquefoilKnot extends THREE.Curve { | ||
} | ||
getPoint( t, optionalTarget = new THREE.Vector3() ) { | ||
@@ -201,4 +202,5 @@ | ||
} // TrefoilPolynomialKnot | ||
} | ||
// TrefoilPolynomialKnot | ||
@@ -213,3 +215,2 @@ class TrefoilPolynomialKnot extends THREE.Curve { | ||
} | ||
getPoint( t, optionalTarget = new THREE.Vector3() ) { | ||
@@ -227,3 +228,2 @@ | ||
} | ||
function scaleTo( x, y, t ) { | ||
@@ -234,4 +234,5 @@ | ||
} // FigureEightPolynomialKnot | ||
} | ||
// FigureEightPolynomialKnot | ||
@@ -246,3 +247,2 @@ class FigureEightPolynomialKnot extends THREE.Curve { | ||
} | ||
getPoint( t, optionalTarget = new THREE.Vector3() ) { | ||
@@ -259,4 +259,5 @@ | ||
} // DecoratedTorusKnot4a | ||
} | ||
// DecoratedTorusKnot4a | ||
@@ -271,3 +272,2 @@ class DecoratedTorusKnot4a extends THREE.Curve { | ||
} | ||
getPoint( t, optionalTarget = new THREE.Vector3() ) { | ||
@@ -284,4 +284,5 @@ | ||
} // DecoratedTorusKnot4b | ||
} | ||
// DecoratedTorusKnot4b | ||
@@ -296,3 +297,2 @@ class DecoratedTorusKnot4b extends THREE.Curve { | ||
} | ||
getPoint( t, optionalTarget = new THREE.Vector3() ) { | ||
@@ -309,4 +309,5 @@ | ||
} // DecoratedTorusKnot5a | ||
} | ||
// DecoratedTorusKnot5a | ||
@@ -321,3 +322,2 @@ class DecoratedTorusKnot5a extends THREE.Curve { | ||
} | ||
getPoint( t, optionalTarget = new THREE.Vector3() ) { | ||
@@ -334,4 +334,5 @@ | ||
} // DecoratedTorusKnot5c | ||
} | ||
// DecoratedTorusKnot5c | ||
@@ -346,3 +347,2 @@ class DecoratedTorusKnot5c extends THREE.Curve { | ||
} | ||
getPoint( t, optionalTarget = new THREE.Vector3() ) { | ||
@@ -349,0 +349,0 @@ |
@@ -14,11 +14,3 @@ ( function () { | ||
constructor( degree, knots | ||
/* array of reals */ | ||
, controlPoints | ||
/* array of Vector(2|3|4) */ | ||
, startKnot | ||
/* index in knots */ | ||
, endKnot | ||
/* index in knots */ | ||
) { | ||
constructor( degree, knots /* array of reals */, controlPoints /* array of Vector(2|3|4) */, startKnot /* index in knots */, endKnot /* index in knots */ ) { | ||
@@ -28,7 +20,6 @@ super(); | ||
this.knots = knots; | ||
this.controlPoints = []; // Used by periodic NURBS to remove hidden spans | ||
this.controlPoints = []; | ||
// Used by periodic NURBS to remove hidden spans | ||
this.startKnot = startKnot || 0; | ||
this.endKnot = endKnot || this.knots.length - 1; | ||
for ( let i = 0; i < controlPoints.length; ++ i ) { | ||
@@ -43,3 +34,2 @@ | ||
} | ||
getPoint( t, optionalTarget = new THREE.Vector3() ) { | ||
@@ -49,6 +39,5 @@ | ||
const u = this.knots[ this.startKnot ] + t * ( this.knots[ this.endKnot ] - this.knots[ this.startKnot ] ); // linear mapping t->u | ||
// following results in (wx, wy, wz, w) homogeneous point | ||
const hpoint = THREE.NURBSUtils.calcBSplinePoint( this.degree, this.knots, this.controlPoints, u ); | ||
if ( hpoint.w !== 1.0 ) { | ||
@@ -64,3 +53,2 @@ | ||
} | ||
getTangent( t, optionalTarget = new THREE.Vector3() ) { | ||
@@ -67,0 +55,0 @@ |
@@ -11,7 +11,3 @@ ( function () { | ||
constructor( degree1, degree2, knots1, knots2 | ||
/* arrays of reals */ | ||
, controlPoints | ||
/* array^2 of Vector(2|3|4) */ | ||
) { | ||
constructor( degree1, degree2, knots1, knots2 /* arrays of reals */, controlPoints /* array^2 of Vector(2|3|4) */ ) { | ||
@@ -24,8 +20,8 @@ this.degree1 = degree1; | ||
const len1 = knots1.length - degree1 - 1; | ||
const len2 = knots2.length - degree2 - 1; // ensure THREE.Vector4 for control points | ||
const len2 = knots2.length - degree2 - 1; | ||
// ensure THREE.Vector4 for control points | ||
for ( let i = 0; i < len1; ++ i ) { | ||
this.controlPoints[ i ] = []; | ||
for ( let j = 0; j < len2; ++ j ) { | ||
@@ -41,7 +37,5 @@ | ||
} | ||
getPoint( t1, t2, target ) { | ||
const u = this.knots1[ 0 ] + t1 * ( this.knots1[ this.knots1.length - 1 ] - this.knots1[ 0 ] ); // linear mapping t1->u | ||
const v = this.knots2[ 0 ] + t2 * ( this.knots2[ this.knots2.length - 1 ] - this.knots2[ 0 ] ); // linear mapping t2->u | ||
@@ -48,0 +42,0 @@ |
@@ -22,7 +22,5 @@ ( function () { | ||
*/ | ||
function findSpan( p, u, U ) { | ||
const n = U.length - p - 1; | ||
if ( u >= U[ n ] ) { | ||
@@ -43,3 +41,2 @@ | ||
let mid = Math.floor( ( low + high ) / 2 ); | ||
while ( u < U[ mid ] || u >= U[ mid + 1 ] ) { | ||
@@ -64,2 +61,3 @@ | ||
} | ||
/* | ||
@@ -75,4 +73,2 @@ Calculate basis functions. See The NURBS Book, page 70, algorithm A2.2 | ||
*/ | ||
function calcBasisFunctions( span, u, p, U ) { | ||
@@ -84,3 +80,2 @@ | ||
N[ 0 ] = 1.0; | ||
for ( let j = 1; j <= p; ++ j ) { | ||
@@ -91,3 +86,2 @@ | ||
let saved = 0.0; | ||
for ( let r = 0; r < j; ++ r ) { | ||
@@ -110,2 +104,3 @@ | ||
} | ||
/* | ||
@@ -121,4 +116,2 @@ Calculate B-Spline curve points. See The NURBS Book, page 82, algorithm A3.1. | ||
*/ | ||
function calcBSplinePoint( p, U, P, u ) { | ||
@@ -129,3 +122,2 @@ | ||
const C = new THREE.Vector4( 0, 0, 0, 0 ); | ||
for ( let j = 0; j <= p; ++ j ) { | ||
@@ -146,2 +138,3 @@ | ||
} | ||
/* | ||
@@ -158,22 +151,13 @@ Calculate basis functions derivatives. See The NURBS Book, page 72, algorithm A2.3. | ||
*/ | ||
function calcBasisFunctionDerivatives( span, u, p, n, U ) { | ||
const zeroArr = []; | ||
for ( let i = 0; i <= p; ++ i ) zeroArr[ i ] = 0.0; | ||
const ders = []; | ||
for ( let i = 0; i <= n; ++ i ) ders[ i ] = zeroArr.slice( 0 ); | ||
const ndu = []; | ||
for ( let i = 0; i <= p; ++ i ) ndu[ i ] = zeroArr.slice( 0 ); | ||
ndu[ 0 ][ 0 ] = 1.0; | ||
const left = zeroArr.slice( 0 ); | ||
const right = zeroArr.slice( 0 ); | ||
for ( let j = 1; j <= p; ++ j ) { | ||
@@ -184,3 +168,2 @@ | ||
let saved = 0.0; | ||
for ( let r = 0; r < j; ++ r ) { | ||
@@ -212,3 +195,2 @@ | ||
const a = []; | ||
for ( let i = 0; i <= p; ++ i ) { | ||
@@ -221,3 +203,2 @@ | ||
a[ 0 ][ 0 ] = 1.0; | ||
for ( let k = 1; k <= n; ++ k ) { | ||
@@ -228,3 +209,2 @@ | ||
const pk = p - k; | ||
if ( r >= k ) { | ||
@@ -239,3 +219,2 @@ | ||
const j2 = r - 1 <= pk ? k - 1 : p - r; | ||
for ( let j = j1; j <= j2; ++ j ) { | ||
@@ -265,3 +244,2 @@ | ||
let r = p; | ||
for ( let k = 1; k <= n; ++ k ) { | ||
@@ -282,2 +260,3 @@ | ||
} | ||
/* | ||
@@ -294,4 +273,2 @@ Calculate derivatives of a B-Spline. See The NURBS Book, page 93, algorithm A3.2. | ||
*/ | ||
function calcBSplineDerivatives( p, U, P, u, nd ) { | ||
@@ -304,3 +281,2 @@ | ||
const Pw = []; | ||
for ( let i = 0; i < P.length; ++ i ) { | ||
@@ -320,3 +296,2 @@ | ||
const point = Pw[ span - p ].clone().multiplyScalar( nders[ k ][ 0 ] ); | ||
for ( let j = 1; j <= p; ++ j ) { | ||
@@ -341,2 +316,3 @@ | ||
} | ||
/* | ||
@@ -347,8 +323,5 @@ Calculate "K over I" | ||
*/ | ||
function calcKoverI( k, i ) { | ||
let nom = 1; | ||
for ( let j = 2; j <= k; ++ j ) { | ||
@@ -361,3 +334,2 @@ | ||
let denom = 1; | ||
for ( let j = 2; j <= i; ++ j ) { | ||
@@ -378,2 +350,3 @@ | ||
} | ||
/* | ||
@@ -386,4 +359,2 @@ Calculate derivatives (0-nd) of rational curve. See The NURBS Book, page 127, algorithm A4.2. | ||
*/ | ||
function calcRationalCurveDerivatives( Pders ) { | ||
@@ -394,3 +365,2 @@ | ||
const wders = []; | ||
for ( let i = 0; i < nd; ++ i ) { | ||
@@ -405,7 +375,5 @@ | ||
const CK = []; | ||
for ( let k = 0; k < nd; ++ k ) { | ||
const v = Aders[ k ].clone(); | ||
for ( let i = 1; i <= k; ++ i ) { | ||
@@ -424,2 +392,3 @@ | ||
} | ||
/* | ||
@@ -436,4 +405,2 @@ Calculate NURBS curve derivatives. See The NURBS Book, page 127, algorithm A4.2. | ||
*/ | ||
function calcNURBSDerivatives( p, U, P, u, nd ) { | ||
@@ -445,2 +412,3 @@ | ||
} | ||
/* | ||
@@ -456,4 +424,2 @@ Calculate rational B-Spline surface point. See The NURBS Book, page 134, algorithm A4.3. | ||
*/ | ||
function calcSurfacePoint( p, q, U, V, P, u, v, target ) { | ||
@@ -466,7 +432,5 @@ | ||
const temp = []; | ||
for ( let l = 0; l <= q; ++ l ) { | ||
temp[ l ] = new THREE.Vector4( 0, 0, 0, 0 ); | ||
for ( let k = 0; k <= p; ++ k ) { | ||
@@ -486,3 +450,2 @@ | ||
const Sw = new THREE.Vector4( 0, 0, 0, 0 ); | ||
for ( let l = 0; l <= q; ++ l ) { | ||
@@ -489,0 +452,0 @@ |
@@ -8,11 +8,8 @@ ( function () { | ||
// Dubois matrices from https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.7.6968&rep=rep1&type=pdf#page=4 | ||
this.colorMatrixLeft = new THREE.Matrix3().fromArray( [ 0.456100, - 0.0400822, - 0.0152161, 0.500484, - 0.0378246, - 0.0205971, 0.176381, - 0.0157589, - 0.00546856 ] ); | ||
this.colorMatrixRight = new THREE.Matrix3().fromArray( [ - 0.0434706, 0.378476, - 0.0721527, - 0.0879388, 0.73364, - 0.112961, - 0.00155529, - 0.0184503, 1.2264 ] ); | ||
const _camera = new THREE.OrthographicCamera( - 1, 1, 1, - 1, 0, 1 ); | ||
const _scene = new THREE.Scene(); | ||
const _stereo = new THREE.StereoCamera(); | ||
const _params = { | ||
@@ -23,7 +20,4 @@ minFilter: THREE.LinearFilter, | ||
}; | ||
const _renderTargetL = new THREE.WebGLRenderTarget( width, height, _params ); | ||
const _renderTargetR = new THREE.WebGLRenderTarget( width, height, _params ); | ||
const _material = new THREE.ShaderMaterial( { | ||
@@ -45,10 +39,9 @@ uniforms: { | ||
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 | ||
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' ) | ||
} ); | ||
const _mesh = new THREE.Mesh( new THREE.PlaneGeometry( 2, 2 ), _material ); | ||
_scene.add( _mesh ); | ||
this.setSize = function ( width, height ) { | ||
@@ -58,5 +51,3 @@ | ||
const pixelRatio = renderer.getPixelRatio(); | ||
_renderTargetL.setSize( width * pixelRatio, height * pixelRatio ); | ||
_renderTargetR.setSize( width * pixelRatio, height * pixelRatio ); | ||
@@ -71,5 +62,3 @@ | ||
if ( camera.parent === null && camera.matrixWorldAutoUpdate === true ) camera.updateMatrixWorld(); | ||
_stereo.update( camera ); | ||
renderer.setRenderTarget( _renderTargetL ); | ||
@@ -90,7 +79,4 @@ renderer.clear(); | ||
_renderTargetL.dispose(); | ||
_renderTargetR.dispose(); | ||
_mesh.geometry.dispose(); | ||
_mesh.material.dispose(); | ||
@@ -97,0 +83,0 @@ |
@@ -8,2 +8,3 @@ ( function () { | ||
*/ | ||
class AsciiEffect { | ||
@@ -16,14 +17,11 @@ | ||
// ' .\'`^",:;Il!i~+_-?][}{1)(|/tfjrxnuvczXYUJCLQ0OZmwqpdbkhao*#MW&8%B@$'.split(''); | ||
// Some ASCII settings | ||
const fResolution = options[ 'resolution' ] || 0.15; // Higher for more details | ||
const iScale = options[ 'scale' ] || 1; | ||
const bColor = options[ 'color' ] || false; // nice but slows down rendering! | ||
const bAlpha = options[ 'alpha' ] || false; // Transparency | ||
const bBlock = options[ 'block' ] || false; // blocked characters. like good O dos | ||
const bInvert = options[ 'invert' ] || false; // black is white, white is black | ||
const strResolution = options[ 'strResolution' ] || 'low'; | ||
@@ -37,3 +35,2 @@ let width, height; | ||
let oImg; | ||
this.setSize = function ( w, h ) { | ||
@@ -55,4 +52,6 @@ | ||
this.domElement = domElement; // Throw in ascii library from https://github.com/hassadee/jsascii/blob/master/jsascii.js (MIT License) | ||
this.domElement = domElement; | ||
// Throw in ascii library from https://github.com/hassadee/jsascii/blob/master/jsascii.js (MIT License) | ||
function initAsciiSize() { | ||
@@ -63,3 +62,4 @@ | ||
oCanvas.width = iWidth; | ||
oCanvas.height = iHeight; // oCanvas.style.display = "none"; | ||
oCanvas.height = iHeight; | ||
// oCanvas.style.display = "none"; | ||
// oCanvas.style.width = iWidth; | ||
@@ -69,3 +69,2 @@ // oCanvas.style.height = iHeight; | ||
oImg = renderer.domElement; | ||
if ( oImg.style.backgroundColor ) { | ||
@@ -101,3 +100,2 @@ | ||
const oCanvas = document.createElement( 'canvas' ); | ||
if ( ! oCanvas.getContext ) { | ||
@@ -110,3 +108,2 @@ | ||
const oCtx = oCanvas.getContext( '2d' ); | ||
if ( ! oCtx.getImageData ) { | ||
@@ -119,9 +116,12 @@ | ||
let aCharList = bColor ? aDefaultColorCharList : aDefaultCharList; | ||
if ( charSet ) aCharList = charSet; // Setup dom | ||
if ( charSet ) aCharList = charSet; | ||
// Setup dom | ||
const fFontSize = 2 / fResolution * iScale; | ||
const fLineHeight = 2 / fResolution * iScale; // adjust letter-spacing for all combinations of scale and resolution to get it to fit the image width. | ||
const fLineHeight = 2 / fResolution * iScale; | ||
// adjust letter-spacing for all combinations of scale and resolution to get it to fit the image width. | ||
let fLetterSpacing = 0; | ||
if ( strResolution == 'low' ) { | ||
@@ -134,3 +134,2 @@ | ||
break; | ||
case 2: | ||
@@ -140,7 +139,5 @@ case 3: | ||
break; | ||
case 4: | ||
fLetterSpacing = - 3.1; | ||
break; | ||
case 5: | ||
@@ -161,11 +158,8 @@ fLetterSpacing = - 4.15; | ||
break; | ||
case 2: | ||
fLetterSpacing = - 1; | ||
break; | ||
case 3: | ||
fLetterSpacing = - 1.04; | ||
break; | ||
case 4: | ||
@@ -188,3 +182,2 @@ case 5: | ||
break; | ||
case 3: | ||
@@ -198,6 +191,8 @@ case 4: | ||
} // can't get a span or div to flow like an img element, but a table works? | ||
} | ||
// can't get a span or div to flow like an img element, but a table works? | ||
// convert img element to ascii | ||
function asciifyImage( oAscii ) { | ||
@@ -207,6 +202,9 @@ | ||
oCtx.drawImage( oCanvasImg, 0, 0, iWidth, iHeight ); | ||
const oImgData = oCtx.getImageData( 0, 0, iWidth, iHeight ).data; // Coloring loop starts now | ||
const oImgData = oCtx.getImageData( 0, 0, iWidth, iHeight ).data; | ||
let strChars = ''; // console.time('rendering'); | ||
// Coloring loop starts now | ||
let strChars = ''; | ||
// console.time('rendering'); | ||
for ( let y = 0; y < iHeight; y += 2 ) { | ||
@@ -223,3 +221,4 @@ | ||
let fBrightness; | ||
fBrightness = ( 0.3 * iRed + 0.59 * iGreen + 0.11 * iBlue ) / 255; // fBrightness = (0.3*iRed + 0.5*iGreen + 0.3*iBlue) / 255; | ||
fBrightness = ( 0.3 * iRed + 0.59 * iGreen + 0.11 * iBlue ) / 255; | ||
// fBrightness = (0.3*iRed + 0.5*iGreen + 0.3*iBlue) / 255; | ||
@@ -235,3 +234,2 @@ if ( iAlpha == 0 ) { | ||
iCharIdx = Math.floor( ( 1 - fBrightness ) * ( aCharList.length - 1 ) ); | ||
if ( bInvert ) { | ||
@@ -241,10 +239,10 @@ | ||
} // good for debugging | ||
} | ||
// good for debugging | ||
//fBrightness = Math.floor(fBrightness * 10); | ||
//strThisChar = fBrightness; | ||
let strThisChar = aCharList[ iCharIdx ]; | ||
if ( strThisChar === undefined || strThisChar == ' ' ) strThisChar = ' '; | ||
if ( bColor ) { | ||
@@ -266,3 +264,6 @@ | ||
oAscii.innerHTML = '<tr><td>' + strChars + '</td></tr>'; // console.timeEnd('rendering'); | ||
oAscii.innerHTML = '<tr><td>' + strChars + '</td></tr>'; | ||
// console.timeEnd('rendering'); | ||
// return oAscii; | ||
@@ -269,0 +270,0 @@ |
@@ -67,3 +67,5 @@ ( function () { | ||
const defaultAlpha = parameters.defaultAlpha !== undefined ? parameters.defaultAlpha : 1.0; | ||
const defaultKeepAlive = parameters.defaultKeepAlive !== undefined ? parameters.defaultKeepAlive : false; // object.material.uuid -> outlineMaterial or | ||
const defaultKeepAlive = parameters.defaultKeepAlive !== undefined ? parameters.defaultKeepAlive : false; | ||
// object.material.uuid -> outlineMaterial or | ||
// object.material[ n ].uuid -> outlineMaterial | ||
@@ -73,12 +75,15 @@ // save at the outline material creation and release | ||
// unless keepAlive is true. | ||
const cache = {}; | ||
const removeThresholdCount = 60; | ||
const cache = {}; | ||
const removeThresholdCount = 60; // outlineMaterial.uuid -> object.material or | ||
// outlineMaterial.uuid -> object.material or | ||
// outlineMaterial.uuid -> object.material[ n ] | ||
// save before render and release after render. | ||
const originalMaterials = {}; | ||
const originalMaterials = {}; // object.uuid -> originalOnBeforeRender | ||
// object.uuid -> originalOnBeforeRender | ||
// save before render and release after render. | ||
const originalOnBeforeRenders = {}; | ||
const originalOnBeforeRenders = {}; //this.cache = cache; // for debug | ||
//this.cache = cache; // for debug | ||
@@ -96,8 +101,11 @@ const uniformsOutline = { | ||
}; | ||
const vertexShader = [ '#include <common>', '#include <uv_pars_vertex>', '#include <displacementmap_pars_vertex>', '#include <fog_pars_vertex>', '#include <morphtarget_pars_vertex>', '#include <skinning_pars_vertex>', '#include <logdepthbuf_pars_vertex>', '#include <clipping_planes_pars_vertex>', 'uniform float outlineThickness;', 'vec4 calculateOutline( vec4 pos, vec3 normal, 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 + normal, 1.0 );', // NOTE: subtract pos2 from pos because THREE.BackSide objectNormal is negative | ||
' vec4 norm = normalize( pos - pos2 );', ' return pos + norm * thickness * pos.w * ratio;', '}', 'void main() {', ' #include <uv_vertex>', ' #include <beginnormal_vertex>', ' #include <morphnormal_vertex>', ' #include <skinbase_vertex>', ' #include <skinnormal_vertex>', ' #include <begin_vertex>', ' #include <morphtarget_vertex>', ' #include <skinning_vertex>', ' #include <displacementmap_vertex>', ' #include <project_vertex>', ' vec3 outlineNormal = - objectNormal;', // the outline material is always rendered with THREE.BackSide | ||
const vertexShader = [ '#include <common>', '#include <uv_pars_vertex>', '#include <displacementmap_pars_vertex>', '#include <fog_pars_vertex>', '#include <morphtarget_pars_vertex>', '#include <skinning_pars_vertex>', '#include <logdepthbuf_pars_vertex>', '#include <clipping_planes_pars_vertex>', 'uniform float outlineThickness;', 'vec4 calculateOutline( vec4 pos, vec3 normal, 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 + normal, 1.0 );', | ||
// NOTE: subtract pos2 from pos because THREE.BackSide objectNormal is negative | ||
' vec4 norm = normalize( pos - pos2 );', ' return pos + norm * thickness * pos.w * ratio;', '}', 'void main() {', ' #include <uv_vertex>', ' #include <beginnormal_vertex>', ' #include <morphnormal_vertex>', ' #include <skinbase_vertex>', ' #include <skinnormal_vertex>', ' #include <begin_vertex>', ' #include <morphtarget_vertex>', ' #include <skinning_vertex>', ' #include <displacementmap_vertex>', ' #include <project_vertex>', ' vec3 outlineNormal = - objectNormal;', | ||
// the outline material is always rendered with THREE.BackSide | ||
' gl_Position = calculateOutline( gl_Position, outlineNormal, vec4( transformed, 1.0 ) );', ' #include <logdepthbuf_vertex>', ' #include <clipping_planes_vertex>', ' #include <fog_vertex>', '}' ].join( '\n' ); | ||
const fragmentShader = [ '#include <common>', '#include <fog_pars_fragment>', '#include <logdepthbuf_pars_fragment>', '#include <clipping_planes_pars_fragment>', 'uniform vec3 outlineColor;', 'uniform float outlineAlpha;', 'void main() {', ' #include <clipping_planes_fragment>', ' #include <logdepthbuf_fragment>', ' gl_FragColor = vec4( outlineColor, outlineAlpha );', ' #include <tonemapping_fragment>', ' #include <encodings_fragment>', ' #include <fog_fragment>', ' #include <premultiplied_alpha_fragment>', '}' ].join( '\n' ); | ||
function createMaterial() { | ||
@@ -118,3 +126,2 @@ | ||
let data = cache[ originalMaterial.uuid ]; | ||
if ( data === undefined ) { | ||
@@ -150,3 +157,2 @@ | ||
let hasNormals = false; | ||
if ( object.geometry !== undefined ) { | ||
@@ -173,3 +179,2 @@ | ||
if ( isCompatible( object ) === false ) return; | ||
if ( Array.isArray( object.material ) ) { | ||
@@ -197,3 +202,2 @@ | ||
if ( isCompatible( object ) === false ) return; | ||
if ( Array.isArray( object.material ) ) { | ||
@@ -219,4 +223,5 @@ | ||
const originalMaterial = originalMaterials[ material.uuid ]; // just in case | ||
const originalMaterial = originalMaterials[ material.uuid ]; | ||
// just in case | ||
if ( originalMaterial === undefined ) return; | ||
@@ -231,3 +236,2 @@ updateUniforms( material, originalMaterial ); | ||
material.uniforms.outlineAlpha.value = originalMaterial.opacity; | ||
if ( outlineParameters !== undefined ) { | ||
@@ -259,3 +263,2 @@ | ||
material.displacementMap = originalMaterial.displacementMap; | ||
if ( outlineParameters !== undefined ) { | ||
@@ -284,3 +287,2 @@ | ||
if ( originalMaterial.wireframe === true || originalMaterial.depthTest === false ) material.visible = false; | ||
if ( originalMaterial.clippingPlanes ) { | ||
@@ -301,6 +303,6 @@ | ||
let keys; // clear originialMaterials | ||
let keys; | ||
// clear originialMaterials | ||
keys = Object.keys( originalMaterials ); | ||
for ( let i = 0, il = keys.length; i < il; i ++ ) { | ||
@@ -310,7 +312,6 @@ | ||
} // clear originalOnBeforeRenders | ||
} | ||
// clear originalOnBeforeRenders | ||
keys = Object.keys( originalOnBeforeRenders ); | ||
for ( let i = 0, il = keys.length; i < il; i ++ ) { | ||
@@ -320,15 +321,12 @@ | ||
} // remove unused outlineMaterial from cache | ||
} | ||
// remove unused outlineMaterial from cache | ||
keys = Object.keys( cache ); | ||
for ( let i = 0, il = keys.length; i < il; i ++ ) { | ||
const key = keys[ i ]; | ||
if ( cache[ key ].used === false ) { | ||
cache[ key ].count ++; | ||
if ( cache[ key ].keepAlive === false && cache[ key ].count > removeThresholdCount ) { | ||
@@ -388,2 +386,3 @@ | ||
}; | ||
/* | ||
@@ -403,8 +402,5 @@ * See #9918 | ||
*/ | ||
this.autoClear = renderer.autoClear; | ||
this.domElement = renderer.domElement; | ||
this.shadowMap = renderer.shadowMap; | ||
this.clear = function ( color, depth, stencil ) { | ||
@@ -411,0 +407,0 @@ |
@@ -8,7 +8,4 @@ ( function () { | ||
const _camera = new THREE.OrthographicCamera( - 1, 1, 1, - 1, 0, 1 ); | ||
const _scene = new THREE.Scene(); | ||
const _stereo = new THREE.StereoCamera(); | ||
const _params = { | ||
@@ -19,7 +16,4 @@ minFilter: THREE.LinearFilter, | ||
}; | ||
const _renderTargetL = new THREE.WebGLRenderTarget( 512, 512, _params ); | ||
const _renderTargetR = new THREE.WebGLRenderTarget( 512, 512, _params ); | ||
const _material = new THREE.ShaderMaterial( { | ||
@@ -37,7 +31,4 @@ uniforms: { | ||
} ); | ||
const mesh = new THREE.Mesh( new THREE.PlaneGeometry( 2, 2 ), _material ); | ||
_scene.add( mesh ); | ||
this.setSize = function ( width, height ) { | ||
@@ -47,5 +38,3 @@ | ||
const pixelRatio = renderer.getPixelRatio(); | ||
_renderTargetL.setSize( width * pixelRatio, height * pixelRatio ); | ||
_renderTargetR.setSize( width * pixelRatio, height * pixelRatio ); | ||
@@ -59,5 +48,3 @@ | ||
if ( camera.parent === null && camera.matrixWorldAutoUpdate === true ) camera.updateMatrixWorld(); | ||
_stereo.update( camera ); | ||
renderer.setRenderTarget( _renderTargetL ); | ||
@@ -64,0 +51,0 @@ renderer.clear(); |
@@ -13,31 +13,20 @@ ( function () { | ||
scope.cameraDistance = 15; | ||
scope.reflectFromAbove = false; // Internals | ||
scope.reflectFromAbove = false; | ||
// Internals | ||
let _halfWidth, _width, _height; | ||
const _cameraF = new THREE.PerspectiveCamera(); //front | ||
const _cameraB = new THREE.PerspectiveCamera(); //back | ||
const _cameraL = new THREE.PerspectiveCamera(); //left | ||
const _cameraR = new THREE.PerspectiveCamera(); //right | ||
const _position = new THREE.Vector3(); | ||
const _quaternion = new THREE.Quaternion(); | ||
const _scale = new THREE.Vector3(); | ||
const _scale = new THREE.Vector3(); // Initialization | ||
// Initialization | ||
renderer.autoClear = false; | ||
this.setSize = function ( width, height ) { | ||
_halfWidth = width / 2; | ||
if ( width < height ) { | ||
@@ -63,41 +52,29 @@ | ||
if ( camera.parent === null && camera.matrixWorldAutoUpdate === true ) camera.updateMatrixWorld(); | ||
camera.matrixWorld.decompose( _position, _quaternion, _scale ); // front | ||
camera.matrixWorld.decompose( _position, _quaternion, _scale ); | ||
// front | ||
_cameraF.position.copy( _position ); | ||
_cameraF.quaternion.copy( _quaternion ); | ||
_cameraF.translateZ( scope.cameraDistance ); | ||
_cameraF.lookAt( scene.position ); | ||
_cameraF.lookAt( scene.position ); // back | ||
// back | ||
_cameraB.position.copy( _position ); | ||
_cameraB.quaternion.copy( _quaternion ); | ||
_cameraB.translateZ( - scope.cameraDistance ); | ||
_cameraB.lookAt( scene.position ); | ||
_cameraB.rotation.z += 180 * ( Math.PI / 180 ); | ||
_cameraB.rotation.z += 180 * ( Math.PI / 180 ); // left | ||
// left | ||
_cameraL.position.copy( _position ); | ||
_cameraL.quaternion.copy( _quaternion ); | ||
_cameraL.translateX( - scope.cameraDistance ); | ||
_cameraL.lookAt( scene.position ); | ||
_cameraL.rotation.x += 90 * ( Math.PI / 180 ); | ||
_cameraL.rotation.x += 90 * ( Math.PI / 180 ); // right | ||
// right | ||
_cameraR.position.copy( _position ); | ||
_cameraR.quaternion.copy( _quaternion ); | ||
_cameraR.translateX( scope.cameraDistance ); | ||
_cameraR.lookAt( scene.position ); | ||
_cameraR.rotation.x += 90 * ( Math.PI / 180 ); | ||
@@ -108,3 +85,2 @@ renderer.clear(); | ||
renderer.setViewport( _halfWidth - _width / 2, _height * 2, _width, _height ); | ||
if ( scope.reflectFromAbove ) { | ||
@@ -122,3 +98,2 @@ | ||
renderer.setViewport( _halfWidth - _width / 2, 0, _width, _height ); | ||
if ( scope.reflectFromAbove ) { | ||
@@ -136,3 +111,2 @@ | ||
renderer.setViewport( _halfWidth - _width / 2 - _width, _height, _width, _height ); | ||
if ( scope.reflectFromAbove ) { | ||
@@ -150,3 +124,2 @@ | ||
renderer.setViewport( _halfWidth + _width / 2, _height, _width, _height ); | ||
if ( scope.reflectFromAbove ) { | ||
@@ -153,0 +126,0 @@ |
@@ -8,6 +8,4 @@ ( function () { | ||
const _stereo = new THREE.StereoCamera(); | ||
_stereo.aspect = 0.5; | ||
const size = new THREE.Vector2(); | ||
this.setEyeSeparation = function ( eyeSep ) { | ||
@@ -29,5 +27,3 @@ | ||
if ( camera.parent === null && camera.matrixWorldAutoUpdate === true ) camera.updateMatrixWorld(); | ||
_stereo.update( camera ); | ||
renderer.getSize( size ); | ||
@@ -34,0 +30,0 @@ if ( renderer.autoClear ) renderer.clear(); |
@@ -6,3 +6,2 @@ ( function () { | ||
*/ | ||
class RoomEnvironment extends THREE.Scene { | ||
@@ -55,29 +54,35 @@ | ||
box6.scale.set( 3.875, 3.487, 2.986 ); | ||
this.add( box6 ); // -x right | ||
this.add( box6 ); | ||
// -x right | ||
const light1 = new THREE.Mesh( geometry, createAreaLightMaterial( 50 ) ); | ||
light1.position.set( - 16.116, 14.37, 8.208 ); | ||
light1.scale.set( 0.1, 2.428, 2.739 ); | ||
this.add( light1 ); // -x left | ||
this.add( light1 ); | ||
// -x left | ||
const light2 = new THREE.Mesh( geometry, createAreaLightMaterial( 50 ) ); | ||
light2.position.set( - 16.109, 18.021, - 8.207 ); | ||
light2.scale.set( 0.1, 2.425, 2.751 ); | ||
this.add( light2 ); // +x | ||
this.add( light2 ); | ||
// +x | ||
const light3 = new THREE.Mesh( geometry, createAreaLightMaterial( 17 ) ); | ||
light3.position.set( 14.904, 12.198, - 1.832 ); | ||
light3.scale.set( 0.15, 4.265, 6.331 ); | ||
this.add( light3 ); // +z | ||
this.add( light3 ); | ||
// +z | ||
const light4 = new THREE.Mesh( geometry, createAreaLightMaterial( 43 ) ); | ||
light4.position.set( - 0.462, 8.89, 14.520 ); | ||
light4.scale.set( 4.38, 5.441, 0.088 ); | ||
this.add( light4 ); // -z | ||
this.add( light4 ); | ||
// -z | ||
const light5 = new THREE.Mesh( geometry, createAreaLightMaterial( 20 ) ); | ||
light5.position.set( 3.235, 11.486, - 12.541 ); | ||
light5.scale.set( 2.5, 2.0, 0.1 ); | ||
this.add( light5 ); // +y | ||
this.add( light5 ); | ||
// +y | ||
const light6 = new THREE.Mesh( geometry, createAreaLightMaterial( 100 ) ); | ||
@@ -89,3 +94,2 @@ light6.position.set( 0.0, 20.0, 0.0 ); | ||
} | ||
dispose() { | ||
@@ -104,3 +108,2 @@ | ||
} ); | ||
for ( const resource of resources ) { | ||
@@ -115,3 +118,2 @@ | ||
} | ||
function createAreaLightMaterial( intensity ) { | ||
@@ -118,0 +120,0 @@ |
@@ -27,3 +27,2 @@ ( function () { | ||
}, options ); | ||
if ( options.upAxis.match( /^[XYZ]_UP$/ ) === null ) { | ||
@@ -57,3 +56,2 @@ | ||
const version = options.version; | ||
if ( version !== '1.4.1' && version !== '1.5.0' ) { | ||
@@ -64,5 +62,5 @@ | ||
} // Convert the urdf xml into a well-formatted, indented format | ||
} | ||
// Convert the urdf xml into a well-formatted, indented format | ||
function format( urdf ) { | ||
@@ -73,5 +71,3 @@ | ||
const HAS_TEXT = /<[^>]+>[^<]*<\/[^<]+>/; | ||
const pad = ( ch, num ) => num > 0 ? ch + pad( ch, num - 1 ) : ''; | ||
let tagnum = 0; | ||
@@ -87,3 +83,2 @@ return urdf.match( /(<[^>]+>[^<]+<\/[^<]+>)|(<[^>]+>)/g ).map( tag => { | ||
const res = `${pad( ' ', tagnum )}${tag}`; | ||
if ( ! HAS_TEXT.test( tag ) && ! IS_SELF_CLOSING.test( tag ) && ! IS_END_TAG.test( tag ) ) { | ||
@@ -99,5 +94,5 @@ | ||
} // Convert an image into a png format for saving | ||
} | ||
// Convert an image into a png format for saving | ||
function base64ToBuffer( str ) { | ||
@@ -107,3 +102,2 @@ | ||
const buf = new Uint8Array( b.length ); | ||
for ( let i = 0, l = buf.length; i < l; i ++ ) { | ||
@@ -120,3 +114,2 @@ | ||
let canvas, ctx; | ||
function imageToData( image, ext ) { | ||
@@ -128,14 +121,15 @@ | ||
canvas.height = image.height; | ||
ctx.drawImage( image, 0, 0 ); // Get the base64 encoded data | ||
ctx.drawImage( image, 0, 0 ); | ||
const base64data = canvas.toDataURL( `image/${ext}`, 1 ).replace( /^data:image\/(png|jpg);base64,/, '' ); // Convert to a uint8 array | ||
// Get the base64 encoded data | ||
const base64data = canvas.toDataURL( `image/${ext}`, 1 ).replace( /^data:image\/(png|jpg);base64,/, '' ); | ||
// Convert to a uint8 array | ||
return base64ToBuffer( base64data ); | ||
} // gets the attribute array. Generate a new array if the attribute is interleaved | ||
} | ||
// gets the attribute array. Generate a new array if the attribute is interleaved | ||
const getFuncs = [ 'getX', 'getY', 'getZ', 'getW' ]; | ||
const tempColor = new THREE.Color(); | ||
function attrBufferToArray( attr, isColor = false ) { | ||
@@ -148,3 +142,2 @@ | ||
const arr = new Float32Array( attr.count * 3 ); | ||
for ( let i = 0, l = attr.count; i < l; i ++ ) { | ||
@@ -166,3 +159,2 @@ | ||
const size = attr.itemSize; | ||
for ( let i = 0, l = attr.count; i < l; i ++ ) { | ||
@@ -186,6 +178,6 @@ | ||
} // Returns an array of the same type starting at the `st` index, | ||
} | ||
// Returns an array of the same type starting at the `st` index, | ||
// and `ct` length | ||
function subArray( arr, st, ct ) { | ||
@@ -195,5 +187,5 @@ | ||
} // Returns the string for a geometry's attribute | ||
} | ||
// Returns the string for a geometry's attribute | ||
function getAttribute( attr, name, params, type, isColor = false ) { | ||
@@ -205,7 +197,6 @@ | ||
} // Returns the string for a node's transform information | ||
} | ||
// Returns the string for a node's transform information | ||
let transMat; | ||
function getTransform( o ) { | ||
@@ -221,10 +212,9 @@ | ||
} // Process the given piece of geometry into the geometry library | ||
} | ||
// Process the given piece of geometry into the geometry library | ||
// Returns the mesh id | ||
function processGeometry( bufferGeometry ) { | ||
let info = geometryInfo.get( bufferGeometry ); | ||
if ( ! info ) { | ||
@@ -240,15 +230,17 @@ | ||
const gname = bufferGeometry.name ? ` name="${bufferGeometry.name}"` : ''; | ||
let gnode = `<geometry id="${meshid}"${gname}><mesh>`; // define the geometry node and the vertices for the geometry | ||
let gnode = `<geometry id="${meshid}"${gname}><mesh>`; | ||
// define the geometry node and the vertices for the geometry | ||
const posName = `${meshid}-position`; | ||
const vertName = `${meshid}-vertices`; | ||
gnode += getAttribute( bufferGeometry.attributes.position, posName, [ 'X', 'Y', 'Z' ], 'float' ); | ||
gnode += `<vertices id="${vertName}"><input semantic="POSITION" source="#${posName}" /></vertices>`; // NOTE: We're not optimizing the attribute arrays here, so they're all the same length and | ||
gnode += `<vertices id="${vertName}"><input semantic="POSITION" source="#${posName}" /></vertices>`; | ||
// NOTE: We're not optimizing the attribute arrays here, so they're all the same length and | ||
// can therefore share the same triangle indices. However, MeshLab seems to have trouble opening | ||
// models with attributes that share an offset. | ||
// MeshLab Bug#424: https://sourceforge.net/p/meshlab/bugs/424/ | ||
// serialize normals | ||
let triangleInputs = `<input semantic="VERTEX" source="#${vertName}" offset="0" />`; | ||
if ( 'normal' in bufferGeometry.attributes ) { | ||
@@ -260,5 +252,5 @@ | ||
} // serialize uvs | ||
} | ||
// serialize uvs | ||
if ( 'uv' in bufferGeometry.attributes ) { | ||
@@ -270,5 +262,5 @@ | ||
} // serialize lightmap uvs | ||
} | ||
// serialize lightmap uvs | ||
if ( 'uv2' in bufferGeometry.attributes ) { | ||
@@ -280,5 +272,5 @@ | ||
} // serialize colors | ||
} | ||
// serialize colors | ||
if ( 'color' in bufferGeometry.attributes ) { | ||
@@ -294,3 +286,2 @@ | ||
let indexArray = null; | ||
if ( bufferGeometry.index ) { | ||
@@ -303,3 +294,2 @@ | ||
indexArray = new Array( indexCount ); | ||
for ( let i = 0, l = indexArray.length; i < l; i ++ ) indexArray[ i ] = i; | ||
@@ -333,10 +323,9 @@ | ||
} // Process the given texture into the image library | ||
} | ||
// Process the given texture into the image library | ||
// Returns the image library | ||
function processTexture( tex ) { | ||
let texid = imageMap.get( tex ); | ||
if ( texid == null ) { | ||
@@ -348,3 +337,2 @@ | ||
let imageNode = `<image id="${texid}" name="${name}">`; | ||
if ( version === '1.5.0' ) { | ||
@@ -376,10 +364,9 @@ | ||
} // Process the given material into the material and effect libraries | ||
} | ||
// Process the given material into the material and effect libraries | ||
// Returns the material id | ||
function processMaterial( m ) { | ||
let matid = materialMap.get( m ); | ||
if ( matid == null ) { | ||
@@ -389,3 +376,2 @@ | ||
let type = 'phong'; | ||
if ( m.isMeshLambertMaterial === true ) { | ||
@@ -398,3 +384,2 @@ | ||
type = 'constant'; | ||
if ( m.map !== null ) { | ||
@@ -418,12 +403,11 @@ | ||
specular.convertLinearToSRGB(); | ||
diffuse.convertLinearToSRGB(); // Do not export and alpha map for the reasons mentioned in issue (#13792) | ||
diffuse.convertLinearToSRGB(); | ||
// Do not export and alpha map for the reasons mentioned in issue (#13792) | ||
// in three.js alpha maps are black and white, but collada expects the alpha | ||
// channel to specify the transparency | ||
let transparencyNode = ''; | ||
if ( m.transparent === true ) { | ||
transparencyNode += '<transparent>' + ( m.map ? '<texture texture="diffuse-sampler"></texture>' : '<float>1</float>' ) + '</transparent>'; | ||
if ( m.opacity < 1 ) { | ||
@@ -449,5 +433,5 @@ | ||
} // Recursively process the object into a scene | ||
} | ||
// Recursively process the object into a scene | ||
function processObject( o ) { | ||
@@ -457,3 +441,2 @@ | ||
node += getTransform( o ); | ||
if ( o.isMesh === true && o.geometry !== null ) { | ||
@@ -465,12 +448,13 @@ | ||
const meshid = geomInfo.meshid; | ||
const geometry = geomInfo.bufferGeometry; // ids of the materials to bind to the geometry | ||
const geometry = geomInfo.bufferGeometry; | ||
// ids of the materials to bind to the geometry | ||
let matids = null; | ||
let matidsArray; // get a list of materials to bind to the sub groups of the geometry. | ||
let matidsArray; | ||
// get a list of materials to bind to the sub groups of the geometry. | ||
// If the amount of subgroups is greater than the materials, than reuse | ||
// the materials. | ||
const mat = o.material || new THREE.MeshBasicMaterial(); | ||
const materials = Array.isArray( mat ) ? mat : [ mat ]; | ||
if ( geometry.groups.length > materials.length ) { | ||
@@ -519,3 +503,2 @@ | ||
}; | ||
if ( typeof onDone === 'function' ) { | ||
@@ -522,0 +505,0 @@ |
@@ -18,2 +18,3 @@ ( function () { | ||
/* global DracoEncoderModule */ | ||
class DRACOExporter { | ||
@@ -42,3 +43,2 @@ | ||
let dracoObject; | ||
if ( object.isMesh === true ) { | ||
@@ -51,3 +51,2 @@ | ||
const faces = geometry.getIndex(); | ||
if ( faces !== null ) { | ||
@@ -60,3 +59,2 @@ | ||
const faces = new ( vertices.count > 65535 ? Uint32Array : Uint16Array )( vertices.count ); | ||
for ( let i = 0; i < faces.length; i ++ ) { | ||
@@ -75,3 +73,2 @@ | ||
const normals = geometry.getAttribute( 'normal' ); | ||
if ( normals !== undefined ) { | ||
@@ -88,3 +85,2 @@ | ||
const uvs = geometry.getAttribute( 'uv' ); | ||
if ( uvs !== undefined ) { | ||
@@ -101,3 +97,2 @@ | ||
const colors = geometry.getAttribute( 'color' ); | ||
if ( colors !== undefined ) { | ||
@@ -117,7 +112,5 @@ | ||
builder.AddFloatAttribute( dracoObject, dracoEncoder.POSITION, vertices.count, vertices.itemSize, vertices.array ); | ||
if ( options.exportColor === true ) { | ||
const colors = geometry.getAttribute( 'color' ); | ||
if ( colors !== undefined ) { | ||
@@ -135,11 +128,16 @@ | ||
} //Compress using draco encoder | ||
} | ||
//Compress using draco encoder | ||
const encodedData = new dracoEncoder.DracoInt8Array(); //Sets the desired encoding and decoding speed for the given options from 0 (slowest speed, but the best compression) to 10 (fastest, but the worst compression). | ||
const encodedData = new dracoEncoder.DracoInt8Array(); | ||
//Sets the desired encoding and decoding speed for the given options from 0 (slowest speed, but the best compression) to 10 (fastest, but the worst compression). | ||
const encodeSpeed = options.encodeSpeed !== undefined ? options.encodeSpeed : 5; | ||
const decodeSpeed = options.decodeSpeed !== undefined ? options.decodeSpeed : 5; | ||
encoder.SetSpeedOptions( encodeSpeed, decodeSpeed ); // Sets the desired encoding method for a given geometry. | ||
encoder.SetSpeedOptions( encodeSpeed, decodeSpeed ); | ||
// Sets the desired encoding method for a given geometry. | ||
if ( options.encoderMethod !== undefined ) { | ||
@@ -149,6 +147,6 @@ | ||
} // Sets the quantization (number of bits used to represent) compression options for a named attribute. | ||
} | ||
// Sets the quantization (number of bits used to represent) compression options for a named attribute. | ||
// The attribute values will be quantized in a box defined by the maximum extent of the attribute values. | ||
if ( options.quantization !== undefined ) { | ||
@@ -169,3 +167,2 @@ | ||
let length; | ||
if ( object.isMesh === true ) { | ||
@@ -182,3 +179,2 @@ | ||
dracoEncoder.destroy( dracoObject ); | ||
if ( length === 0 ) { | ||
@@ -188,7 +184,6 @@ | ||
} //Copy encoded data to buffer. | ||
} | ||
//Copy encoded data to buffer. | ||
const outputData = new Int8Array( new ArrayBuffer( length ) ); | ||
for ( let i = 0; i < length; i ++ ) { | ||
@@ -207,11 +202,16 @@ | ||
} // Encoder methods | ||
} | ||
// Encoder methods | ||
DRACOExporter.MESH_EDGEBREAKER_ENCODING = 1; | ||
DRACOExporter.MESH_SEQUENTIAL_ENCODING = 0; // Geometry type | ||
DRACOExporter.MESH_SEQUENTIAL_ENCODING = 0; | ||
// Geometry type | ||
DRACOExporter.POINT_CLOUD = 0; | ||
DRACOExporter.TRIANGULAR_MESH = 1; // Attribute type | ||
DRACOExporter.TRIANGULAR_MESH = 1; | ||
// Attribute type | ||
DRACOExporter.INVALID = - 1; | ||
@@ -218,0 +218,0 @@ DRACOExporter.POSITION = 0; |
@@ -13,3 +13,2 @@ ( function () { | ||
const ZIP_COMPRESSION = 3; | ||
class EXRExporter { | ||
@@ -29,3 +28,2 @@ | ||
} | ||
function supported( renderer, renderTarget ) { | ||
@@ -102,3 +100,2 @@ | ||
let dataBuffer; | ||
if ( info.type === THREE.FloatType ) { | ||
@@ -137,3 +134,2 @@ | ||
dv = new DataView( outBuffer.buffer ); | ||
for ( let y = 0; y < h; ++ y ) { | ||
@@ -177,3 +173,2 @@ | ||
size = info.width * info.numOutputChannels * info.blockLines * info.dataSize; | ||
switch ( info.compression ) { | ||
@@ -184,3 +179,2 @@ | ||
break; | ||
case 2: | ||
@@ -227,2 +221,3 @@ case 3: | ||
// | ||
let t1 = 0, | ||
@@ -232,3 +227,2 @@ t2 = Math.floor( ( data.length + 1 ) / 2 ), | ||
const stop = data.length - 1; | ||
while ( true ) { | ||
@@ -241,9 +235,9 @@ | ||
} // | ||
} | ||
// | ||
// Predictor. | ||
// | ||
let p = tmpBuffer[ 0 ]; | ||
for ( let t = 1; t < tmpBuffer.length; t ++ ) { | ||
@@ -276,4 +270,4 @@ | ||
setUint32( dv, 20000630, offset ); // magic | ||
setUint32( dv, 2, offset ); // mask | ||
setUint32( dv, 2, offset ); // mask | ||
// = HEADER = | ||
@@ -339,8 +333,10 @@ | ||
setUint32( dv, 1, offset ); | ||
setUint8( dv, 0, offset ); // null-byte | ||
setUint8( dv, 0, offset ); | ||
setUint8( dv, 0, offset ); // = OFFSET TABLE = | ||
// null-byte | ||
setUint8( dv, 0, offset ); | ||
// = OFFSET TABLE = | ||
let sum = offset.value + info.numBlocks * 8; | ||
for ( let i = 0; i < chunks.data.length; ++ i ) { | ||
@@ -366,3 +362,2 @@ | ||
fillHeader( outBuffer, chunks, info ); | ||
for ( let i = 0; i < chunks.data.length; ++ i ) { | ||
@@ -390,3 +385,6 @@ | ||
} // function decodeSRGB( dec, r, g, b, a ) { | ||
} | ||
// function decodeSRGB( dec, r, g, b, a ) { | ||
// dec.r = r > 0.04045 ? Math.pow( r * 0.9478672986 + 0.0521327014, 2.4 ) : r * 0.0773993808; | ||
@@ -396,5 +394,5 @@ // dec.g = g > 0.04045 ? Math.pow( g * 0.9478672986 + 0.0521327014, 2.4 ) : g * 0.0773993808; | ||
// dec.a = a; | ||
// } | ||
function setUint8( dv, value, offset ) { | ||
@@ -438,3 +436,2 @@ | ||
const tmp = textEncoder.encode( string + '\0' ); | ||
for ( let i = 0; i < tmp.length; ++ i ) { | ||
@@ -441,0 +438,0 @@ |
@@ -45,3 +45,2 @@ ( function () { | ||
let a = num.toString(); | ||
if ( a.indexOf( '.' ) === - 1 ) { | ||
@@ -64,3 +63,2 @@ | ||
const a = []; | ||
for ( let i = 0, il = array.length; i < il; i ++ ) { | ||
@@ -89,3 +87,2 @@ | ||
array.push( '' ); | ||
for ( let i = 0, il = bones.length; i < il; i ++ ) { | ||
@@ -95,2 +92,3 @@ | ||
const bone2 = bones2[ i ]; | ||
/* | ||
@@ -100,3 +98,2 @@ * use the bone matrix saved before solving IK. | ||
*/ | ||
if ( useOriginalBones === true && bone.userData.ik !== undefined && bone.userData.ik.originalMatrix !== undefined ) { | ||
@@ -115,4 +112,5 @@ | ||
const pArray = position.sub( bone2.position ).toArray(); | ||
const qArray = quaternion2.copy( bone2.quaternion ).conjugate().multiply( quaternion ).toArray(); // right to left | ||
const qArray = quaternion2.copy( bone2.quaternion ).conjugate().multiply( quaternion ).toArray(); | ||
// right to left | ||
pArray[ 2 ] = - pArray[ 2 ]; | ||
@@ -135,7 +133,6 @@ qArray[ 0 ] = - qArray[ 0 ]; | ||
} // Unicode to Shift_JIS table | ||
} | ||
// Unicode to Shift_JIS table | ||
let u2sTable; | ||
function unicodeToShiftjis( str ) { | ||
@@ -146,7 +143,5 @@ | ||
const encoder = new MMDParser.CharsetEncoder(); // eslint-disable-line no-undef | ||
const table = encoder.s2uTable; | ||
u2sTable = {}; | ||
const keys = Object.keys( table ); | ||
for ( let i = 0, il = keys.length; i < il; i ++ ) { | ||
@@ -164,3 +159,2 @@ | ||
const array = []; | ||
for ( let i = 0, il = str.length; i < il; i ++ ) { | ||
@@ -170,3 +164,2 @@ | ||
const value = u2sTable[ code ]; | ||
if ( value === undefined ) { | ||
@@ -173,0 +166,0 @@ |
@@ -16,3 +16,2 @@ ( function () { | ||
const face = []; | ||
function parseMesh( mesh ) { | ||
@@ -24,11 +23,14 @@ | ||
const geometry = mesh.geometry; | ||
const normalMatrixWorld = new THREE.Matrix3(); // shortcuts | ||
const normalMatrixWorld = new THREE.Matrix3(); | ||
// shortcuts | ||
const vertices = geometry.getAttribute( 'position' ); | ||
const normals = geometry.getAttribute( 'normal' ); | ||
const uvs = geometry.getAttribute( 'uv' ); | ||
const indices = geometry.getIndex(); // name of the mesh object | ||
const indices = geometry.getIndex(); | ||
output += 'o ' + mesh.name + '\n'; // name of the mesh material | ||
// name of the mesh object | ||
output += 'o ' + mesh.name + '\n'; | ||
// name of the mesh material | ||
if ( mesh.material && mesh.material.name ) { | ||
@@ -38,4 +40,5 @@ | ||
} // vertices | ||
} | ||
// vertices | ||
@@ -46,6 +49,8 @@ if ( vertices !== undefined ) { | ||
vertex.fromBufferAttribute( vertices, i ); // transform the vertex to world space | ||
vertex.fromBufferAttribute( vertices, i ); | ||
vertex.applyMatrix4( mesh.matrixWorld ); // transform the vertex to export format | ||
// transform the vertex to world space | ||
vertex.applyMatrix4( mesh.matrixWorld ); | ||
// transform the vertex to export format | ||
output += 'v ' + vertex.x + ' ' + vertex.y + ' ' + vertex.z + '\n'; | ||
@@ -55,4 +60,5 @@ | ||
} // uvs | ||
} | ||
// uvs | ||
@@ -63,4 +69,5 @@ if ( uvs !== undefined ) { | ||
uv.fromBufferAttribute( uvs, i ); // transform the uv to export format | ||
uv.fromBufferAttribute( uvs, i ); | ||
// transform the uv to export format | ||
output += 'vt ' + uv.x + ' ' + uv.y + '\n'; | ||
@@ -70,4 +77,5 @@ | ||
} // normals | ||
} | ||
// normals | ||
@@ -77,9 +85,10 @@ if ( normals !== undefined ) { | ||
normalMatrixWorld.getNormalMatrix( mesh.matrixWorld ); | ||
for ( let i = 0, l = normals.count; i < l; i ++, nbNormals ++ ) { | ||
normal.fromBufferAttribute( normals, i ); // transform the normal to world space | ||
normal.fromBufferAttribute( normals, i ); | ||
normal.applyMatrix3( normalMatrixWorld ).normalize(); // transform the normal to export format | ||
// transform the normal to world space | ||
normal.applyMatrix3( normalMatrixWorld ).normalize(); | ||
// transform the normal to export format | ||
output += 'vn ' + normal.x + ' ' + normal.y + ' ' + normal.z + '\n'; | ||
@@ -89,4 +98,5 @@ | ||
} // faces | ||
} | ||
// faces | ||
@@ -102,5 +112,5 @@ if ( indices !== null ) { | ||
} // transform the face to export format | ||
} | ||
// transform the face to export format | ||
output += 'f ' + face.join( ' ' ) + '\n'; | ||
@@ -119,5 +129,5 @@ | ||
} // transform the face to export format | ||
} | ||
// transform the face to export format | ||
output += 'f ' + face.join( ' ' ) + '\n'; | ||
@@ -127,5 +137,5 @@ | ||
} // update index | ||
} | ||
// update index | ||
indexVertex += nbVertex; | ||
@@ -141,8 +151,9 @@ indexVertexUvs += nbVertexUvs; | ||
const geometry = line.geometry; | ||
const type = line.type; // shortcuts | ||
const type = line.type; | ||
const vertices = geometry.getAttribute( 'position' ); // name of the line object | ||
// shortcuts | ||
const vertices = geometry.getAttribute( 'position' ); | ||
// name of the line object | ||
output += 'o ' + line.name + '\n'; | ||
if ( vertices !== undefined ) { | ||
@@ -152,6 +163,8 @@ | ||
vertex.fromBufferAttribute( vertices, i ); // transform the vertex to world space | ||
vertex.fromBufferAttribute( vertices, i ); | ||
vertex.applyMatrix4( line.matrixWorld ); // transform the vertex to export format | ||
// transform the vertex to world space | ||
vertex.applyMatrix4( line.matrixWorld ); | ||
// transform the vertex to export format | ||
output += 'v ' + vertex.x + ' ' + vertex.y + ' ' + vertex.z + '\n'; | ||
@@ -166,3 +179,2 @@ | ||
output += 'l '; | ||
for ( let j = 1, l = vertices.count; j <= l; j ++ ) { | ||
@@ -186,5 +198,5 @@ | ||
} // update index | ||
} | ||
// update index | ||
indexVertex += nbVertex; | ||
@@ -201,3 +213,2 @@ | ||
output += 'o ' + points.name + '\n'; | ||
if ( vertices !== undefined ) { | ||
@@ -210,3 +221,2 @@ | ||
output += 'v ' + vertex.x + ' ' + vertex.y + ' ' + vertex.z; | ||
if ( colors !== undefined ) { | ||
@@ -224,3 +234,2 @@ | ||
output += 'p '; | ||
for ( let j = 1, l = vertices.count; j <= l; j ++ ) { | ||
@@ -234,5 +243,5 @@ | ||
} // update index | ||
} | ||
// update index | ||
indexVertex += nbVertex; | ||
@@ -239,0 +248,0 @@ |
@@ -29,3 +29,2 @@ ( function () { | ||
const geometry = mesh.geometry; | ||
if ( geometry.hasAttribute( 'position' ) === true ) { | ||
@@ -41,5 +40,5 @@ | ||
} // Default options | ||
} | ||
// Default options | ||
const defaultOptions = { | ||
@@ -56,5 +55,6 @@ binary: false, | ||
let includeColors = false; | ||
let includeUVs = false; // count the vertices, check which properties are used, | ||
let includeUVs = false; | ||
// count the vertices, check which properties are used, | ||
// and cache the BufferGeometry | ||
let vertexCount = 0; | ||
@@ -73,3 +73,2 @@ let faceCount = 0; | ||
const indices = geometry.getIndex(); | ||
if ( vertices === undefined ) { | ||
@@ -103,3 +102,2 @@ | ||
includeUVs = includeUVs && excludeAttributes.indexOf( 'uv' ) === - 1; | ||
if ( includeIndices && faceCount !== Math.floor( faceCount ) ) { | ||
@@ -116,5 +114,5 @@ | ||
const indexByteCount = 4; | ||
let header = 'ply\n' + `format ${options.binary ? options.littleEndian ? 'binary_little_endian' : 'binary_big_endian' : 'ascii'} 1.0\n` + `element vertex ${vertexCount}\n` + // position | ||
let header = 'ply\n' + `format ${options.binary ? options.littleEndian ? 'binary_little_endian' : 'binary_big_endian' : 'ascii'} 1.0\n` + `element vertex ${vertexCount}\n` + | ||
// position | ||
'property float x\n' + 'property float y\n' + 'property float z\n'; | ||
if ( includeNormals === true ) { | ||
@@ -148,19 +146,21 @@ | ||
header += 'end_header\n'; // Generate attribute data | ||
header += 'end_header\n'; | ||
// Generate attribute data | ||
const vertex = new THREE.Vector3(); | ||
const normalMatrixWorld = new THREE.Matrix3(); | ||
let result = null; | ||
if ( options.binary === true ) { | ||
// Binary File Generation | ||
const headerBin = new TextEncoder().encode( header ); // 3 position values at 4 bytes | ||
const headerBin = new TextEncoder().encode( header ); | ||
// 3 position values at 4 bytes | ||
// 3 normal values at 4 bytes | ||
// 3 color channels with 1 byte | ||
// 2 uv values at 4 bytes | ||
const vertexListLength = vertexCount * ( 4 * 3 + ( includeNormals ? 4 * 3 : 0 ) + ( includeColors ? 3 : 0 ) + ( includeUVs ? 4 * 2 : 0 ) ); | ||
const vertexListLength = vertexCount * ( 4 * 3 + ( includeNormals ? 4 * 3 : 0 ) + ( includeColors ? 3 : 0 ) + ( includeUVs ? 4 * 2 : 0 ) ); // 1 byte shape desciptor | ||
// 1 byte shape desciptor | ||
// 3 vertex indices at ${indexByteCount} bytes | ||
const faceListLength = includeIndices ? faceCount * ( indexByteCount * 3 + 1 ) : 0; | ||
@@ -180,8 +180,8 @@ const output = new DataView( new ArrayBuffer( headerBin.length + vertexListLength + faceListLength ) ); | ||
normalMatrixWorld.getNormalMatrix( mesh.matrixWorld ); | ||
for ( let i = 0, l = vertices.count; i < l; i ++ ) { | ||
vertex.fromBufferAttribute( vertices, i ); | ||
vertex.applyMatrix4( mesh.matrixWorld ); // Position information | ||
vertex.applyMatrix4( mesh.matrixWorld ); | ||
// Position information | ||
output.setFloat32( vOffset, vertex.x, options.littleEndian ); | ||
@@ -192,4 +192,5 @@ vOffset += 4; | ||
output.setFloat32( vOffset, vertex.z, options.littleEndian ); | ||
vOffset += 4; // Normal information | ||
vOffset += 4; | ||
// Normal information | ||
if ( includeNormals === true ) { | ||
@@ -219,5 +220,5 @@ | ||
} // UV information | ||
} | ||
// UV information | ||
if ( includeUVs === true ) { | ||
@@ -241,5 +242,5 @@ | ||
} // THREE.Color information | ||
} | ||
// THREE.Color information | ||
if ( includeColors === true ) { | ||
@@ -275,2 +276,3 @@ | ||
// Create the face list | ||
if ( indices !== null ) { | ||
@@ -308,6 +310,6 @@ | ||
} // Save the amount of verts we've already written so we can offset | ||
} | ||
// Save the amount of verts we've already written so we can offset | ||
// the face index on the next mesh | ||
writtenVertices += vertices.count; | ||
@@ -332,11 +334,14 @@ | ||
const indices = geometry.getIndex(); | ||
normalMatrixWorld.getNormalMatrix( mesh.matrixWorld ); // form each line | ||
normalMatrixWorld.getNormalMatrix( mesh.matrixWorld ); | ||
// form each line | ||
for ( let i = 0, l = vertices.count; i < l; i ++ ) { | ||
vertex.fromBufferAttribute( vertices, i ); | ||
vertex.applyMatrix4( mesh.matrixWorld ); // Position information | ||
vertex.applyMatrix4( mesh.matrixWorld ); | ||
let line = vertex.x + ' ' + vertex.y + ' ' + vertex.z; // Normal information | ||
// Position information | ||
let line = vertex.x + ' ' + vertex.y + ' ' + vertex.z; | ||
// Normal information | ||
if ( includeNormals === true ) { | ||
@@ -356,5 +361,5 @@ | ||
} // UV information | ||
} | ||
// UV information | ||
if ( includeUVs === true ) { | ||
@@ -372,5 +377,5 @@ | ||
} // THREE.Color information | ||
} | ||
// THREE.Color information | ||
if ( includeColors === true ) { | ||
@@ -393,5 +398,5 @@ | ||
} // Create the face list | ||
} | ||
// Create the face list | ||
if ( includeIndices === true ) { | ||
@@ -398,0 +403,0 @@ |
@@ -16,4 +16,6 @@ ( function () { | ||
const binary = options.binary !== undefined ? options.binary : false; // | ||
const binary = options.binary !== undefined ? options.binary : false; | ||
// | ||
const objects = []; | ||
@@ -61,3 +63,2 @@ let triangles = 0; | ||
const normal = new THREE.Vector3(); | ||
for ( let i = 0, il = objects.length; i < il; i ++ ) { | ||
@@ -69,6 +70,6 @@ | ||
const positionAttribute = geometry.getAttribute( 'position' ); | ||
if ( index !== null ) { | ||
// indexed geometry | ||
for ( let j = 0; j < index.count; j += 3 ) { | ||
@@ -86,2 +87,3 @@ | ||
// non-indexed geometry | ||
for ( let j = 0; j < positionAttribute.count; j += 3 ) { | ||
@@ -107,3 +109,2 @@ | ||
return output; | ||
function writeFace( a, b, c, positionAttribute, object ) { | ||
@@ -114,3 +115,2 @@ | ||
vC.fromBufferAttribute( positionAttribute, c ); | ||
if ( object.isSkinnedMesh === true ) { | ||
@@ -131,3 +131,2 @@ | ||
writeVertex( vC ); | ||
if ( binary === true ) { | ||
@@ -153,3 +152,2 @@ | ||
normal.copy( cb ).normalize(); | ||
if ( binary === true ) { | ||
@@ -156,0 +154,0 @@ |
@@ -8,4 +8,5 @@ ( function () { | ||
const files = {}; | ||
const modelFileName = 'model.usda'; // model file should be first in USDZ archive so we init it here | ||
const modelFileName = 'model.usda'; | ||
// model file should be first in USDZ archive so we init it here | ||
files[ modelFileName ] = null; | ||
@@ -21,7 +22,5 @@ let output = buildHeader(); | ||
const material = object.material; | ||
if ( material.isMeshStandardMaterial ) { | ||
const geometryFileName = 'geometries/Geometry_' + geometry.id + '.usd'; | ||
if ( ! ( geometryFileName in files ) ) { | ||
@@ -48,2 +47,6 @@ | ||
} else if ( object.isCamera ) { | ||
output += buildCamera( object ); | ||
} | ||
@@ -55,3 +58,2 @@ | ||
output = null; | ||
for ( const id in textures ) { | ||
@@ -66,8 +68,8 @@ | ||
} // 64 byte alignment | ||
} | ||
// 64 byte alignment | ||
// https://github.com/101arrowz/fflate/issues/39#issuecomment-777263109 | ||
let offset = 0; | ||
for ( const filename in files ) { | ||
@@ -79,3 +81,2 @@ | ||
const offsetMod64 = offset & 63; | ||
if ( offsetMod64 !== 4 ) { | ||
@@ -104,3 +105,2 @@ | ||
} | ||
function imageToCanvas( image, color ) { | ||
@@ -116,3 +116,2 @@ | ||
context.drawImage( image, 0, 0, canvas.width, canvas.height ); | ||
if ( color !== undefined ) { | ||
@@ -126,3 +125,2 @@ | ||
const data = imagedata.data; | ||
for ( let i = 0; i < data.length; i += 4 ) { | ||
@@ -144,7 +142,7 @@ | ||
} // | ||
} | ||
// | ||
const PRECISION = 7; | ||
function buildHeader() { | ||
@@ -171,4 +169,5 @@ | ||
} // Xform | ||
} | ||
// Xform | ||
@@ -179,3 +178,2 @@ function buildXform( object, geometry, material ) { | ||
const transform = buildMatrix( object.matrixWorld ); | ||
if ( object.matrixWorld.determinant() < 0 ) { | ||
@@ -212,4 +210,5 @@ | ||
} // Mesh | ||
} | ||
// Mesh | ||
@@ -262,3 +261,2 @@ function buildMeshObject( geometry ) { | ||
const array = []; | ||
if ( index !== null ) { | ||
@@ -275,3 +273,2 @@ | ||
const length = geometry.attributes.position.count; | ||
for ( let i = 0; i < length; i ++ ) { | ||
@@ -299,3 +296,2 @@ | ||
const array = []; | ||
for ( let i = 0; i < attribute.count; i ++ ) { | ||
@@ -324,3 +320,2 @@ | ||
const array = []; | ||
for ( let i = 0; i < attribute.count; i ++ ) { | ||
@@ -336,4 +331,5 @@ | ||
} // Materials | ||
} | ||
// Materials | ||
@@ -343,3 +339,2 @@ function buildMaterials( materials, textures ) { | ||
const array = []; | ||
for ( const uuid in materials ) { | ||
@@ -364,6 +359,6 @@ | ||
// https://graphics.pixar.com/usd/docs/UsdPreviewSurface-Proposal.html | ||
const pad = ' '; | ||
const inputs = []; | ||
const samplers = []; | ||
function buildTexture( texture, mapType, color ) { | ||
@@ -413,3 +408,2 @@ | ||
inputs.push( `${pad}color3f inputs:diffuseColor.connect = </Materials/Material_${material.id}/Texture_${material.map.id}_diffuse.outputs:rgb>` ); | ||
if ( material.transparent ) { | ||
@@ -542,4 +536,50 @@ | ||
function buildCamera( camera ) { | ||
const name = camera.name ? camera.name : 'Camera_' + camera.id; | ||
const transform = buildMatrix( camera.matrixWorld ); | ||
if ( camera.matrixWorld.determinant() < 0 ) { | ||
console.warn( 'THREE.USDZExporter: USDZ does not support negative scales', camera ); | ||
} | ||
if ( camera.isOrthographicCamera ) { | ||
return `def Camera "${name}" | ||
{ | ||
matrix4d xformOp:transform = ${transform} | ||
uniform token[] xformOpOrder = ["xformOp:transform"] | ||
float2 clippingRange = (${camera.near}, ${camera.far}) | ||
float horizontalAperture = ${( Math.abs( camera.left ) + Math.abs( camera.right ) ) * 10} | ||
float verticalAperture = ${( Math.abs( camera.top ) + Math.abs( camera.bottom ) ) * 10} | ||
token projection = "orthographic" | ||
} | ||
`; | ||
} else { | ||
return `def Camera "${name}" | ||
{ | ||
matrix4d xformOp:transform = ${transform} | ||
uniform token[] xformOpOrder = ["xformOp:transform"] | ||
float2 clippingRange = (${camera.near}, ${camera.far}) | ||
float focalLength = ${camera.getFocalLength()} | ||
float focusDistance = ${camera.focus} | ||
float horizontalAperture = ${camera.getFilmWidth()} | ||
token projection = "perspective" | ||
float verticalAperture = ${camera.getFilmHeight()} | ||
} | ||
`; | ||
} | ||
} | ||
THREE.USDZExporter = USDZExporter; | ||
} )(); |
@@ -21,3 +21,2 @@ ( function () { | ||
let z = - depthHalf; | ||
for ( let i = 0; i <= widthSegments; i ++ ) { | ||
@@ -24,0 +23,0 @@ |
@@ -7,7 +7,8 @@ ( function () { | ||
super(); // buffers | ||
super(); | ||
// buffers | ||
const vertices = []; | ||
const normals = []; | ||
if ( THREE.ConvexHull === undefined ) { | ||
@@ -19,11 +20,14 @@ | ||
const convexHull = new THREE.ConvexHull().setFromPoints( points ); // generate vertices and normals | ||
const convexHull = new THREE.ConvexHull().setFromPoints( points ); | ||
// generate vertices and normals | ||
const faces = convexHull.faces; | ||
for ( let i = 0; i < faces.length; i ++ ) { | ||
const face = faces[ i ]; | ||
let edge = face.edge; // we move along a doubly-connected edge list to access all face points (see HalfEdge docs) | ||
let edge = face.edge; | ||
// we move along a doubly-connected edge list to access all face points (see HalfEdge docs) | ||
do { | ||
@@ -38,4 +42,5 @@ | ||
} // build geometry | ||
} | ||
// build geometry | ||
@@ -42,0 +47,0 @@ this.setAttribute( 'position', new THREE.Float32BufferAttribute( vertices, 3 ) ); |
@@ -22,10 +22,16 @@ ( function () { | ||
super(); // buffers | ||
super(); | ||
// buffers | ||
const vertices = []; | ||
const normals = []; | ||
const uvs = []; // helpers | ||
const uvs = []; | ||
const plane = new THREE.Vector3(); // this matrix represents the transformation of the decal projector | ||
// helpers | ||
const plane = new THREE.Vector3(); | ||
// this matrix represents the transformation of the decal projector | ||
const projectorMatrix = new THREE.Matrix4(); | ||
@@ -35,10 +41,13 @@ projectorMatrix.makeRotationFromEuler( orientation ); | ||
const projectorMatrixInverse = new THREE.Matrix4(); | ||
projectorMatrixInverse.copy( projectorMatrix ).invert(); // generate buffers | ||
projectorMatrixInverse.copy( projectorMatrix ).invert(); | ||
generate(); // build geometry | ||
// generate buffers | ||
generate(); | ||
// build geometry | ||
this.setAttribute( 'position', new THREE.Float32BufferAttribute( vertices, 3 ) ); | ||
this.setAttribute( 'normal', new THREE.Float32BufferAttribute( normals, 3 ) ); | ||
this.setAttribute( 'uv', new THREE.Float32BufferAttribute( uvs, 2 ) ); | ||
function generate() { | ||
@@ -48,7 +57,11 @@ | ||
const vertex = new THREE.Vector3(); | ||
const normal = new THREE.Vector3(); // handle different geometry types | ||
const normal = new THREE.Vector3(); | ||
// handle different geometry types | ||
const geometry = mesh.geometry; | ||
const positionAttribute = geometry.attributes.position; | ||
const normalAttribute = geometry.attributes.normal; // first, create an array of 'DecalVertex' objects | ||
const normalAttribute = geometry.attributes.normal; | ||
// first, create an array of 'DecalVertex' objects | ||
// three consecutive 'DecalVertex' objects represent a single face | ||
@@ -61,4 +74,4 @@ // | ||
// indexed THREE.BufferGeometry | ||
const index = geometry.index; | ||
for ( let i = 0; i < index.count; i ++ ) { | ||
@@ -75,2 +88,3 @@ | ||
// non-indexed THREE.BufferGeometry | ||
for ( let i = 0; i < positionAttribute.count; i ++ ) { | ||
@@ -84,4 +98,5 @@ | ||
} // second, clip the geometry so that it doesn't extend out from the projector | ||
} | ||
// second, clip the geometry so that it doesn't extend out from the projector | ||
@@ -93,12 +108,20 @@ decalVertices = clipGeometry( decalVertices, plane.set( 1, 0, 0 ) ); | ||
decalVertices = clipGeometry( decalVertices, plane.set( 0, 0, 1 ) ); | ||
decalVertices = clipGeometry( decalVertices, plane.set( 0, 0, - 1 ) ); // third, generate final vertices, normals and uvs | ||
decalVertices = clipGeometry( decalVertices, plane.set( 0, 0, - 1 ) ); | ||
// third, generate final vertices, normals and uvs | ||
for ( let i = 0; i < decalVertices.length; i ++ ) { | ||
const decalVertex = decalVertices[ i ]; // create texture coordinates (we are still in projector space) | ||
const decalVertex = decalVertices[ i ]; | ||
uvs.push( 0.5 + decalVertex.position.x / size.x, 0.5 + decalVertex.position.y / size.y ); // transform the vertex back to world space | ||
// create texture coordinates (we are still in projector space) | ||
decalVertex.position.applyMatrix4( projectorMatrix ); // now create vertex and normal buffer data | ||
uvs.push( 0.5 + decalVertex.position.x / size.x, 0.5 + decalVertex.position.y / size.y ); | ||
// transform the vertex back to world space | ||
decalVertex.position.applyMatrix4( projectorMatrix ); | ||
// now create vertex and normal buffer data | ||
vertices.push( decalVertex.position.x, decalVertex.position.y, decalVertex.position.z ); | ||
@@ -114,2 +137,3 @@ normals.push( decalVertex.normal.x, decalVertex.normal.y, decalVertex.normal.z ); | ||
// transform the vertex to world space, then to projector space | ||
vertex.applyMatrix4( mesh.matrixWorld ); | ||
@@ -125,3 +149,5 @@ vertex.applyMatrix4( projectorMatrixInverse ); | ||
const outVertices = []; | ||
const s = 0.5 * Math.abs( size.dot( plane ) ); // a single iteration clips one face, | ||
const s = 0.5 * Math.abs( size.dot( plane ) ); | ||
// a single iteration clips one face, | ||
// which consists of three consecutive 'DecalVertex' objects | ||
@@ -141,6 +167,7 @@ | ||
const v2Out = d2 > 0; | ||
const v3Out = d3 > 0; // calculate, how many vertices of the face lie outside of the clipping plane | ||
const v3Out = d3 > 0; | ||
// calculate, how many vertices of the face lie outside of the clipping plane | ||
total = ( v1Out ? 1 : 0 ) + ( v2Out ? 1 : 0 ) + ( v3Out ? 1 : 0 ); | ||
switch ( total ) { | ||
@@ -152,2 +179,3 @@ | ||
// the entire face lies inside of the plane, no clipping needed | ||
outVertices.push( inVertices[ i ] ); | ||
@@ -164,2 +192,3 @@ outVertices.push( inVertices[ i + 1 ] ); | ||
// one vertex lies outside of the plane, perform clipping | ||
if ( v1Out ) { | ||
@@ -213,2 +242,3 @@ | ||
// two vertices lies outside of the plane, perform clipping | ||
if ( ! v1Out ) { | ||
@@ -255,2 +285,3 @@ | ||
// the entire face lies outside of the plane, so let's discard the corresponding vertices | ||
break; | ||
@@ -273,3 +304,5 @@ | ||
const s0 = d0 / ( d0 - d1 ); | ||
const v = new DecalVertex( new THREE.Vector3( v0.position.x + s0 * ( v1.position.x - v0.position.x ), v0.position.y + s0 * ( v1.position.y - v0.position.y ), v0.position.z + s0 * ( v1.position.z - v0.position.z ) ), new THREE.Vector3( v0.normal.x + s0 * ( v1.normal.x - v0.normal.x ), v0.normal.y + s0 * ( v1.normal.y - v0.normal.y ), v0.normal.z + s0 * ( v1.normal.z - v0.normal.z ) ) ); // need to clip more values (texture coordinates)? do it this way: | ||
const v = new DecalVertex( new THREE.Vector3( v0.position.x + s0 * ( v1.position.x - v0.position.x ), v0.position.y + s0 * ( v1.position.y - v0.position.y ), v0.position.z + s0 * ( v1.position.z - v0.position.z ) ), new THREE.Vector3( v0.normal.x + s0 * ( v1.normal.x - v0.normal.x ), v0.normal.y + s0 * ( v1.normal.y - v0.normal.y ), v0.normal.z + s0 * ( 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 ); | ||
@@ -283,4 +316,5 @@ | ||
} // helper | ||
} | ||
// helper | ||
@@ -295,3 +329,2 @@ class DecalVertex { | ||
} | ||
clone() { | ||
@@ -298,0 +331,0 @@ |
@@ -110,10 +110,11 @@ ( function () { | ||
this.isLightningStrike = true; | ||
this.type = 'LightningStrike'; // Set parameters, and set undefined parameters to default values | ||
this.type = 'LightningStrike'; | ||
this.init( LightningStrike.copyParameters( rayParameters, rayParameters ) ); // Creates and populates the mesh | ||
// Set parameters, and set undefined parameters to default values | ||
this.init( LightningStrike.copyParameters( rayParameters, rayParameters ) ); | ||
// Creates and populates the mesh | ||
this.createMesh(); | ||
} | ||
static createRandomGenerator() { | ||
@@ -123,3 +124,2 @@ | ||
const seeds = []; | ||
for ( let i = 0; i < numSeeds; i ++ ) { | ||
@@ -154,3 +154,2 @@ | ||
} | ||
static copyParameters( dest = {}, source = {} ) { | ||
@@ -173,5 +172,9 @@ | ||
dest.sourceOffset = source.sourceOffset !== undefined ? vecCopy( source.sourceOffset ) : new THREE.Vector3( 0, 100, 0 ), dest.destOffset = source.destOffset !== undefined ? vecCopy( source.destOffset ) : new THREE.Vector3( 0, 0, 0 ), dest.timeScale = source.timeScale !== undefined ? source.timeScale : 1, dest.roughness = source.roughness !== undefined ? source.roughness : 0.9, dest.straightness = source.straightness !== undefined ? source.straightness : 0.7, dest.up0 = source.up0 !== undefined ? vecCopy( source.up0 ) : new THREE.Vector3( 0, 0, 1 ); | ||
dest.up1 = source.up1 !== undefined ? vecCopy( source.up1 ) : new THREE.Vector3( 0, 0, 1 ), dest.radius0 = source.radius0 !== undefined ? source.radius0 : 1, dest.radius1 = source.radius1 !== undefined ? source.radius1 : 1, dest.radius0Factor = source.radius0Factor !== undefined ? source.radius0Factor : 0.5, dest.radius1Factor = source.radius1Factor !== undefined ? source.radius1Factor : 0.2, dest.minRadius = source.minRadius !== undefined ? source.minRadius : 0.2, // These parameters should not be changed after lightning creation. They can be changed but the ray will change its form abruptly: | ||
dest.isEternal = source.isEternal !== undefined ? source.isEternal : source.birthTime === undefined || source.deathTime === undefined, dest.birthTime = source.birthTime, dest.deathTime = source.deathTime, dest.propagationTimeFactor = source.propagationTimeFactor !== undefined ? source.propagationTimeFactor : 0.1, dest.vanishingTimeFactor = source.vanishingTimeFactor !== undefined ? source.vanishingTimeFactor : 0.9, dest.subrayPeriod = source.subrayPeriod !== undefined ? source.subrayPeriod : 4, dest.subrayDutyCycle = source.subrayDutyCycle !== undefined ? source.subrayDutyCycle : 0.6; // These parameters cannot change after lightning creation: | ||
dest.up1 = source.up1 !== undefined ? vecCopy( source.up1 ) : new THREE.Vector3( 0, 0, 1 ), dest.radius0 = source.radius0 !== undefined ? source.radius0 : 1, dest.radius1 = source.radius1 !== undefined ? source.radius1 : 1, dest.radius0Factor = source.radius0Factor !== undefined ? source.radius0Factor : 0.5, dest.radius1Factor = source.radius1Factor !== undefined ? source.radius1Factor : 0.2, dest.minRadius = source.minRadius !== undefined ? source.minRadius : 0.2, | ||
// These parameters should not be changed after lightning creation. They can be changed but the ray will change its form abruptly: | ||
dest.isEternal = source.isEternal !== undefined ? source.isEternal : source.birthTime === undefined || source.deathTime === undefined, dest.birthTime = source.birthTime, dest.deathTime = source.deathTime, dest.propagationTimeFactor = source.propagationTimeFactor !== undefined ? source.propagationTimeFactor : 0.1, dest.vanishingTimeFactor = source.vanishingTimeFactor !== undefined ? source.vanishingTimeFactor : 0.9, dest.subrayPeriod = source.subrayPeriod !== undefined ? source.subrayPeriod : 4, dest.subrayDutyCycle = source.subrayDutyCycle !== undefined ? source.subrayDutyCycle : 0.6; | ||
// These parameters cannot change after lightning creation: | ||
dest.maxIterations = source.maxIterations !== undefined ? source.maxIterations : 9; | ||
@@ -187,11 +190,8 @@ dest.isStatic = source.isStatic !== undefined ? source.isStatic : false; | ||
} | ||
update( time ) { | ||
if ( this.isStatic ) return; | ||
if ( this.rayParameters.isEternal || this.rayParameters.birthTime <= time && time <= this.rayParameters.deathTime ) { | ||
this.updateMesh( time ); | ||
if ( time < this.subrays[ 0 ].endPropagationTime ) { | ||
@@ -216,3 +216,2 @@ | ||
this.visible = false; | ||
if ( time < this.rayParameters.birthTime ) { | ||
@@ -231,8 +230,10 @@ | ||
} | ||
init( rayParameters ) { | ||
// Init all the state from the parameters | ||
this.rayParameters = rayParameters; // These parameters cannot change after lightning creation: | ||
this.rayParameters = rayParameters; | ||
// These parameters cannot change after lightning creation: | ||
this.maxIterations = rayParameters.maxIterations !== undefined ? Math.floor( rayParameters.maxIterations ) : 9; | ||
@@ -249,4 +250,5 @@ rayParameters.maxIterations = this.maxIterations; | ||
this.generateUVs = rayParameters.generateUVs !== undefined ? rayParameters.generateUVs : false; | ||
rayParameters.generateUVs = this.generateUVs; // Random generator | ||
rayParameters.generateUVs = this.generateUVs; | ||
// Random generator | ||
if ( rayParameters.randomGenerator !== undefined ) { | ||
@@ -256,3 +258,2 @@ | ||
this.seedGenerator = rayParameters.randomGenerator; | ||
if ( rayParameters.noiseSeed !== undefined ) { | ||
@@ -269,5 +270,5 @@ | ||
} // Ray creation callbacks | ||
} | ||
// Ray creation callbacks | ||
if ( rayParameters.onDecideSubrayCreation !== undefined ) { | ||
@@ -280,3 +281,2 @@ | ||
this.createDefaultSubrayCreationCallbacks(); | ||
if ( rayParameters.onSubrayCreation !== undefined ) { | ||
@@ -288,4 +288,5 @@ | ||
} // Internal state | ||
} | ||
// Internal state | ||
@@ -297,3 +298,2 @@ this.state = LightningStrike.RAY_INITIALIZED; | ||
this.subrays = []; | ||
for ( let i = 0; i < this.maxSubrays; i ++ ) { | ||
@@ -306,3 +306,2 @@ | ||
this.raySegments = []; | ||
for ( let i = 0; i < this.maxRaySegments; i ++ ) { | ||
@@ -334,4 +333,5 @@ | ||
this.simplexY = new THREE.SimplexNoise( this.seedGenerator ); | ||
this.simplexZ = new THREE.SimplexNoise( this.seedGenerator ); // Temp vectors | ||
this.simplexZ = new THREE.SimplexNoise( this.seedGenerator ); | ||
// Temp vectors | ||
this.forwards = new THREE.Vector3(); | ||
@@ -348,3 +348,2 @@ this.forwardsFill = new THREE.Vector3(); | ||
} | ||
createMesh() { | ||
@@ -357,3 +356,2 @@ | ||
this.indices = new Uint32Array( maxIndices ); | ||
if ( this.generateUVs ) { | ||
@@ -363,5 +361,5 @@ | ||
} // Populate the mesh | ||
} | ||
// Populate the mesh | ||
this.fillMesh( 0 ); | ||
@@ -371,3 +369,2 @@ this.setIndex( new THREE.Uint32BufferAttribute( this.indices, 1 ) ); | ||
this.setAttribute( 'position', this.positionAttribute ); | ||
if ( this.generateUVs ) { | ||
@@ -384,3 +381,2 @@ | ||
this.positionAttribute.usage = THREE.DynamicDrawUsage; | ||
if ( this.generateUVs ) { | ||
@@ -392,8 +388,7 @@ | ||
} // Store buffers for later modification | ||
} | ||
// Store buffers for later modification | ||
this.vertices = this.positionAttribute.array; | ||
this.indices = this.index.array; | ||
if ( this.generateUVs ) { | ||
@@ -406,3 +401,2 @@ | ||
} | ||
updateMesh( time ) { | ||
@@ -414,3 +408,2 @@ | ||
this.positionAttribute.needsUpdate = true; | ||
if ( this.generateUVs ) { | ||
@@ -423,3 +416,2 @@ | ||
} | ||
fillMesh( time ) { | ||
@@ -435,6 +427,6 @@ | ||
const subray = scope.currentSubray; | ||
if ( time < subray.birthTime ) { | ||
//&& ( ! this.rayParameters.isEternal || scope.currentSubray.recursion > 0 ) ) { | ||
return; | ||
@@ -445,2 +437,3 @@ | ||
// Eternal rays don't propagate nor vanish, but its subrays do | ||
scope.createPrism( segment ); | ||
@@ -454,2 +447,3 @@ scope.onDecideSubrayCreation( segment, scope ); | ||
// Ray propagation has arrived to this segment | ||
scope.createPrism( segment ); | ||
@@ -463,2 +457,3 @@ scope.onDecideSubrayCreation( segment, scope ); | ||
// Ray is steady (nor propagating nor vanishing) | ||
scope.createPrism( segment ); | ||
@@ -472,2 +467,3 @@ scope.onDecideSubrayCreation( segment, scope ); | ||
// Segment has not yet vanished | ||
scope.createPrism( segment ); | ||
@@ -484,3 +480,2 @@ | ||
} | ||
addNewSubray() { | ||
@@ -491,3 +486,2 @@ | ||
} | ||
initSubray( subray, rayParameters ) { | ||
@@ -513,3 +507,2 @@ | ||
} | ||
fractalRay( time, segmentCallback ) { | ||
@@ -519,6 +512,8 @@ | ||
this.currentSegmentCallback = segmentCallback; | ||
this.numSubrays = 0; // Add the top level subray | ||
this.numSubrays = 0; | ||
this.initSubray( this.addNewSubray(), this.rayParameters ); // Process all subrays that are being generated until consuming all of them | ||
// Add the top level subray | ||
this.initSubray( this.addNewSubray(), this.rayParameters ); | ||
// Process all subrays that are being generated until consuming all of them | ||
for ( let subrayIndex = 0; subrayIndex < this.numSubrays; subrayIndex ++ ) { | ||
@@ -559,3 +554,2 @@ | ||
} | ||
fractalRayRecursive( segment ) { | ||
@@ -569,8 +563,7 @@ | ||
} // Interpolation | ||
} | ||
// Interpolation | ||
this.forwards.subVectors( segment.pos1, segment.pos0 ); | ||
let lForwards = this.forwards.length(); | ||
if ( lForwards < 0.000001 ) { | ||
@@ -588,8 +581,11 @@ | ||
this.middleLinPos.lerpVectors( segment.linPos0, segment.linPos1, 0.5 ); | ||
const p = this.middleLinPos; // Noise | ||
const p = this.middleLinPos; | ||
// Noise | ||
this.newPos.set( this.simplexX.noise4d( p.x, p.y, p.z, timeDimension ), this.simplexY.noise4d( p.x, p.y, p.z, timeDimension ), this.simplexZ.noise4d( p.x, p.y, p.z, timeDimension ) ); | ||
this.newPos.multiplyScalar( segment.positionVariationFactor * lForwards ); | ||
this.newPos.add( this.middlePos ); // Recursion | ||
this.newPos.add( this.middlePos ); | ||
// Recursion | ||
const newSegment1 = this.getNewSegment(); | ||
@@ -626,8 +622,7 @@ newSegment1.pos0.copy( segment.pos0 ); | ||
} | ||
createPrism( segment ) { | ||
// Creates one triangular prism and its vertices at the segment | ||
this.forwardsFill.subVectors( segment.pos1, segment.pos0 ).normalize(); | ||
if ( this.isInitialSegment ) { | ||
@@ -644,6 +639,6 @@ | ||
} | ||
createTriangleVerticesWithoutUVs( pos, up, forwards, radius ) { | ||
// Create an equilateral triangle (only vertices) | ||
this.side.crossVectors( up, forwards ).multiplyScalar( radius * LightningStrike.COS30DEG ); | ||
@@ -668,6 +663,6 @@ this.down.copy( up ).multiplyScalar( - radius * LightningStrike.SIN30DEG ); | ||
} | ||
createTriangleVerticesWithUVs( pos, up, forwards, radius, u ) { | ||
// Create an equilateral triangle (only vertices) | ||
this.side.crossVectors( up, forwards ).multiplyScalar( radius * LightningStrike.COS30DEG ); | ||
@@ -699,7 +694,4 @@ this.down.copy( up ).multiplyScalar( - radius * LightningStrike.SIN30DEG ); | ||
} | ||
createPrismFaces( vertex /*, index*/ ) { | ||
createPrismFaces( vertex | ||
/*, index*/ | ||
) { | ||
const indices = this.indices; | ||
@@ -727,10 +719,9 @@ vertex = this.currentVertex - 6; | ||
} | ||
createDefaultSubrayCreationCallbacks() { | ||
const random1 = this.randomGenerator.random; | ||
this.onDecideSubrayCreation = function ( segment, lightningStrike ) { | ||
// Decide subrays creation at parent (sub)ray segment | ||
const subray = lightningStrike.currentSubray; | ||
@@ -745,6 +736,6 @@ const period = lightningStrike.rayParameters.subrayPeriod; | ||
let probability = 0; | ||
if ( isActive ) { | ||
probability = lightningStrike.subrayProbability; // Distribution test: probability *= segment.fraction0 > 0.5 && segment.fraction0 < 0.9 ? 1 / 0.4 : 0; | ||
probability = lightningStrike.subrayProbability; | ||
// Distribution test: probability *= segment.fraction0 > 0.5 && segment.fraction0 < 0.9 ? 1 / 0.4 : 0; | ||
@@ -769,3 +760,2 @@ } | ||
childSubray.deathTime = childSubray.birthTime + period * dutyCycle; | ||
if ( ! lightningStrike.rayParameters.isEternal && subray.recursion == 0 ) { | ||
@@ -794,6 +784,6 @@ | ||
const vec4Up = new THREE.Vector3(); | ||
this.onSubrayCreation = function ( segment, parentSubray, childSubray, lightningStrike ) { | ||
// Decide childSubray origin and destination positions (pos0 and pos1) and possibly other properties of childSubray | ||
// Just use the default cone position generator | ||
@@ -807,2 +797,3 @@ lightningStrike.subrayCylinderPosition( segment, parentSubray, childSubray, 0.5, 0.6, 0.2 ); | ||
// Sets childSubray pos0 and pos1 in a cone | ||
childSubray.pos0.copy( segment.pos0 ); | ||
@@ -824,2 +815,3 @@ vec1Pos.subVectors( parentSubray.pos1, parentSubray.pos0 ); | ||
// Sets childSubray pos0 and pos1 in a cylinder | ||
childSubray.pos0.copy( segment.pos0 ); | ||
@@ -839,3 +831,2 @@ vec1Pos.subVectors( parentSubray.pos1, parentSubray.pos0 ); | ||
} | ||
createSubray() { | ||
@@ -867,3 +858,2 @@ | ||
} | ||
createSegment() { | ||
@@ -887,3 +877,2 @@ | ||
} | ||
getNewSegment() { | ||
@@ -894,3 +883,2 @@ | ||
} | ||
copy( source ) { | ||
@@ -903,3 +891,2 @@ | ||
} | ||
clone() { | ||
@@ -911,5 +898,5 @@ | ||
} // Ray states | ||
} | ||
// Ray states | ||
LightningStrike.RAY_INITIALIZED = 0; | ||
@@ -916,0 +903,0 @@ LightningStrike.RAY_UNBORN = 1; |
@@ -14,3 +14,2 @@ ( function () { | ||
let x, z; | ||
if ( u < Math.PI ) { | ||
@@ -60,2 +59,3 @@ | ||
// volumetric mobius strip | ||
u *= Math.PI; | ||
@@ -76,2 +76,3 @@ t *= 2 * Math.PI; | ||
}; | ||
/********************************************* | ||
@@ -93,3 +94,2 @@ * | ||
const position = new THREE.Vector3(); | ||
function ParametricTube( u, v, target ) { | ||
@@ -103,3 +103,2 @@ | ||
const cx = - radius * Math.cos( v ); // TODO: Hack: Negating it so it faces outside. | ||
const cy = radius * Math.sin( v ); | ||
@@ -113,4 +112,6 @@ position.x += cx * normal.x + cy * binormal.x; | ||
super( ParametricTube, segments, segmentsRadius ); // proxy internals | ||
super( ParametricTube, segments, segmentsRadius ); | ||
// proxy internals | ||
this.tangents = tangents; | ||
@@ -128,2 +129,3 @@ this.normals = normals; | ||
}; | ||
/********************************************* | ||
@@ -134,3 +136,2 @@ * | ||
*********************************************/ | ||
ParametricGeometries.TorusKnotGeometry = class TorusKnotGeometry extends ParametricGeometries.TubeGeometry { | ||
@@ -155,3 +156,2 @@ | ||
} | ||
const segments = segmentsT; | ||
@@ -171,2 +171,3 @@ const radiusSegments = segmentsR; | ||
}; | ||
/********************************************* | ||
@@ -177,3 +178,2 @@ * | ||
*********************************************/ | ||
ParametricGeometries.SphereGeometry = class SphereGeometry extends THREE.ParametricGeometry { | ||
@@ -199,2 +199,3 @@ | ||
}; | ||
/********************************************* | ||
@@ -201,0 +202,0 @@ * |
@@ -7,3 +7,2 @@ ( function () { | ||
*/ | ||
class ParametricGeometry extends THREE.BufferGeometry { | ||
@@ -19,4 +18,6 @@ | ||
stacks: stacks | ||
}; // buffers | ||
}; | ||
// buffers | ||
const indices = []; | ||
@@ -31,16 +32,21 @@ const vertices = []; | ||
const pu = new THREE.Vector3(), | ||
pv = new THREE.Vector3(); // generate vertices, normals and uvs | ||
pv = new THREE.Vector3(); | ||
// generate vertices, normals and uvs | ||
const sliceCount = slices + 1; | ||
for ( let i = 0; i <= stacks; i ++ ) { | ||
const v = i / stacks; | ||
for ( let j = 0; j <= slices; j ++ ) { | ||
const u = j / slices; // vertex | ||
const u = j / slices; | ||
// vertex | ||
func( u, v, p0 ); | ||
vertices.push( p0.x, p0.y, p0.z ); // normal | ||
vertices.push( p0.x, p0.y, p0.z ); | ||
// normal | ||
// approximate tangent vectors via finite differences | ||
@@ -70,8 +76,11 @@ | ||
} // cross product of tangent vectors returns surface normal | ||
} | ||
// cross product of tangent vectors returns surface normal | ||
normal.crossVectors( pu, pv ).normalize(); | ||
normals.push( normal.x, normal.y, normal.z ); // uv | ||
normals.push( normal.x, normal.y, normal.z ); | ||
// uv | ||
uvs.push( u, v ); | ||
@@ -81,4 +90,5 @@ | ||
} // generate indices | ||
} | ||
// generate indices | ||
@@ -92,4 +102,6 @@ for ( let i = 0; i < stacks; i ++ ) { | ||
const c = ( i + 1 ) * sliceCount + j + 1; | ||
const d = ( i + 1 ) * sliceCount + j; // faces one and two | ||
const d = ( i + 1 ) * sliceCount + j; | ||
// faces one and two | ||
indices.push( a, b, d ); | ||
@@ -100,4 +112,5 @@ indices.push( b, c, d ); | ||
} // build geometry | ||
} | ||
// build geometry | ||
@@ -104,0 +117,0 @@ this.setIndex( indices ); |
( function () { | ||
const _tempNormal = new THREE.Vector3(); | ||
function getUv( faceDirVector, normal, uvAxis, projectionAxis, radius, sideLength ) { | ||
const totArcLength = 2 * Math.PI * radius / 4; // length of the planes between the arcs on each axis | ||
const totArcLength = 2 * Math.PI * radius / 4; | ||
// length of the planes between the arcs on each axis | ||
const centerLength = Math.max( sideLength - 2 * radius, 0 ); | ||
const halfArc = Math.PI / 4; // Get the vector projected onto the Y plane | ||
const halfArc = Math.PI / 4; | ||
// Get the vector projected onto the Y plane | ||
_tempNormal.copy( normal ); | ||
_tempNormal[ projectionAxis ] = 0; | ||
_tempNormal.normalize(); | ||
_tempNormal.normalize(); // total amount of UV space alloted to a single arc | ||
// total amount of UV space alloted to a single arc | ||
const arcUvRatio = 0.5 * totArcLength / ( totArcLength + centerLength ); | ||
const arcUvRatio = 0.5 * totArcLength / ( totArcLength + centerLength ); // the distance along one arc the point is at | ||
// the distance along one arc the point is at | ||
const arcAngleRatio = 1.0 - _tempNormal.angleTo( faceDirVector ) / halfArc; | ||
if ( Math.sign( _tempNormal[ uvAxis ] ) === 1 ) { | ||
@@ -42,7 +41,9 @@ | ||
// ensure segments is odd so we have a plane connecting the rounded corners | ||
segments = segments * 2 + 1; // ensure radius isn't bigger than shortest side | ||
segments = segments * 2 + 1; | ||
// ensure radius isn't bigger than shortest side | ||
radius = Math.min( width / 2, height / 2, depth / 2, radius ); | ||
super( 1, 1, 1, segments, segments, segments ); // if we just have one segment we're the same as a regular box | ||
super( 1, 1, 1, segments, segments, segments ); | ||
// if we just have one segment we're the same as a regular box | ||
if ( segments === 1 ) return; | ||
@@ -53,4 +54,6 @@ const geometry2 = this.toNonIndexed(); | ||
this.attributes.normal = geometry2.attributes.normal; | ||
this.attributes.uv = geometry2.attributes.uv; // | ||
this.attributes.uv = geometry2.attributes.uv; | ||
// | ||
const position = new THREE.Vector3(); | ||
@@ -65,3 +68,2 @@ const normal = new THREE.Vector3(); | ||
const halfSegmentSize = 0.5 / segments; | ||
for ( let i = 0, j = 0; i < positions.length; i += 3, j += 2 ) { | ||
@@ -82,3 +84,2 @@ | ||
const side = Math.floor( i / faceTris ); | ||
switch ( side ) { | ||
@@ -88,2 +89,3 @@ | ||
// right | ||
// generate UVs along Z then Y | ||
@@ -94,5 +96,5 @@ faceDirVector.set( 1, 0, 0 ); | ||
break; | ||
case 1: | ||
// left | ||
// generate UVs along Z then Y | ||
@@ -103,5 +105,5 @@ faceDirVector.set( - 1, 0, 0 ); | ||
break; | ||
case 2: | ||
// top | ||
// generate UVs along X then Z | ||
@@ -112,5 +114,5 @@ faceDirVector.set( 0, 1, 0 ); | ||
break; | ||
case 3: | ||
// bottom | ||
// generate UVs along X then Z | ||
@@ -121,5 +123,5 @@ faceDirVector.set( 0, - 1, 0 ); | ||
break; | ||
case 4: | ||
// front | ||
// generate UVs along X then Y | ||
@@ -130,5 +132,5 @@ faceDirVector.set( 0, 0, 1 ); | ||
break; | ||
case 5: | ||
// back | ||
// generate UVs along X then Y | ||
@@ -135,0 +137,0 @@ faceDirVector.set( 0, 0, - 1 ); |
@@ -56,19 +56,16 @@ ( function () { | ||
// 32 * 4 * 4 Bezier spline patches | ||
const 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*/ | ||
const 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 ]; | ||
const 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 ]; | ||
super(); // number of segments per patch | ||
super(); | ||
segments = Math.max( 2, Math.floor( segments ) ); // Jim Blinn scaled the teapot down in size by about 1.3 for | ||
// number of segments per patch | ||
segments = Math.max( 2, Math.floor( segments ) ); | ||
// Jim Blinn scaled the teapot down in size by about 1.3 for | ||
// some rendering tests. He liked the new proportions that he kept | ||
@@ -80,10 +77,11 @@ // the data in this form. The model was distributed with these new | ||
// value given, we use it here. | ||
const blinnScale = 1.3; | ||
const blinnScale = 1.3; // scale the size to be the real scaling factor | ||
// scale the size to be the real scaling factor | ||
const maxHeight = 3.15 * ( blinn ? 1 : blinnScale ); | ||
const maxHeight2 = maxHeight / 2; | ||
const trueSize = size / maxHeight2; // Number of elements depends on what is needed. Subtract degenerate | ||
const trueSize = size / maxHeight2; | ||
// Number of elements depends on what is needed. Subtract degenerate | ||
// triangles at tip of bottom and lid out in advance. | ||
let numTriangles = bottom ? ( 8 * segments - 4 ) * segments : 0; | ||
@@ -99,4 +97,5 @@ numTriangles += lid ? ( 16 * segments - 4 ) * segments : 0; | ||
const normals = new Float32Array( numVertices * 3 ); | ||
const uvs = new Float32Array( numVertices * 2 ); // Bezier form | ||
const uvs = new Float32Array( numVertices * 2 ); | ||
// Bezier form | ||
const ms = new THREE.Matrix4(); | ||
@@ -108,5 +107,6 @@ 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 ); | ||
const dsp = []; | ||
const dtp = []; // M * G * M matrix, sort of see | ||
const dtp = []; | ||
// M * G * M matrix, sort of see | ||
// http://www.cs.helsinki.fi/group/goa/mallinnus/curves/surfaces.html | ||
const mgm = []; | ||
@@ -133,8 +133,9 @@ const vert = []; | ||
const mst = ms.clone(); | ||
mst.transpose(); // internal function: test if triangle has any matching vertices; | ||
mst.transpose(); | ||
// internal function: test if triangle has any matching vertices; | ||
// if so, don't save triangle, since it won't display anything. | ||
const notDegenerate = ( vtx1, vtx2, vtx3 ) => // if any vertex matches, return false | ||
const notDegenerate = ( vtx1, vtx2, vtx3 ) => | ||
// if any vertex matches, return false | ||
! ( 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 ( let i = 0; i < 3; i ++ ) { | ||
@@ -154,3 +155,2 @@ | ||
let indexCount = 0; | ||
for ( let surf = minPatches; surf < maxPatches; surf ++ ) { | ||
@@ -171,5 +171,6 @@ | ||
// 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 | ||
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 ) { | ||
@@ -182,6 +183,6 @@ | ||
} // Blinn "fixed" the teapot by dividing Z by blinnScale, and that's the | ||
} | ||
// 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 ) { | ||
@@ -201,14 +202,14 @@ | ||
} // step along, get points, and output | ||
} | ||
// step along, get points, and output | ||
for ( let sstep = 0; sstep <= segments; sstep ++ ) { | ||
const s = sstep / segments; | ||
for ( let tstep = 0; tstep <= segments; tstep ++ ) { | ||
const t = tstep / segments; // point from basis | ||
const t = tstep / segments; | ||
// point from basis | ||
// get power vectors and their derivatives | ||
for ( p = 4, sval = tval = 1.0; p --; ) { | ||
@@ -220,3 +221,2 @@ | ||
tval *= t; | ||
if ( p === 3 ) { | ||
@@ -241,4 +241,5 @@ | ||
vdsp.fromArray( dsp ); | ||
vdtp.fromArray( dtp ); // do for x,y,z | ||
vdtp.fromArray( dtp ); | ||
// do for x,y,z | ||
for ( let i = 0; i < 3; i ++ ) { | ||
@@ -249,4 +250,5 @@ | ||
tcoord.applyMatrix4( mgm[ i ] ); | ||
vert[ i ] = tcoord.dot( vtp ); // get s and t tangent vectors | ||
vert[ i ] = tcoord.dot( vtp ); | ||
// get s and t tangent vectors | ||
tcoord = vdsp.clone(); | ||
@@ -259,10 +261,11 @@ tcoord.applyMatrix4( mgm[ i ] ); | ||
} // find normal | ||
} | ||
// 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 | ||
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 ) { | ||
@@ -278,5 +281,5 @@ | ||
} // store it all | ||
} | ||
// store it all | ||
vertices[ vertCount ++ ] = trueSize * vert[ 0 ]; | ||
@@ -293,5 +296,5 @@ vertices[ vertCount ++ ] = trueSize * ( vert[ 2 ] - maxHeight2 ); | ||
} // save the faces | ||
} | ||
// save the faces | ||
for ( let sstep = 0; sstep < segments; sstep ++ ) { | ||
@@ -304,5 +307,6 @@ | ||
const v3 = v2 + vertPerRow; | ||
const v4 = v1 + vertPerRow; // Normals and UVs cannot be shared. Without clone(), you can see the consequences | ||
const v4 = v1 + vertPerRow; | ||
// Normals and UVs cannot be shared. Without clone(), you can see the consequences | ||
// of sharing if you call geometry.applyMatrix4( matrix ). | ||
if ( notDegenerate( v1, v2, v3 ) ) { | ||
@@ -326,5 +330,5 @@ | ||
} // increment only if a surface was used | ||
} | ||
// increment only if a surface was used | ||
surfCount ++; | ||
@@ -331,0 +335,0 @@ |
@@ -19,3 +19,2 @@ ( function () { | ||
*/ | ||
class TextGeometry extends THREE.ExtrudeGeometry { | ||
@@ -26,3 +25,2 @@ | ||
const font = parameters.font; | ||
if ( font === undefined ) { | ||
@@ -34,6 +32,10 @@ | ||
const shapes = font.generateShapes( text, parameters.size ); // translate parameters to THREE.ExtrudeGeometry API | ||
const shapes = font.generateShapes( text, parameters.size ); | ||
parameters.depth = parameters.height !== undefined ? parameters.height : 50; // defaults | ||
// translate parameters to THREE.ExtrudeGeometry API | ||
parameters.depth = parameters.height !== undefined ? parameters.height : 50; | ||
// defaults | ||
if ( parameters.bevelThickness === undefined ) parameters.bevelThickness = 10; | ||
@@ -40,0 +42,0 @@ if ( parameters.bevelSize === undefined ) parameters.bevelSize = 8; |
@@ -14,2 +14,3 @@ ( function () { | ||
// by reference | ||
intensity: { | ||
@@ -30,3 +31,2 @@ value: lightProbe.intensity | ||
} | ||
dispose() { | ||
@@ -38,3 +38,2 @@ | ||
} | ||
onBeforeRender() { | ||
@@ -41,0 +40,0 @@ |
@@ -7,4 +7,15 @@ ( function () { | ||
super( new THREE.BufferGeometry(), new THREE.LineBasicMaterial( { | ||
color: color, | ||
toneMapped: false | ||
} ) ); | ||
this.octree = octree; | ||
this.color = color; | ||
this.type = 'OctreeHelper'; | ||
this.update(); | ||
} | ||
update() { | ||
const vertices = []; | ||
function traverse( tree ) { | ||
@@ -18,9 +29,6 @@ | ||
vertices.push( min.x, max.y, max.z ); // 0, 1 | ||
vertices.push( min.x, max.y, max.z ); | ||
vertices.push( min.x, min.y, max.z ); // 1, 2 | ||
vertices.push( min.x, min.y, max.z ); | ||
vertices.push( max.x, min.y, max.z ); // 2, 3 | ||
vertices.push( max.x, min.y, max.z ); | ||
@@ -31,9 +39,6 @@ vertices.push( max.x, max.y, max.z ); // 3, 0 | ||
vertices.push( min.x, max.y, min.z ); // 4, 5 | ||
vertices.push( min.x, max.y, min.z ); | ||
vertices.push( min.x, min.y, min.z ); // 5, 6 | ||
vertices.push( min.x, min.y, min.z ); | ||
vertices.push( max.x, min.y, min.z ); // 6, 7 | ||
vertices.push( max.x, min.y, min.z ); | ||
@@ -44,9 +49,6 @@ vertices.push( max.x, max.y, min.z ); // 7, 4 | ||
vertices.push( max.x, max.y, min.z ); // 0, 4 | ||
vertices.push( min.x, max.y, max.z ); | ||
vertices.push( min.x, max.y, min.z ); // 1, 5 | ||
vertices.push( min.x, min.y, max.z ); | ||
vertices.push( min.x, min.y, min.z ); // 2, 6 | ||
vertices.push( max.x, min.y, max.z ); | ||
@@ -61,15 +63,15 @@ vertices.push( max.x, min.y, min.z ); // 3, 7 | ||
traverse( octree.subTrees ); | ||
const geometry = new THREE.BufferGeometry(); | ||
geometry.setAttribute( 'position', new THREE.Float32BufferAttribute( vertices, 3 ) ); | ||
super( geometry, new THREE.LineBasicMaterial( { | ||
color: color, | ||
toneMapped: false | ||
} ) ); | ||
this.octree = octree; | ||
this.color = color; | ||
this.type = 'OctreeHelper'; | ||
traverse( this.octree.subTrees ); | ||
this.geometry.dispose(); | ||
this.geometry = new THREE.BufferGeometry(); | ||
this.geometry.setAttribute( 'position', new THREE.Float32BufferAttribute( vertices, 3 ) ); | ||
} | ||
dispose() { | ||
this.geometry.dispose(); | ||
this.material.dispose(); | ||
} | ||
} | ||
@@ -76,0 +78,0 @@ |
@@ -26,3 +26,2 @@ ( function () { | ||
} | ||
update() { | ||
@@ -44,4 +43,6 @@ | ||
const positionAttribute = geometry.attributes.position; | ||
geometry.clearGroups(); // | ||
geometry.clearGroups(); | ||
// | ||
function generateSegment( from, to, divisions, materialIndex ) { | ||
@@ -52,3 +53,2 @@ | ||
count ++; | ||
for ( i = from; i < to; i += step ) { | ||
@@ -68,9 +68,12 @@ | ||
} // | ||
} | ||
// | ||
generateSegment( - halfConeOuterAngle, - halfConeInnerAngle, divisionsOuterAngle, 0 ); | ||
generateSegment( - halfConeInnerAngle, halfConeInnerAngle, divisionsInnerAngle, 1 ); | ||
generateSegment( halfConeInnerAngle, halfConeOuterAngle, divisionsOuterAngle, 0 ); // | ||
generateSegment( halfConeInnerAngle, halfConeOuterAngle, divisionsOuterAngle, 0 ); | ||
// | ||
positionAttribute.needsUpdate = true; | ||
@@ -80,3 +83,2 @@ if ( coneInnerAngle === coneOuterAngle ) this.material[ 0 ].visible = false; | ||
} | ||
dispose() { | ||
@@ -83,0 +85,0 @@ |
@@ -21,4 +21,5 @@ ( function () { | ||
this.color = color; // optional hardwired color for the helper | ||
this.type = 'RectAreaLightHelper'; | ||
this.type = 'RectAreaLightHelper'; // | ||
// | ||
@@ -35,7 +36,5 @@ const positions2 = [ 1, 1, 0, - 1, 1, 0, - 1, - 1, 0, 1, 1, 0, - 1, - 1, 0, 1, - 1, 0 ]; | ||
} | ||
updateMatrixWorld() { | ||
this.scale.set( 0.5 * this.light.width, 0.5 * this.light.height, 1 ); | ||
if ( this.color !== undefined ) { | ||
@@ -48,4 +47,5 @@ | ||
this.material.color.copy( this.light.color ).multiplyScalar( this.light.intensity ); // prevent hue shift | ||
this.material.color.copy( this.light.color ).multiplyScalar( this.light.intensity ); | ||
// prevent hue shift | ||
const c = this.material.color; | ||
@@ -56,5 +56,5 @@ const max = Math.max( c.r, c.g, c.b ); | ||
} // ignore world scale on light | ||
} | ||
// ignore world scale on light | ||
this.matrixWorld.extractRotation( this.light.matrixWorld ).scale( this.scale ).copyPosition( this.light.matrixWorld ); | ||
@@ -64,3 +64,2 @@ this.children[ 0 ].matrixWorld.copy( this.matrixWorld ); | ||
} | ||
dispose() { | ||
@@ -67,0 +66,0 @@ |
( function () { | ||
const _v1 = new THREE.Vector3(); | ||
const _v2 = new THREE.Vector3(); | ||
const _normalMatrix = new THREE.Matrix3(); | ||
class VertexNormalsHelper extends THREE.LineSegments { | ||
@@ -23,4 +20,6 @@ | ||
this.size = size; | ||
this.type = 'VertexNormalsHelper'; // | ||
this.type = 'VertexNormalsHelper'; | ||
// | ||
this.matrixAutoUpdate = false; | ||
@@ -30,14 +29,12 @@ this.update(); | ||
} | ||
update() { | ||
this.object.updateMatrixWorld( true ); | ||
_normalMatrix.getNormalMatrix( this.object.matrixWorld ); | ||
const matrixWorld = this.object.matrixWorld; | ||
const position = this.geometry.attributes.position; // | ||
const position = this.geometry.attributes.position; | ||
// | ||
const objGeometry = this.object.geometry; | ||
if ( objGeometry ) { | ||
@@ -47,12 +44,11 @@ | ||
const objNorm = objGeometry.attributes.normal; | ||
let idx = 0; // for simplicity, ignore index and drawcalls, and render every normal | ||
let idx = 0; | ||
// for simplicity, ignore index and drawcalls, and render every normal | ||
for ( let j = 0, jl = objPos.count; j < jl; j ++ ) { | ||
_v1.fromBufferAttribute( objPos, j ).applyMatrix4( matrixWorld ); | ||
_v2.fromBufferAttribute( objNorm, j ); | ||
_v2.applyMatrix3( _normalMatrix ).normalize().multiplyScalar( this.size ).add( _v1 ); | ||
position.setXYZ( idx, _v1.x, _v1.y, _v1.z ); | ||
@@ -70,3 +66,9 @@ idx = idx + 1; | ||
} | ||
dispose() { | ||
this.geometry.dispose(); | ||
this.material.dispose(); | ||
} | ||
} | ||
@@ -73,0 +75,0 @@ |
( function () { | ||
const _v1 = new THREE.Vector3(); | ||
const _v2 = new THREE.Vector3(); | ||
class VertexTangentsHelper extends THREE.LineSegments { | ||
@@ -21,4 +19,6 @@ | ||
this.size = size; | ||
this.type = 'VertexTangentsHelper'; // | ||
this.type = 'VertexTangentsHelper'; | ||
// | ||
this.matrixAutoUpdate = false; | ||
@@ -28,3 +28,2 @@ this.update(); | ||
} | ||
update() { | ||
@@ -34,17 +33,18 @@ | ||
const matrixWorld = this.object.matrixWorld; | ||
const position = this.geometry.attributes.position; // | ||
const position = this.geometry.attributes.position; | ||
// | ||
const objGeometry = this.object.geometry; | ||
const objPos = objGeometry.attributes.position; | ||
const objTan = objGeometry.attributes.tangent; | ||
let idx = 0; // for simplicity, ignore index and drawcalls, and render every tangent | ||
let idx = 0; | ||
// for simplicity, ignore index and drawcalls, and render every tangent | ||
for ( let j = 0, jl = objPos.count; j < jl; j ++ ) { | ||
_v1.fromBufferAttribute( objPos, j ).applyMatrix4( matrixWorld ); | ||
_v2.fromBufferAttribute( objTan, j ); | ||
_v2.transformDirection( matrixWorld ).multiplyScalar( this.size ).add( _v1 ); | ||
position.setXYZ( idx, _v1.x, _v1.y, _v1.z ); | ||
@@ -60,3 +60,9 @@ idx = idx + 1; | ||
} | ||
dispose() { | ||
this.geometry.dispose(); | ||
this.material.dispose(); | ||
} | ||
} | ||
@@ -63,0 +69,0 @@ |
( function () { | ||
const vpTemp = new THREE.Vector4(); | ||
class ViewHelper extends THREE.Object3D { | ||
@@ -74,3 +73,2 @@ | ||
point.applyQuaternion( editorCamera.quaternion ); | ||
if ( point.x >= 0 ) { | ||
@@ -110,4 +108,5 @@ | ||
} // | ||
} | ||
// | ||
@@ -128,3 +127,2 @@ const x = dom.offsetWidth - dim; | ||
let radius = 0; | ||
this.handleClick = function ( event ) { | ||
@@ -140,3 +138,2 @@ | ||
const intersects = raycaster.intersectObjects( interactiveObjects ); | ||
if ( intersects.length > 0 ) { | ||
@@ -161,9 +158,12 @@ | ||
const step = delta * turnRate; | ||
const focusPoint = this.controls.center; // animate position by doing a slerp and then scaling the position on the unit sphere | ||
const focusPoint = this.controls.center; | ||
// animate position by doing a slerp and then scaling the position on the unit sphere | ||
q1.rotateTowards( q2, step ); | ||
editorCamera.position.set( 0, 0, 1 ).applyQuaternion( q1 ).multiplyScalar( radius ).add( focusPoint ); // animate orientation | ||
editorCamera.position.set( 0, 0, 1 ).applyQuaternion( q1 ).multiplyScalar( radius ).add( focusPoint ); | ||
// animate orientation | ||
editorCamera.quaternion.rotateTowards( targetQuaternion, step ); | ||
if ( q1.angleTo( q2 ) === 0 ) { | ||
@@ -177,2 +177,23 @@ | ||
this.dispose = function () { | ||
geometry.dispose(); | ||
xAxis.material.dispose(); | ||
yAxis.material.dispose(); | ||
zAxis.material.dispose(); | ||
posXAxisHelper.material.map.dispose(); | ||
posYAxisHelper.material.map.dispose(); | ||
posZAxisHelper.material.map.dispose(); | ||
negXAxisHelper.material.map.dispose(); | ||
negYAxisHelper.material.map.dispose(); | ||
negZAxisHelper.material.map.dispose(); | ||
posXAxisHelper.material.dispose(); | ||
posYAxisHelper.material.dispose(); | ||
posZAxisHelper.material.dispose(); | ||
negXAxisHelper.material.dispose(); | ||
negYAxisHelper.material.dispose(); | ||
negZAxisHelper.material.dispose(); | ||
}; | ||
function prepareAnimationData( object, focusPoint ) { | ||
@@ -186,3 +207,2 @@ | ||
break; | ||
case 'posY': | ||
@@ -192,3 +212,2 @@ targetPosition.set( 0, 1, 0 ); | ||
break; | ||
case 'posZ': | ||
@@ -198,3 +217,2 @@ targetPosition.set( 0, 0, 1 ); | ||
break; | ||
case 'negX': | ||
@@ -204,3 +222,2 @@ targetPosition.set( - 1, 0, 0 ); | ||
break; | ||
case 'negY': | ||
@@ -210,3 +227,2 @@ targetPosition.set( 0, - 1, 0 ); | ||
break; | ||
case 'negZ': | ||
@@ -216,8 +232,8 @@ targetPosition.set( 0, 0, - 1 ); | ||
break; | ||
default: | ||
console.error( 'ViewHelper: Invalid axis.' ); | ||
} // | ||
} | ||
// | ||
@@ -254,3 +270,2 @@ radius = editorCamera.position.distanceTo( focusPoint ); | ||
context.fill(); | ||
if ( text !== null ) { | ||
@@ -257,0 +272,0 @@ |
@@ -15,3 +15,2 @@ ( function () { | ||
super( geometry, material ); | ||
function onEvent( event ) { | ||
@@ -27,3 +26,2 @@ | ||
this.addEventListener( 'click', onEvent ); | ||
this.dispose = function () { | ||
@@ -34,2 +32,3 @@ | ||
material.map.dispose(); | ||
canvases.delete( dom ); | ||
this.removeEventListener( 'mousedown', onEvent ); | ||
@@ -45,3 +44,2 @@ this.removeEventListener( 'mousemove', onEvent ); | ||
} | ||
class HTMLTexture extends THREE.CanvasTexture { | ||
@@ -56,4 +54,5 @@ | ||
this.minFilter = THREE.LinearFilter; | ||
this.magFilter = THREE.LinearFilter; // Create an observer on the DOM, and run html2canvas update in the next loop | ||
this.magFilter = THREE.LinearFilter; | ||
// Create an observer on the DOM, and run html2canvas update in the next loop | ||
const observer = new MutationObserver( () => { | ||
@@ -79,3 +78,2 @@ | ||
} | ||
dispatchDOMEvent( event ) { | ||
@@ -90,3 +88,2 @@ | ||
} | ||
update() { | ||
@@ -99,3 +96,2 @@ | ||
} | ||
dispose() { | ||
@@ -114,7 +110,7 @@ | ||
} // | ||
} | ||
// | ||
const canvases = new WeakMap(); | ||
function html2canvas( element ) { | ||
@@ -124,3 +120,2 @@ | ||
const color = new THREE.Color(); | ||
function Clipper( context ) { | ||
@@ -130,3 +125,2 @@ | ||
let isClipping = false; | ||
function doClip() { | ||
@@ -146,3 +140,2 @@ | ||
maxY = Infinity; | ||
for ( let i = 0; i < clips.length; i ++ ) { | ||
@@ -221,3 +214,2 @@ | ||
const borderColor = style[ which + 'Color' ]; | ||
if ( borderWidth !== '0px' && borderStyle !== 'none' && borderColor !== 'transparent' && borderColor !== 'rgba(0, 0, 0, 0)' ) { | ||
@@ -242,6 +234,6 @@ | ||
height = 0; | ||
if ( element.nodeType === Node.TEXT_NODE ) { | ||
// text | ||
range.selectNode( element ); | ||
@@ -277,7 +269,8 @@ const rect = range.getBoundingClientRect(); | ||
height = rect.height; | ||
style = window.getComputedStyle( element ); // Get the border of the element used for fill and border | ||
style = window.getComputedStyle( element ); | ||
// Get the border of the element used for fill and border | ||
buildRectPath( x, y, width, height, parseFloat( style.borderRadius ) ); | ||
const backgroundColor = style.backgroundColor; | ||
if ( backgroundColor !== 'transparent' && backgroundColor !== 'rgba(0, 0, 0, 0)' ) { | ||
@@ -288,4 +281,5 @@ | ||
} // If all the borders match then stroke the round rectangle | ||
} | ||
// If all the borders match then stroke the round rectangle | ||
@@ -295,3 +289,2 @@ const borders = [ 'borderTop', 'borderLeft', 'borderBottom', 'borderRight' ]; | ||
let prevBorder = null; | ||
for ( const border of borders ) { | ||
@@ -313,4 +306,4 @@ | ||
// They all match so stroke the rectangle from before allows for border-radius | ||
const width = parseFloat( style.borderTopWidth ); | ||
if ( style.borderTopWidth !== '0px' && style.borderTopStyle !== 'none' && style.borderTopColor !== 'transparent' && style.borderTopColor !== 'rgba(0, 0, 0, 0)' ) { | ||
@@ -327,2 +320,3 @@ | ||
// Otherwise draw individual borders | ||
drawBorder( style, 'borderTop', x, y, width, 0 ); | ||
@@ -342,3 +336,2 @@ drawBorder( style, 'borderLeft', x, y, 0, height ); | ||
const accentTextColor = luminance < 0.5 ? 'white' : '#111111'; | ||
if ( element.type === 'radio' ) { | ||
@@ -352,3 +345,2 @@ | ||
context.stroke(); | ||
if ( element.checked ) { | ||
@@ -375,3 +367,2 @@ | ||
context.fill(); | ||
if ( element.checked ) { | ||
@@ -429,2 +420,3 @@ | ||
} | ||
/* | ||
@@ -436,3 +428,2 @@ // debug | ||
const isClipping = style.overflow === 'auto' || style.overflow === 'hidden'; | ||
@@ -445,3 +436,2 @@ if ( isClipping ) clipper.add( { | ||
} ); | ||
for ( let i = 0; i < element.childNodes.length; i ++ ) { | ||
@@ -459,3 +449,2 @@ | ||
let canvas = canvases.get( element ); | ||
if ( canvas === undefined ) { | ||
@@ -470,9 +459,12 @@ | ||
const context = canvas.getContext( '2d' | ||
/*, { alpha: false }*/ | ||
); | ||
const clipper = new Clipper( context ); // console.time( 'drawElement' ); | ||
const context = canvas.getContext( '2d' /*, { alpha: false }*/ ); | ||
drawElement( element ); // console.timeEnd( 'drawElement' ); | ||
const clipper = new Clipper( context ); | ||
// console.time( 'drawElement' ); | ||
drawElement( element ); | ||
// console.timeEnd( 'drawElement' ); | ||
return canvas; | ||
@@ -493,3 +485,2 @@ | ||
y = y * rect.height + rect.top; | ||
function traverse( element ) { | ||
@@ -500,7 +491,5 @@ | ||
const rect = element.getBoundingClientRect(); | ||
if ( x > rect.left && x < rect.right && y > rect.top && y < rect.bottom ) { | ||
element.dispatchEvent( new MouseEvent( event, mouseEventInit ) ); | ||
if ( element instanceof HTMLInputElement && element.type === 'range' && ( event === 'mousedown' || event === 'click' ) ) { | ||
@@ -507,0 +496,0 @@ |
( function () { | ||
const _pointer = new THREE.Vector2(); | ||
const _event = { | ||
@@ -9,3 +8,2 @@ type: '', | ||
}; | ||
class InteractiveGroup extends THREE.Group { | ||
@@ -18,6 +16,7 @@ | ||
const raycaster = new THREE.Raycaster(); | ||
const tempMatrix = new THREE.Matrix4(); // Pointer Events | ||
const tempMatrix = new THREE.Matrix4(); | ||
// Pointer Events | ||
const element = renderer.domElement; | ||
function onPointerEvent( event ) { | ||
@@ -31,3 +30,2 @@ | ||
const intersects = raycaster.intersectObjects( scope.children, false ); | ||
if ( intersects.length > 0 ) { | ||
@@ -39,5 +37,3 @@ | ||
_event.type = event.type; | ||
_event.data.set( uv.x, 1 - uv.y ); | ||
object.dispatchEvent( _event ); | ||
@@ -55,3 +51,5 @@ | ||
element.addEventListener( 'mousemove', onPointerEvent ); | ||
element.addEventListener( 'click', onPointerEvent ); // WebXR Controller Events | ||
element.addEventListener( 'click', onPointerEvent ); | ||
// WebXR Controller Events | ||
// TODO: Dispatch pointerevents too | ||
@@ -65,3 +63,2 @@ | ||
}; | ||
function onXRControllerEvent( event ) { | ||
@@ -74,3 +71,2 @@ | ||
const intersections = raycaster.intersectObjects( scope.children, false ); | ||
if ( intersections.length > 0 ) { | ||
@@ -82,5 +78,3 @@ | ||
_event.type = events[ event.type ]; | ||
_event.data.set( uv.x, 1 - uv.y ); | ||
object.dispatchEvent( _event ); | ||
@@ -87,0 +81,0 @@ |
@@ -8,37 +8,19 @@ ( function () { | ||
const _frustum = new THREE.Frustum(); | ||
const _center = new THREE.Vector3(); | ||
const _tmpPoint = new THREE.Vector3(); | ||
const _vecNear = new THREE.Vector3(); | ||
const _vecTopLeft = new THREE.Vector3(); | ||
const _vecTopRight = new THREE.Vector3(); | ||
const _vecDownRight = new THREE.Vector3(); | ||
const _vecDownLeft = new THREE.Vector3(); | ||
const _vecFarTopLeft = new THREE.Vector3(); | ||
const _vecFarTopRight = new THREE.Vector3(); | ||
const _vecFarDownRight = new THREE.Vector3(); | ||
const _vecFarDownLeft = new THREE.Vector3(); | ||
const _vectemp1 = new THREE.Vector3(); | ||
const _vectemp2 = new THREE.Vector3(); | ||
const _vectemp3 = new THREE.Vector3(); | ||
const _matrix = new THREE.Matrix4(); | ||
const _quaternion = new THREE.Quaternion(); | ||
const _scale = new THREE.Vector3(); | ||
class SelectionBox { | ||
@@ -57,3 +39,2 @@ | ||
} | ||
select( startPoint, endPoint ) { | ||
@@ -69,8 +50,9 @@ | ||
} | ||
updateFrustum( startPoint, endPoint ) { | ||
startPoint = startPoint || this.startPoint; | ||
endPoint = endPoint || this.endPoint; // Avoid invalid frustum | ||
endPoint = endPoint || this.endPoint; | ||
// Avoid invalid frustum | ||
if ( startPoint.x === endPoint.x ) { | ||
@@ -90,7 +72,5 @@ | ||
this.camera.updateMatrixWorld(); | ||
if ( this.camera.isPerspectiveCamera ) { | ||
_tmpPoint.copy( startPoint ); | ||
_tmpPoint.x = Math.min( startPoint.x, endPoint.x ); | ||
@@ -100,45 +80,23 @@ _tmpPoint.y = Math.max( startPoint.y, endPoint.y ); | ||
endPoint.y = Math.min( startPoint.y, endPoint.y ); | ||
_vecNear.setFromMatrixPosition( this.camera.matrixWorld ); | ||
_vecTopLeft.copy( _tmpPoint ); | ||
_vecTopRight.set( endPoint.x, _tmpPoint.y, 0 ); | ||
_vecDownRight.copy( endPoint ); | ||
_vecDownLeft.set( _tmpPoint.x, endPoint.y, 0 ); | ||
_vecTopLeft.unproject( this.camera ); | ||
_vecTopRight.unproject( this.camera ); | ||
_vecDownRight.unproject( this.camera ); | ||
_vecDownLeft.unproject( this.camera ); | ||
_vectemp1.copy( _vecTopLeft ).sub( _vecNear ); | ||
_vectemp2.copy( _vecTopRight ).sub( _vecNear ); | ||
_vectemp3.copy( _vecDownRight ).sub( _vecNear ); | ||
_vectemp1.normalize(); | ||
_vectemp2.normalize(); | ||
_vectemp3.normalize(); | ||
_vectemp1.multiplyScalar( this.deep ); | ||
_vectemp2.multiplyScalar( this.deep ); | ||
_vectemp3.multiplyScalar( this.deep ); | ||
_vectemp1.add( _vecNear ); | ||
_vectemp2.add( _vecNear ); | ||
_vectemp3.add( _vecNear ); | ||
const planes = _frustum.planes; | ||
@@ -159,35 +117,18 @@ planes[ 0 ].setFromCoplanarPoints( _vecNear, _vecTopLeft, _vecTopRight ); | ||
const down = Math.min( startPoint.y, endPoint.y ); | ||
_vecTopLeft.set( left, top, - 1 ); | ||
_vecTopRight.set( right, top, - 1 ); | ||
_vecDownRight.set( right, down, - 1 ); | ||
_vecDownLeft.set( left, down, - 1 ); | ||
_vecFarTopLeft.set( left, top, 1 ); | ||
_vecFarTopRight.set( right, top, 1 ); | ||
_vecFarDownRight.set( right, down, 1 ); | ||
_vecFarDownLeft.set( left, down, 1 ); | ||
_vecTopLeft.unproject( this.camera ); | ||
_vecTopRight.unproject( this.camera ); | ||
_vecDownRight.unproject( this.camera ); | ||
_vecDownLeft.unproject( this.camera ); | ||
_vecFarTopLeft.unproject( this.camera ); | ||
_vecFarTopRight.unproject( this.camera ); | ||
_vecFarDownRight.unproject( this.camera ); | ||
_vecFarDownLeft.unproject( this.camera ); | ||
const planes = _frustum.planes; | ||
@@ -209,3 +150,2 @@ planes[ 0 ].setFromCoplanarPoints( _vecTopLeft, _vecFarTopLeft, _vecFarTopRight ); | ||
} | ||
searchChildInFrustum( frustum, object ) { | ||
@@ -218,11 +158,7 @@ | ||
this.instances[ object.uuid ] = []; | ||
for ( let instanceId = 0; instanceId < object.count; instanceId ++ ) { | ||
object.getMatrixAt( instanceId, _matrix ); | ||
_matrix.decompose( _center, _quaternion, _scale ); | ||
_center.applyMatrix4( object.matrixWorld ); | ||
if ( frustum.containsPoint( _center ) ) { | ||
@@ -239,7 +175,4 @@ | ||
if ( object.geometry.boundingSphere === null ) object.geometry.computeBoundingSphere(); | ||
_center.copy( object.geometry.boundingSphere.center ); | ||
_center.applyMatrix4( object.matrixWorld ); | ||
if ( frustum.containsPoint( _center ) ) { | ||
@@ -246,0 +179,0 @@ |
@@ -15,3 +15,2 @@ ( function () { | ||
this.isDown = false; | ||
this.onPointerDown = function ( event ) { | ||
@@ -23,3 +22,2 @@ | ||
}.bind( this ); | ||
this.onPointerMove = function ( event ) { | ||
@@ -34,3 +32,2 @@ | ||
}.bind( this ); | ||
this.onPointerUp = function () { | ||
@@ -42,3 +39,2 @@ | ||
}.bind( this ); | ||
this.renderer.domElement.addEventListener( 'pointerdown', this.onPointerDown ); | ||
@@ -49,3 +45,2 @@ this.renderer.domElement.addEventListener( 'pointermove', this.onPointerMove ); | ||
} | ||
dispose() { | ||
@@ -58,3 +53,2 @@ | ||
} | ||
onSelectStart( event ) { | ||
@@ -72,3 +66,2 @@ | ||
} | ||
onSelectMove( event ) { | ||
@@ -87,3 +80,2 @@ | ||
} | ||
onSelectOver() { | ||
@@ -90,0 +82,0 @@ |
@@ -15,3 +15,2 @@ ( function () { | ||
const shCoefficients = sh.coefficients; | ||
for ( let faceIndex = 0; faceIndex < 6; faceIndex ++ ) { | ||
@@ -32,15 +31,17 @@ | ||
const pixelSize = 2 / imageWidth; | ||
for ( let i = 0, il = data.length; i < il; i += 4 ) { | ||
// RGBA assumed | ||
// pixel color | ||
color.setRGB( data[ i ] / 255, data[ i + 1 ] / 255, data[ i + 2 ] / 255 ); // convert to linear color space | ||
color.setRGB( data[ i ] / 255, data[ i + 1 ] / 255, data[ i + 2 ] / 255 ); | ||
convertColorToLinear( color, cubeTexture.encoding ); // pixel coordinate on unit cube | ||
// convert to linear color space | ||
convertColorToLinear( color, cubeTexture.encoding ); | ||
// pixel coordinate on unit cube | ||
const pixelIndex = i / 4; | ||
const col = - 1 + ( pixelIndex % imageWidth + 0.5 ) * pixelSize; | ||
const row = 1 - ( Math.floor( pixelIndex / imageWidth ) + 0.5 ) * pixelSize; | ||
switch ( faceIndex ) { | ||
@@ -51,19 +52,14 @@ | ||
break; | ||
case 1: | ||
coord.set( 1, row, col ); | ||
break; | ||
case 2: | ||
coord.set( - col, 1, - row ); | ||
break; | ||
case 3: | ||
coord.set( - col, - 1, row ); | ||
break; | ||
case 4: | ||
coord.set( - col, row, 1 ); | ||
break; | ||
case 5: | ||
@@ -73,13 +69,17 @@ coord.set( col, row, - 1 ); | ||
} // weight assigned to this pixel | ||
} | ||
// weight assigned to this pixel | ||
const lengthSq = coord.lengthSq(); | ||
const weight = 4 / ( Math.sqrt( lengthSq ) * lengthSq ); | ||
totalWeight += weight; // direction vector to this pixel | ||
totalWeight += weight; | ||
dir.copy( coord ).normalize(); // evaluate SH basis functions in direction dir | ||
// direction vector to this pixel | ||
dir.copy( coord ).normalize(); | ||
THREE.SphericalHarmonics3.getBasisAt( dir, shBasis ); // accummuulate | ||
// evaluate SH basis functions in direction dir | ||
THREE.SphericalHarmonics3.getBasisAt( dir, shBasis ); | ||
// accummuulate | ||
for ( let j = 0; j < 9; j ++ ) { | ||
@@ -95,7 +95,6 @@ | ||
} // normalize | ||
} | ||
// normalize | ||
const norm = 4 * Math.PI / totalWeight; | ||
for ( let j = 0; j < 9; j ++ ) { | ||
@@ -112,3 +111,2 @@ | ||
} | ||
static fromCubeRenderTarget( renderer, cubeRenderTarget ) { | ||
@@ -124,23 +122,23 @@ | ||
const shCoefficients = sh.coefficients; | ||
for ( let faceIndex = 0; faceIndex < 6; faceIndex ++ ) { | ||
const imageWidth = cubeRenderTarget.width; // assumed to be square | ||
const data = new Uint8Array( imageWidth * imageWidth * 4 ); | ||
renderer.readRenderTargetPixels( cubeRenderTarget, 0, 0, imageWidth, imageWidth, data, faceIndex ); | ||
const pixelSize = 2 / imageWidth; | ||
for ( let i = 0, il = data.length; i < il; i += 4 ) { | ||
// RGBA assumed | ||
// pixel color | ||
color.setRGB( data[ i ] / 255, data[ i + 1 ] / 255, data[ i + 2 ] / 255 ); // convert to linear color space | ||
color.setRGB( data[ i ] / 255, data[ i + 1 ] / 255, data[ i + 2 ] / 255 ); | ||
convertColorToLinear( color, cubeRenderTarget.texture.encoding ); // pixel coordinate on unit cube | ||
// convert to linear color space | ||
convertColorToLinear( color, cubeRenderTarget.texture.encoding ); | ||
// pixel coordinate on unit cube | ||
const pixelIndex = i / 4; | ||
const col = - 1 + ( pixelIndex % imageWidth + 0.5 ) * pixelSize; | ||
const row = 1 - ( Math.floor( pixelIndex / imageWidth ) + 0.5 ) * pixelSize; | ||
switch ( faceIndex ) { | ||
@@ -151,19 +149,14 @@ | ||
break; | ||
case 1: | ||
coord.set( - 1, row, col ); | ||
break; | ||
case 2: | ||
coord.set( col, 1, - row ); | ||
break; | ||
case 3: | ||
coord.set( col, - 1, row ); | ||
break; | ||
case 4: | ||
coord.set( col, row, 1 ); | ||
break; | ||
case 5: | ||
@@ -173,13 +166,17 @@ coord.set( - col, row, - 1 ); | ||
} // weight assigned to this pixel | ||
} | ||
// weight assigned to this pixel | ||
const lengthSq = coord.lengthSq(); | ||
const weight = 4 / ( Math.sqrt( lengthSq ) * lengthSq ); | ||
totalWeight += weight; // direction vector to this pixel | ||
totalWeight += weight; | ||
dir.copy( coord ).normalize(); // evaluate SH basis functions in direction dir | ||
// direction vector to this pixel | ||
dir.copy( coord ).normalize(); | ||
THREE.SphericalHarmonics3.getBasisAt( dir, shBasis ); // accummuulate | ||
// evaluate SH basis functions in direction dir | ||
THREE.SphericalHarmonics3.getBasisAt( dir, shBasis ); | ||
// accummuulate | ||
for ( let j = 0; j < 9; j ++ ) { | ||
@@ -195,7 +192,6 @@ | ||
} // normalize | ||
} | ||
// normalize | ||
const norm = 4 * Math.PI / totalWeight; | ||
for ( let j = 0; j < 9; j ++ ) { | ||
@@ -214,3 +210,2 @@ | ||
} | ||
function convertColorToLinear( color, encoding ) { | ||
@@ -223,6 +218,4 @@ | ||
break; | ||
case THREE.LinearEncoding: | ||
break; | ||
default: | ||
@@ -229,0 +222,0 @@ console.warn( 'WARNING: LightProbeGenerator convertColorToLinear() encountered an unsupported encoding.' ); |
@@ -12,9 +12,8 @@ ( function () { | ||
} | ||
setPositions( array ) { | ||
// converts [ x1, y1, z1, x2, y2, z2, ... ] to pairs format | ||
const length = array.length - 3; | ||
const points = new Float32Array( 2 * length ); | ||
for ( let i = 0; i < length; i += 3 ) { | ||
@@ -35,9 +34,8 @@ | ||
} | ||
setColors( array ) { | ||
// converts [ r1, g1, b1, r2, g2, b2, ... ] to pairs format | ||
const length = array.length - 3; | ||
const colors = new Float32Array( 2 * length ); | ||
for ( let i = 0; i < length; i += 3 ) { | ||
@@ -58,3 +56,2 @@ | ||
} | ||
fromLine( line ) { | ||
@@ -64,2 +61,3 @@ | ||
this.setPositions( geometry.attributes.position.array ); // assumes non-indexed | ||
// set colors, maybe | ||
@@ -66,0 +64,0 @@ |
@@ -37,9 +37,7 @@ ( function () { | ||
} // todo FIX - maybe change to totalSize | ||
}; | ||
}; | ||
THREE.ShaderLib[ 'line' ] = { | ||
uniforms: THREE.UniformsUtils.merge( [ THREE.UniformsLib.common, THREE.UniformsLib.fog, THREE.UniformsLib.line ] ), | ||
vertexShader: | ||
/* glsl */ | ||
` | ||
vertexShader: /* glsl */` | ||
#include <common> | ||
@@ -273,5 +271,3 @@ #include <color_pars_vertex> | ||
`, | ||
fragmentShader: | ||
/* glsl */ | ||
` | ||
fragmentShader: /* glsl */` | ||
uniform vec3 diffuse; | ||
@@ -437,3 +433,2 @@ uniform float opacity; | ||
}; | ||
class LineMaterial extends THREE.ShaderMaterial { | ||
@@ -449,4 +444,4 @@ | ||
clipping: true // required for clipping support | ||
} ); | ||
} ); | ||
this.isLineMaterial = true; | ||
@@ -508,3 +503,2 @@ Object.defineProperties( this, { | ||
}, | ||
set( value ) { | ||
@@ -529,3 +523,2 @@ | ||
} | ||
}, | ||
@@ -532,0 +525,0 @@ dashScale: { |
( function () { | ||
const _start = new THREE.Vector3(); | ||
const _end = new THREE.Vector3(); | ||
const _start4 = new THREE.Vector4(); | ||
const _end4 = new THREE.Vector4(); | ||
const _ssOrigin = new THREE.Vector4(); | ||
const _ssOrigin3 = new THREE.Vector3(); | ||
const _mvMatrix = new THREE.Matrix4(); | ||
const _line = new THREE.Line3(); | ||
const _closestPoint = new THREE.Vector3(); | ||
const _box = new THREE.Box3(); | ||
const _sphere = new THREE.Sphere(); | ||
const _clipToWorldVector = new THREE.Vector4(); | ||
let _ray, _instanceStart, _instanceEnd, _lineWidth; | ||
let _ray, _instanceStart, _instanceEnd, _lineWidth; // Returns the margin required to expand by in world space given the distance from the camera, | ||
// Returns the margin required to expand by in world space given the distance from the camera, | ||
// line width, resolution, and camera projection | ||
function getWorldSpaceHalfWidth( camera, distance, resolution ) { | ||
@@ -37,12 +25,7 @@ | ||
_clipToWorldVector.set( 0, 0, - distance, 1.0 ).applyMatrix4( camera.projectionMatrix ); | ||
_clipToWorldVector.multiplyScalar( 1.0 / _clipToWorldVector.w ); | ||
_clipToWorldVector.x = _lineWidth / resolution.width; | ||
_clipToWorldVector.y = _lineWidth / resolution.height; | ||
_clipToWorldVector.applyMatrix4( camera.projectionMatrixInverse ); | ||
_clipToWorldVector.multiplyScalar( 1.0 / _clipToWorldVector.w ); | ||
return Math.abs( Math.max( _clipToWorldVector.x, _clipToWorldVector.y ) ); | ||
@@ -57,12 +40,7 @@ | ||
_line.start.fromBufferAttribute( _instanceStart, i ); | ||
_line.end.fromBufferAttribute( _instanceEnd, i ); | ||
const pointOnLine = new THREE.Vector3(); | ||
const point = new THREE.Vector3(); | ||
_ray.distanceSqToSegment( _line.start, _line.end, point, pointOnLine ); | ||
const isInside = point.distanceTo( pointOnLine ) < _lineWidth * 0.5; | ||
if ( isInside ) { | ||
@@ -96,43 +74,36 @@ | ||
const instanceEnd = geometry.attributes.instanceEnd; | ||
const near = - camera.near; // | ||
const near = - camera.near; | ||
// | ||
// pick a point 1 unit out along the ray to avoid the ray origin | ||
// sitting at the camera origin which will cause "w" to be 0 when | ||
// applying the projection matrix. | ||
_ray.at( 1, _ssOrigin ); | ||
_ray.at( 1, _ssOrigin ); // ndc space [ - 1.0, 1.0 ] | ||
// ndc space [ - 1.0, 1.0 ] | ||
_ssOrigin.w = 1; | ||
_ssOrigin.applyMatrix4( camera.matrixWorldInverse ); | ||
_ssOrigin.applyMatrix4( projectionMatrix ); | ||
_ssOrigin.multiplyScalar( 1 / _ssOrigin.w ); | ||
_ssOrigin.multiplyScalar( 1 / _ssOrigin.w ); // screen space | ||
// screen space | ||
_ssOrigin.x *= resolution.x / 2; | ||
_ssOrigin.y *= resolution.y / 2; | ||
_ssOrigin.z = 0; | ||
_ssOrigin3.copy( _ssOrigin ); | ||
_mvMatrix.multiplyMatrices( camera.matrixWorldInverse, matrixWorld ); | ||
for ( let i = 0, l = instanceStart.count; i < l; i ++ ) { | ||
_start4.fromBufferAttribute( instanceStart, i ); | ||
_end4.fromBufferAttribute( instanceEnd, i ); | ||
_start4.w = 1; | ||
_end4.w = 1; // camera space | ||
_end4.w = 1; | ||
// camera space | ||
_start4.applyMatrix4( _mvMatrix ); | ||
_end4.applyMatrix4( _mvMatrix ); | ||
_end4.applyMatrix4( _mvMatrix ); // skip the segment if it's entirely behind the camera | ||
// skip the segment if it's entirely behind the camera | ||
const isBehindCameraNear = _start4.z > near && _end4.z > near; | ||
if ( isBehindCameraNear ) { | ||
@@ -142,5 +113,5 @@ | ||
} // trim the segment if it extends behind camera near | ||
} | ||
// trim the segment if it extends behind camera near | ||
if ( _start4.z > near ) { | ||
@@ -150,3 +121,2 @@ | ||
const t = ( _start4.z - near ) / deltaDist; | ||
_start4.lerp( _end4, t ); | ||
@@ -158,56 +128,43 @@ | ||
const t = ( _end4.z - near ) / deltaDist; | ||
_end4.lerp( _start4, t ); | ||
} // clip space | ||
} | ||
// clip space | ||
_start4.applyMatrix4( projectionMatrix ); | ||
_end4.applyMatrix4( projectionMatrix ); | ||
_end4.applyMatrix4( projectionMatrix ); // ndc space [ - 1.0, 1.0 ] | ||
// ndc space [ - 1.0, 1.0 ] | ||
_start4.multiplyScalar( 1 / _start4.w ); | ||
_end4.multiplyScalar( 1 / _end4.w ); | ||
_end4.multiplyScalar( 1 / _end4.w ); // screen space | ||
// screen space | ||
_start4.x *= resolution.x / 2; | ||
_start4.y *= resolution.y / 2; | ||
_end4.x *= resolution.x / 2; | ||
_end4.y *= resolution.y / 2; // create 2d segment | ||
_end4.y *= resolution.y / 2; | ||
// create 2d segment | ||
_line.start.copy( _start4 ); | ||
_line.start.z = 0; | ||
_line.end.copy( _end4 ); | ||
_line.end.z = 0; | ||
_line.end.z = 0; // get closest point on ray to segment | ||
// get closest point on ray to segment | ||
const param = _line.closestPointToPointParameter( _ssOrigin3, true ); | ||
_line.at( param, _closestPoint ); | ||
_line.at( param, _closestPoint ); // check if the intersection point is within clip space | ||
// check if the intersection point is within clip space | ||
const zPos = THREE.MathUtils.lerp( _start4.z, _end4.z, param ); | ||
const isInClipSpace = zPos >= - 1 && zPos <= 1; | ||
const isInside = _ssOrigin3.distanceTo( _closestPoint ) < _lineWidth * 0.5; | ||
if ( isInClipSpace && isInside ) { | ||
_line.start.fromBufferAttribute( instanceStart, i ); | ||
_line.end.fromBufferAttribute( instanceEnd, i ); | ||
_line.start.applyMatrix4( matrixWorld ); | ||
_line.end.applyMatrix4( matrixWorld ); | ||
const pointOnLine = new THREE.Vector3(); | ||
const point = new THREE.Vector3(); | ||
_ray.distanceSqToSegment( _line.start, _line.end, point, pointOnLine ); | ||
intersects.push( { | ||
@@ -240,4 +197,5 @@ point: point, | ||
} // for backwards-compatibility, but could be a method of THREE.LineSegmentsGeometry... | ||
} | ||
// for backwards-compatibility, but could be a method of THREE.LineSegmentsGeometry... | ||
@@ -250,9 +208,6 @@ computeLineDistances() { | ||
const lineDistances = new Float32Array( 2 * instanceStart.count ); | ||
for ( let i = 0, j = 0, l = instanceStart.count; i < l; i ++, j += 2 ) { | ||
_start.fromBufferAttribute( instanceStart, i ); | ||
_end.fromBufferAttribute( instanceEnd, i ); | ||
lineDistances[ j ] = j === 0 ? 0 : lineDistances[ j - 1 ]; | ||
@@ -266,3 +221,2 @@ lineDistances[ j + 1 ] = lineDistances[ j ] + _start.distanceTo( _end ); | ||
geometry.setAttribute( 'instanceDistanceStart', new THREE.InterleavedBufferAttribute( instanceDistanceBuffer, 1, 0 ) ); // d0 | ||
geometry.setAttribute( 'instanceDistanceEnd', new THREE.InterleavedBufferAttribute( instanceDistanceBuffer, 1, 1 ) ); // d1 | ||
@@ -273,3 +227,2 @@ | ||
} | ||
raycast( raycaster, intersects ) { | ||
@@ -279,3 +232,2 @@ | ||
const camera = raycaster.camera; | ||
if ( camera === null && ! worldUnits ) { | ||
@@ -294,4 +246,5 @@ | ||
_instanceStart = geometry.attributes.instanceStart; | ||
_instanceEnd = geometry.attributes.instanceEnd; // check if we intersect the sphere bounds | ||
_instanceEnd = geometry.attributes.instanceEnd; | ||
// check if we intersect the sphere bounds | ||
if ( geometry.boundingSphere === null ) { | ||
@@ -303,7 +256,6 @@ | ||
_sphere.copy( geometry.boundingSphere ).applyMatrix4( matrixWorld ); // increase the sphere bounds by the worst case line screen space width | ||
_sphere.copy( geometry.boundingSphere ).applyMatrix4( matrixWorld ); | ||
// increase the sphere bounds by the worst case line screen space width | ||
let sphereMargin; | ||
if ( worldUnits ) { | ||
@@ -321,3 +273,2 @@ | ||
_sphere.radius += sphereMargin; | ||
if ( _ray.intersectsSphere( _sphere ) === false ) { | ||
@@ -327,5 +278,5 @@ | ||
} // check if we intersect the box bounds | ||
} | ||
// check if we intersect the box bounds | ||
if ( geometry.boundingBox === null ) { | ||
@@ -337,7 +288,6 @@ | ||
_box.copy( geometry.boundingBox ).applyMatrix4( matrixWorld ); // increase the box bounds by the worst case line width | ||
_box.copy( geometry.boundingBox ).applyMatrix4( matrixWorld ); | ||
// increase the box bounds by the worst case line width | ||
let boxMargin; | ||
if ( worldUnits ) { | ||
@@ -355,3 +305,2 @@ | ||
_box.expandByScalar( boxMargin ); | ||
if ( _ray.intersectsBox( _box ) === false ) { | ||
@@ -358,0 +307,0 @@ |
( function () { | ||
const _box = new THREE.Box3(); | ||
const _vector = new THREE.Vector3(); | ||
class LineSegmentsGeometry extends THREE.InstancedBufferGeometry { | ||
@@ -22,3 +20,2 @@ | ||
} | ||
applyMatrix4( matrix ) { | ||
@@ -28,3 +25,2 @@ | ||
const end = this.attributes.instanceEnd; | ||
if ( start !== undefined ) { | ||
@@ -53,7 +49,5 @@ | ||
} | ||
setPositions( array ) { | ||
let lineSegments; | ||
if ( array instanceof Float32Array ) { | ||
@@ -72,4 +66,4 @@ | ||
this.setAttribute( 'instanceStart', new THREE.InterleavedBufferAttribute( instanceBuffer, 3, 0 ) ); // xyz | ||
this.setAttribute( 'instanceEnd', new THREE.InterleavedBufferAttribute( instanceBuffer, 3, 3 ) ); // xyz | ||
this.setAttribute( 'instanceEnd', new THREE.InterleavedBufferAttribute( instanceBuffer, 3, 3 ) ); // xyz | ||
// | ||
@@ -82,7 +76,5 @@ | ||
} | ||
setColors( array ) { | ||
let colors; | ||
if ( array instanceof Float32Array ) { | ||
@@ -101,3 +93,2 @@ | ||
this.setAttribute( 'instanceColorStart', new THREE.InterleavedBufferAttribute( instanceColorBuffer, 3, 0 ) ); // rgb | ||
this.setAttribute( 'instanceColorEnd', new THREE.InterleavedBufferAttribute( instanceColorBuffer, 3, 3 ) ); // rgb | ||
@@ -108,3 +99,2 @@ | ||
} | ||
fromWireframeGeometry( geometry ) { | ||
@@ -116,3 +106,2 @@ | ||
} | ||
fromEdgesGeometry( geometry ) { | ||
@@ -124,11 +113,11 @@ | ||
} | ||
fromMesh( mesh ) { | ||
this.fromWireframeGeometry( new THREE.WireframeGeometry( mesh.geometry ) ); // set colors, maybe | ||
this.fromWireframeGeometry( new THREE.WireframeGeometry( mesh.geometry ) ); | ||
// set colors, maybe | ||
return this; | ||
} | ||
fromLineSegments( lineSegments ) { | ||
@@ -138,2 +127,3 @@ | ||
this.setPositions( geometry.attributes.position.array ); // assumes non-indexed | ||
// set colors, maybe | ||
@@ -144,3 +134,2 @@ | ||
} | ||
computeBoundingBox() { | ||
@@ -156,9 +145,6 @@ | ||
const end = this.attributes.instanceEnd; | ||
if ( start !== undefined && end !== undefined ) { | ||
this.boundingBox.setFromBufferAttribute( start ); | ||
_box.setFromBufferAttribute( end ); | ||
this.boundingBox.union( _box ); | ||
@@ -169,3 +155,2 @@ | ||
} | ||
computeBoundingSphere() { | ||
@@ -187,3 +172,2 @@ | ||
const end = this.attributes.instanceEnd; | ||
if ( start !== undefined && end !== undefined ) { | ||
@@ -194,11 +178,7 @@ | ||
let maxRadiusSq = 0; | ||
for ( let i = 0, il = start.count; i < il; i ++ ) { | ||
_vector.fromBufferAttribute( start, i ); | ||
maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( _vector ) ); | ||
_vector.fromBufferAttribute( end, i ); | ||
maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( _vector ) ); | ||
@@ -209,3 +189,2 @@ | ||
this.boundingSphere.radius = Math.sqrt( maxRadiusSq ); | ||
if ( isNaN( this.boundingSphere.radius ) ) { | ||
@@ -220,6 +199,6 @@ | ||
} | ||
toJSON() { | ||
toJSON() { // todo | ||
// todo | ||
} | ||
applyMatrix( matrix ) { | ||
@@ -226,0 +205,0 @@ |
( function () { | ||
const _start = new THREE.Vector3(); | ||
const _end = new THREE.Vector3(); | ||
class Wireframe extends THREE.Mesh { | ||
@@ -17,4 +15,5 @@ | ||
} // for backwards-compatibility, but could be a method of THREE.LineSegmentsGeometry... | ||
} | ||
// for backwards-compatibility, but could be a method of THREE.LineSegmentsGeometry... | ||
@@ -27,9 +26,6 @@ computeLineDistances() { | ||
const lineDistances = new Float32Array( 2 * instanceStart.count ); | ||
for ( let i = 0, j = 0, l = instanceStart.count; i < l; i ++, j += 2 ) { | ||
_start.fromBufferAttribute( instanceStart, i ); | ||
_end.fromBufferAttribute( instanceEnd, i ); | ||
lineDistances[ j ] = j === 0 ? 0 : lineDistances[ j - 1 ]; | ||
@@ -43,3 +39,2 @@ lineDistances[ j + 1 ] = lineDistances[ j ] + _start.distanceTo( _end ); | ||
geometry.setAttribute( 'instanceDistanceStart', new THREE.InterleavedBufferAttribute( instanceDistanceBuffer, 1, 0 ) ); // d0 | ||
geometry.setAttribute( 'instanceDistanceEnd', new THREE.InterleavedBufferAttribute( instanceDistanceBuffer, 1, 1 ) ); // d1 | ||
@@ -46,0 +41,0 @@ |
@@ -10,4 +10,6 @@ ( function () { | ||
this.type = 'WireframeGeometry2'; | ||
this.fromWireframeGeometry( new THREE.WireframeGeometry( geometry ) ); // set colors, maybe | ||
this.fromWireframeGeometry( new THREE.WireframeGeometry( geometry ) ); | ||
// set colors, maybe | ||
} | ||
@@ -14,0 +16,0 @@ |
( function () { | ||
const _taskCache = new WeakMap(); | ||
class Rhino3dmLoader extends THREE.Loader { | ||
@@ -24,3 +23,2 @@ | ||
} | ||
setLibraryPath( path ) { | ||
@@ -32,3 +30,2 @@ | ||
} | ||
setWorkerLimit( workerLimit ) { | ||
@@ -40,3 +37,2 @@ | ||
} | ||
load( url, onLoad, onProgress, onError ) { | ||
@@ -56,3 +52,2 @@ | ||
const cachedTask = _taskCache.get( buffer ); | ||
return cachedTask.promise.then( onLoad ).catch( onError ); | ||
@@ -72,3 +67,2 @@ | ||
} | ||
debug() { | ||
@@ -79,3 +73,2 @@ | ||
} | ||
decodeObjects( buffer, url ) { | ||
@@ -86,3 +79,2 @@ | ||
const taskCost = buffer.byteLength; | ||
const objectPending = this._getWorker( taskCost ).then( _worker => { | ||
@@ -102,4 +94,6 @@ | ||
buffer | ||
}, [ buffer ] ); // this.debug(); | ||
}, [ buffer ] ); | ||
// this.debug(); | ||
} ); | ||
@@ -111,6 +105,6 @@ | ||
} ); // Remove task from the task list. | ||
} ); | ||
// Remove task from the task list. | ||
// Note: replaced '.finally()' with '.catch().then()' block - iOS 11 support (#19416) | ||
objectPending.catch( () => true ).then( () => { | ||
@@ -120,8 +114,11 @@ | ||
this._releaseTask( worker, taskID ); //this.debug(); | ||
this._releaseTask( worker, taskID ); | ||
//this.debug(); | ||
} | ||
} ); // Cache the task result. | ||
} ); | ||
// Cache the task result. | ||
_taskCache.set( buffer, { | ||
@@ -131,7 +128,5 @@ url: url, | ||
} ); | ||
return objectPending; | ||
} | ||
parse( data, onLoad, onError ) { | ||
@@ -147,3 +142,2 @@ | ||
} | ||
_compareMaterials( material ) { | ||
@@ -158,3 +152,2 @@ | ||
mat.type = material.type; | ||
for ( let i = 0; i < this.materials.length; i ++ ) { | ||
@@ -170,3 +163,2 @@ | ||
_mat.type = m.type; | ||
if ( JSON.stringify( mat ) === JSON.stringify( _mat ) ) { | ||
@@ -184,3 +176,2 @@ | ||
} | ||
_createMaterial( material ) { | ||
@@ -201,3 +192,2 @@ | ||
const diffusecolor = new THREE.Color( _diffuseColor.r / 255.0, _diffuseColor.g / 255.0, _diffuseColor.b / 255.0 ); | ||
if ( _diffuseColor.r === 0 && _diffuseColor.g === 0 && _diffuseColor.b === 0 ) { | ||
@@ -209,4 +199,5 @@ | ||
} // console.log( material ); | ||
} | ||
// console.log( material ); | ||
@@ -221,11 +212,8 @@ const mat = new THREE.MeshStandardMaterial( { | ||
const textureLoader = new THREE.TextureLoader(); | ||
for ( let i = 0; i < material.textures.length; i ++ ) { | ||
const texture = material.textures[ i ]; | ||
if ( texture.image !== null ) { | ||
const map = textureLoader.load( texture.image ); | ||
switch ( texture.type ) { | ||
@@ -236,7 +224,5 @@ | ||
break; | ||
case 'Bump': | ||
mat.bumpMap = map; | ||
break; | ||
case 'Transparency': | ||
@@ -246,3 +232,2 @@ mat.alphaMap = map; | ||
break; | ||
case 'Emap': | ||
@@ -265,6 +250,6 @@ mat.envMap = map; | ||
} | ||
_createGeometry( data ) { | ||
// console.log(data); | ||
const object = new THREE.Object3D(); | ||
@@ -282,3 +267,2 @@ const instanceDefinitionObjects = []; | ||
const materials = data.materials; | ||
for ( let i = 0; i < objects.length; i ++ ) { | ||
@@ -288,3 +272,2 @@ | ||
const attributes = obj.attributes; | ||
switch ( obj.objectType ) { | ||
@@ -295,16 +278,11 @@ | ||
break; | ||
case 'InstanceReference': | ||
instanceReferences.push( obj ); | ||
break; | ||
default: | ||
let _object; | ||
if ( attributes.materialIndex >= 0 ) { | ||
const rMaterial = materials[ attributes.materialIndex ]; | ||
let material = this._createMaterial( rMaterial ); | ||
material = this._compareMaterials( material ); | ||
@@ -316,3 +294,2 @@ _object = this._createObject( obj, material ); | ||
const material = this._createMaterial(); | ||
_object = this._createObject( obj, material ); | ||
@@ -330,3 +307,2 @@ | ||
_object.visible = layer ? data.layers[ attributes.layerIndex ].visible : true; | ||
if ( attributes.isInstanceDefinitionObject ) { | ||
@@ -352,11 +328,8 @@ | ||
objects = []; | ||
for ( let j = 0; j < iDef.attributes.objectIds.length; j ++ ) { | ||
const objId = iDef.attributes.objectIds[ j ]; | ||
for ( let p = 0; p < instanceDefinitionObjects.length; p ++ ) { | ||
const idoId = instanceDefinitionObjects[ p ].userData.attributes.id; | ||
if ( objId === idoId ) { | ||
@@ -370,4 +343,5 @@ | ||
} // Currently clones geometry and does not take advantage of instancing | ||
} | ||
// Currently clones geometry and does not take advantage of instancing | ||
@@ -377,3 +351,2 @@ for ( let j = 0; j < instanceReferences.length; j ++ ) { | ||
const iRef = instanceReferences[ j ]; | ||
if ( iRef.geometry.parentIdefId === iDef.attributes.id ) { | ||
@@ -386,3 +359,2 @@ | ||
iRefObject.applyMatrix4( matrix ); | ||
for ( let p = 0; p < objects.length; p ++ ) { | ||
@@ -406,3 +378,2 @@ | ||
} | ||
_createObject( obj, mat ) { | ||
@@ -412,5 +383,3 @@ | ||
const attributes = obj.attributes; | ||
let geometry, material, _color, color; | ||
switch ( obj.objectType ) { | ||
@@ -421,3 +390,2 @@ | ||
geometry = loader.parse( obj.geometry ); | ||
if ( geometry.attributes.hasOwnProperty( 'color' ) ) { | ||
@@ -447,3 +415,2 @@ | ||
points.userData[ 'objectType' ] = obj.objectType; | ||
if ( attributes.name ) { | ||
@@ -456,3 +423,2 @@ | ||
return points; | ||
case 'Mesh': | ||
@@ -464,3 +430,2 @@ case 'Extrusion': | ||
geometry = loader.parse( obj.geometry ); | ||
if ( geometry.attributes.hasOwnProperty( 'color' ) ) { | ||
@@ -484,3 +449,2 @@ | ||
mesh.userData[ 'objectType' ] = obj.objectType; | ||
if ( attributes.name ) { | ||
@@ -493,3 +457,2 @@ | ||
return mesh; | ||
case 'Curve': | ||
@@ -506,3 +469,2 @@ geometry = loader.parse( obj.geometry ); | ||
lines.userData[ 'objectType' ] = obj.objectType; | ||
if ( attributes.name ) { | ||
@@ -515,3 +477,2 @@ | ||
return lines; | ||
case 'TextDot': | ||
@@ -551,3 +512,2 @@ geometry = obj.geometry; | ||
sprite.userData[ 'objectType' ] = obj.objectType; | ||
if ( attributes.name ) { | ||
@@ -560,7 +520,5 @@ | ||
return sprite; | ||
case 'Light': | ||
geometry = obj.geometry; | ||
let light; | ||
switch ( geometry.lightStyle.name ) { | ||
@@ -574,3 +532,2 @@ | ||
break; | ||
case 'LightStyle_WorldSpot': | ||
@@ -584,3 +541,2 @@ light = new THREE.SpotLight(); | ||
break; | ||
case 'LightStyle_WorldRectangular': | ||
@@ -595,3 +551,2 @@ light = new THREE.RectAreaLight(); | ||
break; | ||
case 'LightStyle_WorldDirectional': | ||
@@ -604,7 +559,5 @@ light = new THREE.DirectionalLight(); | ||
break; | ||
case 'LightStyle_WorldLinear': | ||
// not conversion exists, warning has already been printed to the console | ||
break; | ||
default: | ||
@@ -631,3 +584,2 @@ break; | ||
} | ||
_initLibrary() { | ||
@@ -644,4 +596,5 @@ | ||
} ); // Load rhino3dm WASM binary. | ||
} ); | ||
// Load rhino3dm WASM binary. | ||
const binaryLoader = new THREE.FileLoader( this.manager ); | ||
@@ -670,3 +623,2 @@ binaryLoader.setPath( this.libraryPath ); | ||
} | ||
_getWorker( taskCost ) { | ||
@@ -686,7 +638,5 @@ | ||
} ); | ||
worker.onmessage = e => { | ||
const message = e.data; | ||
switch ( message.type ) { | ||
@@ -698,13 +648,8 @@ | ||
break; | ||
case 'decode': | ||
worker._callbacks[ message.id ].resolve( message ); | ||
break; | ||
case 'error': | ||
worker._callbacks[ message.id ].reject( message ); | ||
break; | ||
default: | ||
@@ -736,3 +681,2 @@ console.error( 'THREE.Rhino3dmLoader: Unexpected message, "' + message.type + '"' ); | ||
} | ||
_releaseTask( worker, taskID ) { | ||
@@ -745,3 +689,2 @@ | ||
} | ||
dispose() { | ||
@@ -761,5 +704,5 @@ | ||
} | ||
/* WEB WORKER */ | ||
function Rhino3dmWorker() { | ||
@@ -771,7 +714,5 @@ | ||
let taskID; | ||
onmessage = function ( e ) { | ||
const message = e.data; | ||
switch ( message.type ) { | ||
@@ -799,3 +740,2 @@ | ||
break; | ||
case 'decode': | ||
@@ -842,15 +782,13 @@ taskID = message.id; | ||
const groups = []; | ||
const strings = []; //Handle objects | ||
const strings = []; | ||
//Handle objects | ||
const objs = doc.objects(); | ||
const cnt = objs.count; | ||
for ( let i = 0; i < cnt; i ++ ) { | ||
const _object = objs.get( i ); | ||
const object = extractObjectData( _object, doc ); | ||
_object.delete(); | ||
if ( object ) { | ||
@@ -862,6 +800,7 @@ | ||
} // Handle instance definitions | ||
} | ||
// Handle instance definitions | ||
// console.log( `Instance Definitions Count: ${doc.instanceDefinitions().count()}` ); | ||
for ( let i = 0; i < doc.instanceDefinitions().count(); i ++ ) { | ||
@@ -878,22 +817,19 @@ | ||
} // Handle materials | ||
} | ||
// Handle materials | ||
const textureTypes = [// rhino.TextureType.Bitmap, | ||
const textureTypes = [ | ||
// rhino.TextureType.Bitmap, | ||
rhino.TextureType.Diffuse, rhino.TextureType.Bump, rhino.TextureType.Transparency, rhino.TextureType.Opacity, rhino.TextureType.Emap ]; | ||
const pbrTextureTypes = [ rhino.TextureType.PBR_BaseColor, rhino.TextureType.PBR_Subsurface, rhino.TextureType.PBR_SubsurfaceScattering, rhino.TextureType.PBR_SubsurfaceScatteringRadius, rhino.TextureType.PBR_Metallic, rhino.TextureType.PBR_Specular, rhino.TextureType.PBR_SpecularTint, rhino.TextureType.PBR_Roughness, rhino.TextureType.PBR_Anisotropic, rhino.TextureType.PBR_Anisotropic_Rotation, rhino.TextureType.PBR_Sheen, rhino.TextureType.PBR_SheenTint, rhino.TextureType.PBR_Clearcoat, rhino.TextureType.PBR_ClearcoatBump, rhino.TextureType.PBR_ClearcoatRoughness, rhino.TextureType.PBR_OpacityIor, rhino.TextureType.PBR_OpacityRoughness, rhino.TextureType.PBR_Emission, rhino.TextureType.PBR_AmbientOcclusion, rhino.TextureType.PBR_Displacement ]; | ||
for ( let i = 0; i < doc.materials().count(); i ++ ) { | ||
const _material = doc.materials().get( i ); | ||
const _pbrMaterial = _material.physicallyBased(); | ||
let material = extractProperties( _material ); | ||
const textures = []; | ||
for ( let j = 0; j < textureTypes.length; j ++ ) { | ||
const _texture = _material.getTexture( textureTypes[ j ] ); | ||
if ( _texture ) { | ||
@@ -910,7 +846,4 @@ | ||
texture.wrapW = _texture.wrapW; | ||
const uvw = _texture.uvwTransform.toFloatArray( true ); | ||
texture.repeat = [ uvw[ 0 ], uvw[ 5 ] ]; | ||
if ( image ) { | ||
@@ -935,3 +868,2 @@ | ||
textures.push( texture ); | ||
_texture.delete(); | ||
@@ -944,3 +876,2 @@ | ||
material.textures = textures; | ||
if ( _pbrMaterial.supported ) { | ||
@@ -951,3 +882,2 @@ | ||
const _texture = _material.getTexture( pbrTextureTypes[ j ] ); | ||
if ( _texture ) { | ||
@@ -963,3 +893,2 @@ | ||
textures.push( texture ); | ||
_texture.delete(); | ||
@@ -977,9 +906,8 @@ | ||
materials.push( material ); | ||
_material.delete(); | ||
_pbrMaterial.delete(); | ||
} // Handle layers | ||
} | ||
// Handle layers | ||
@@ -989,10 +917,9 @@ for ( let i = 0; i < doc.layers().count(); i ++ ) { | ||
const _layer = doc.layers().get( i ); | ||
const layer = extractProperties( _layer ); | ||
layers.push( layer ); | ||
_layer.delete(); | ||
} // Handle views | ||
} | ||
// Handle views | ||
@@ -1002,10 +929,9 @@ for ( let i = 0; i < doc.views().count(); i ++ ) { | ||
const _view = doc.views().get( i ); | ||
const view = extractProperties( _view ); | ||
views.push( view ); | ||
_view.delete(); | ||
} // Handle named views | ||
} | ||
// Handle named views | ||
@@ -1015,10 +941,9 @@ for ( let i = 0; i < doc.namedViews().count(); i ++ ) { | ||
const _namedView = doc.namedViews().get( i ); | ||
const namedView = extractProperties( _namedView ); | ||
namedViews.push( namedView ); | ||
_namedView.delete(); | ||
} // Handle groups | ||
} | ||
// Handle groups | ||
@@ -1028,16 +953,20 @@ for ( let i = 0; i < doc.groups().count(); i ++ ) { | ||
const _group = doc.groups().get( i ); | ||
const group = extractProperties( _group ); | ||
groups.push( group ); | ||
_group.delete(); | ||
} // Handle settings | ||
} | ||
// Handle settings | ||
const settings = extractProperties( doc.settings() ); //TODO: Handle other document stuff like dimstyles, instance definitions, bitmaps etc. | ||
const settings = extractProperties( doc.settings() ); | ||
//TODO: Handle other document stuff like dimstyles, instance definitions, bitmaps etc. | ||
// Handle dimstyles | ||
// console.log( `Dimstyle Count: ${doc.dimstyles().count()}` ); | ||
// Handle bitmaps | ||
// console.log( `Bitmap Count: ${doc.bitmaps().count()}` ); | ||
// Handle strings | ||
@@ -1049,3 +978,2 @@ // console.log( `Document Strings Count: ${doc.strings().count()}` ); | ||
const strings_count = doc.strings().count(); | ||
for ( let i = 0; i < strings_count; i ++ ) { | ||
@@ -1074,10 +1002,10 @@ | ||
const _geometry = object.geometry(); | ||
const _attributes = object.attributes(); | ||
let objectType = _geometry.objectType; | ||
let geometry, attributes, position, data, mesh; | ||
let objectType = _geometry.objectType; | ||
let geometry, attributes, position, data, mesh; // skip instance definition objects | ||
// skip instance definition objects | ||
//if( _attributes.isInstanceDefinitionObject ) { continue; } | ||
// TODO: handle other geometry types | ||
switch ( objectType ) { | ||
@@ -1093,3 +1021,2 @@ | ||
position.array = []; | ||
for ( let j = 0; j < pts.length; j ++ ) { | ||
@@ -1109,3 +1036,2 @@ | ||
break; | ||
case rhino.ObjectType.Point: | ||
@@ -1120,5 +1046,3 @@ const pt = _geometry.location; | ||
position.array = [ pt[ 0 ], pt[ 1 ], pt[ 2 ] ]; | ||
const _color = _attributes.drawColor( doc ); | ||
color.itemSize = 3; | ||
@@ -1134,3 +1058,2 @@ color.type = 'Float32Array'; | ||
break; | ||
case rhino.ObjectType.PointSet: | ||
@@ -1140,18 +1063,12 @@ case rhino.ObjectType.Mesh: | ||
break; | ||
case rhino.ObjectType.Brep: | ||
const faces = _geometry.faces(); | ||
mesh = new rhino.Mesh(); | ||
for ( let faceIndex = 0; faceIndex < faces.count; faceIndex ++ ) { | ||
const face = faces.get( faceIndex ); | ||
const _mesh = face.getMesh( rhino.MeshType.Any ); | ||
if ( _mesh ) { | ||
mesh.append( _mesh ); | ||
_mesh.delete(); | ||
@@ -1175,6 +1092,4 @@ | ||
break; | ||
case rhino.ObjectType.Extrusion: | ||
mesh = _geometry.getMesh( rhino.MeshType.Any ); | ||
if ( mesh ) { | ||
@@ -1188,10 +1103,7 @@ | ||
break; | ||
case rhino.ObjectType.TextDot: | ||
geometry = extractProperties( _geometry ); | ||
break; | ||
case rhino.ObjectType.Light: | ||
geometry = extractProperties( _geometry ); | ||
if ( geometry.lightStyle.name === 'LightStyle_WorldLinear' ) { | ||
@@ -1212,3 +1124,2 @@ | ||
break; | ||
case rhino.ObjectType.InstanceReference: | ||
@@ -1219,9 +1130,6 @@ geometry = extractProperties( _geometry ); | ||
break; | ||
case rhino.ObjectType.SubD: | ||
// TODO: precalculate resulting vertices and faces and warn on excessive results | ||
_geometry.subdivide( 3 ); | ||
mesh = rhino.Mesh.createFromSubDControlNet( _geometry ); | ||
if ( mesh ) { | ||
@@ -1260,3 +1168,2 @@ | ||
attributes.geometry = extractProperties( _geometry ); | ||
if ( _attributes.groupCount > 0 ) { | ||
@@ -1308,7 +1215,5 @@ | ||
const result = {}; | ||
for ( const property in object ) { | ||
const value = object[ property ]; | ||
if ( typeof value !== 'function' ) { | ||
@@ -1329,3 +1234,5 @@ | ||
} else { // these are functions that could be called to extract more data. | ||
} else { | ||
// these are functions that could be called to extract more data. | ||
//console.log( `${property}: ${object[ property ].constructor.name}` ); | ||
@@ -1345,3 +1252,2 @@ } | ||
const ts = []; | ||
if ( curve instanceof rhino.LineCurve ) { | ||
@@ -1356,3 +1262,2 @@ | ||
pointCount = curve.pointCount; | ||
for ( let i = 0; i < pointCount; i ++ ) { | ||
@@ -1371,3 +1276,2 @@ | ||
const segmentCount = curve.segmentCount; | ||
for ( let i = 0; i < segmentCount; i ++ ) { | ||
@@ -1389,3 +1293,4 @@ | ||
pointCount = Math.floor( curve.angleDegrees / 5 ); | ||
pointCount = pointCount < 2 ? 2 : pointCount; // alternative to this hardcoded version: https://stackoverflow.com/a/18499923/2179399 | ||
pointCount = pointCount < 2 ? 2 : pointCount; | ||
// alternative to this hardcoded version: https://stackoverflow.com/a/18499923/2179399 | ||
@@ -1397,3 +1302,2 @@ } | ||
const pLine = curve.tryGetPolyline(); | ||
for ( let i = 0; i < pLine.count; i ++ ) { | ||
@@ -1412,7 +1316,5 @@ | ||
const divisions = pointCount - 1.0; | ||
for ( let j = 0; j < pointCount; j ++ ) { | ||
const t = domain[ 0 ] + j / divisions * ( domain[ 1 ] - domain[ 0 ] ); | ||
if ( t === domain[ 0 ] || t === domain[ 1 ] ) { | ||
@@ -1426,3 +1328,5 @@ | ||
const tan = curve.tangentAt( t ); | ||
const prevTan = curve.tangentAt( ts.slice( - 1 )[ 0 ] ); // Duplicated from THREE.Vector3 | ||
const prevTan = curve.tangentAt( ts.slice( - 1 )[ 0 ] ); | ||
// Duplicated from THREE.Vector3 | ||
// How to pass imports to worker? | ||
@@ -1434,3 +1338,2 @@ | ||
let angle; | ||
if ( denominator === 0 ) { | ||
@@ -1437,0 +1340,0 @@ |
@@ -29,3 +29,2 @@ ( function () { | ||
} | ||
load( url, onLoad, onProgress, onError ) { | ||
@@ -64,3 +63,2 @@ | ||
} | ||
parse( data ) { | ||
@@ -70,3 +68,2 @@ | ||
const textureLoader = new THREE.TextureLoader( this.manager ); | ||
function loadDocument( data ) { | ||
@@ -84,3 +81,2 @@ | ||
const texturesParts = {}; | ||
try { | ||
@@ -121,9 +117,12 @@ | ||
} // | ||
} | ||
// | ||
const relsView = zip[ relsName ]; | ||
const relsFileText = THREE.LoaderUtils.decodeText( relsView ); | ||
const rels = parseRelsXml( relsFileText ); // | ||
const rels = parseRelsXml( relsFileText ); | ||
// | ||
if ( modelRelsName ) { | ||
@@ -135,4 +134,5 @@ | ||
} // | ||
} | ||
// | ||
@@ -145,3 +145,2 @@ for ( let i = 0; i < modelPartNames.length; i ++ ) { | ||
const xmlData = new DOMParser().parseFromString( fileText, 'application/xml' ); | ||
if ( xmlData.documentElement.nodeName.toLowerCase() !== 'model' ) { | ||
@@ -155,7 +154,5 @@ | ||
const extensions = {}; | ||
for ( let i = 0; i < modelNode.attributes.length; i ++ ) { | ||
const attr = modelNode.attributes[ i ]; | ||
if ( attr.name.match( /^xmlns:(.+)$/ ) ) { | ||
@@ -171,3 +168,2 @@ | ||
modelData[ 'xml' ] = modelNode; | ||
if ( 0 < Object.keys( extensions ).length ) { | ||
@@ -181,4 +177,5 @@ | ||
} // | ||
} | ||
// | ||
@@ -207,3 +204,2 @@ for ( let i = 0; i < texturesPartNames.length; i ++ ) { | ||
const relsNodes = relsXmlData.querySelectorAll( 'Relationship' ); | ||
for ( let i = 0; i < relsNodes.length; i ++ ) { | ||
@@ -218,4 +214,4 @@ | ||
type: relsNode.getAttribute( 'Type' ) //required | ||
}; | ||
}; | ||
relationships.push( relationship ); | ||
@@ -232,3 +228,2 @@ | ||
const metadataData = {}; | ||
for ( let i = 0; i < metadataNodes.length; i ++ ) { | ||
@@ -239,3 +234,2 @@ | ||
const validNames = [ 'Title', 'Designer', 'Description', 'Copyright', 'LicenseTerms', 'Rating', 'CreationDate', 'ModificationDate' ]; | ||
if ( 0 <= validNames.indexOf( name ) ) { | ||
@@ -261,3 +255,2 @@ | ||
const basematerialNodes = basematerialsNode.querySelectorAll( 'base' ); | ||
for ( let i = 0; i < basematerialNodes.length; i ++ ) { | ||
@@ -268,3 +261,2 @@ | ||
basematerialData.index = i; // the order and count of the material nodes form an implicit 0-based index | ||
basematerialsData.basematerials.push( basematerialData ); | ||
@@ -306,3 +298,2 @@ | ||
const uvs = []; | ||
for ( let i = 0; i < tex2coordNodes.length; i ++ ) { | ||
@@ -332,3 +323,2 @@ | ||
const colorObject = new THREE.Color(); | ||
for ( let i = 0; i < colorNodes.length; i ++ ) { | ||
@@ -354,7 +344,6 @@ | ||
id: metallicDisplaypropetiesNode.getAttribute( 'id' ) // required | ||
}; | ||
}; | ||
const metallicNodes = metallicDisplaypropetiesNode.querySelectorAll( 'pbmetallic' ); | ||
const metallicData = []; | ||
for ( let i = 0; i < metallicNodes.length; i ++ ) { | ||
@@ -369,3 +358,2 @@ | ||
roughness: parseFloat( metallicNode.getAttribute( 'roughness' ) ) // required | ||
} ); | ||
@@ -384,5 +372,3 @@ | ||
basematerialData[ 'name' ] = basematerialNode.getAttribute( 'name' ); // required | ||
basematerialData[ 'displaycolor' ] = basematerialNode.getAttribute( 'displaycolor' ); // required | ||
basematerialData[ 'displaypropertiesid' ] = basematerialNode.getAttribute( 'displaypropertiesid' ); | ||
@@ -398,3 +384,2 @@ return basematerialData; | ||
const vertexNodes = meshNode.querySelectorAll( 'vertices vertex' ); | ||
for ( let i = 0; i < vertexNodes.length; i ++ ) { | ||
@@ -414,3 +399,2 @@ | ||
const triangleNodes = meshNode.querySelectorAll( 'triangles triangle' ); | ||
for ( let i = 0; i < triangleNodes.length; i ++ ) { | ||
@@ -430,4 +414,6 @@ | ||
triangleProperty[ 'v3' ] = parseInt( v3, 10 ); | ||
triangles.push( triangleProperty[ 'v1' ], triangleProperty[ 'v2' ], triangleProperty[ 'v3' ] ); // optional | ||
triangles.push( triangleProperty[ 'v1' ], triangleProperty[ 'v2' ], triangleProperty[ 'v3' ] ); | ||
// optional | ||
if ( p1 ) { | ||
@@ -475,3 +461,2 @@ | ||
const componentNodes = componentsNode.querySelectorAll( 'component' ); | ||
for ( let i = 0; i < componentNodes.length; i ++ ) { | ||
@@ -495,3 +480,2 @@ | ||
const transform = componentNode.getAttribute( 'transform' ); | ||
if ( transform ) { | ||
@@ -527,3 +511,2 @@ | ||
const id = objectNode.getAttribute( 'id' ); | ||
if ( id ) { | ||
@@ -536,3 +519,2 @@ | ||
const pid = objectNode.getAttribute( 'pid' ); | ||
if ( pid ) { | ||
@@ -545,3 +527,2 @@ | ||
const pindex = objectNode.getAttribute( 'pindex' ); | ||
if ( pindex ) { | ||
@@ -554,3 +535,2 @@ | ||
const thumbnail = objectNode.getAttribute( 'thumbnail' ); | ||
if ( thumbnail ) { | ||
@@ -563,3 +543,2 @@ | ||
const partnumber = objectNode.getAttribute( 'partnumber' ); | ||
if ( partnumber ) { | ||
@@ -572,3 +551,2 @@ | ||
const name = objectNode.getAttribute( 'name' ); | ||
if ( name ) { | ||
@@ -581,3 +559,2 @@ | ||
const meshNode = objectNode.querySelector( 'mesh' ); | ||
if ( meshNode ) { | ||
@@ -590,3 +567,2 @@ | ||
const componentsNode = objectNode.querySelector( 'components' ); | ||
if ( componentsNode ) { | ||
@@ -607,3 +583,2 @@ | ||
const basematerialsNodes = resourcesNode.querySelectorAll( 'basematerials' ); | ||
for ( let i = 0; i < basematerialsNodes.length; i ++ ) { | ||
@@ -615,8 +590,8 @@ | ||
} // | ||
} | ||
// | ||
resourcesData[ 'texture2d' ] = {}; | ||
const textures2DNodes = resourcesNode.querySelectorAll( 'texture2d' ); | ||
for ( let i = 0; i < textures2DNodes.length; i ++ ) { | ||
@@ -628,8 +603,8 @@ | ||
} // | ||
} | ||
// | ||
resourcesData[ 'colorgroup' ] = {}; | ||
const colorGroupNodes = resourcesNode.querySelectorAll( 'colorgroup' ); | ||
for ( let i = 0; i < colorGroupNodes.length; i ++ ) { | ||
@@ -641,8 +616,8 @@ | ||
} // | ||
} | ||
// | ||
resourcesData[ 'pbmetallicdisplayproperties' ] = {}; | ||
const pbmetallicdisplaypropertiesNodes = resourcesNode.querySelectorAll( 'pbmetallicdisplayproperties' ); | ||
for ( let i = 0; i < pbmetallicdisplaypropertiesNodes.length; i ++ ) { | ||
@@ -654,8 +629,8 @@ | ||
} // | ||
} | ||
// | ||
resourcesData[ 'texture2dgroup' ] = {}; | ||
const textures2DGroupNodes = resourcesNode.querySelectorAll( 'texture2dgroup' ); | ||
for ( let i = 0; i < textures2DGroupNodes.length; i ++ ) { | ||
@@ -667,8 +642,8 @@ | ||
} // | ||
} | ||
// | ||
resourcesData[ 'object' ] = {}; | ||
const objectNodes = resourcesNode.querySelectorAll( 'object' ); | ||
for ( let i = 0; i < objectNodes.length; i ++ ) { | ||
@@ -690,3 +665,2 @@ | ||
const itemNodes = buildNode.querySelectorAll( 'item' ); | ||
for ( let i = 0; i < itemNodes.length; i ++ ) { | ||
@@ -699,3 +673,2 @@ | ||
const transform = itemNode.getAttribute( 'transform' ); | ||
if ( transform ) { | ||
@@ -721,3 +694,2 @@ | ||
const metadataNodes = modelNode.querySelectorAll( 'metadata' ); | ||
if ( metadataNodes ) { | ||
@@ -730,3 +702,2 @@ | ||
const resourcesNode = modelNode.querySelector( 'resources' ); | ||
if ( resourcesNode ) { | ||
@@ -739,3 +710,2 @@ | ||
const buildNode = modelNode.querySelector( 'build' ); | ||
if ( buildNode ) { | ||
@@ -756,3 +726,2 @@ | ||
const texture2d = texture2ds[ texid ]; | ||
if ( texture2d ) { | ||
@@ -771,4 +740,6 @@ | ||
} ); | ||
texture.encoding = THREE.sRGBEncoding; // texture parameters | ||
texture.encoding = THREE.sRGBEncoding; | ||
// texture parameters | ||
switch ( texture2d.tilestyleu ) { | ||
@@ -779,7 +750,5 @@ | ||
break; | ||
case 'mirror': | ||
texture.wrapS = THREE.MirroredRepeatWrapping; | ||
break; | ||
case 'none': | ||
@@ -789,3 +758,2 @@ case 'clamp': | ||
break; | ||
default: | ||
@@ -801,7 +769,5 @@ texture.wrapS = THREE.RepeatWrapping; | ||
break; | ||
case 'mirror': | ||
texture.wrapT = THREE.MirroredRepeatWrapping; | ||
break; | ||
case 'none': | ||
@@ -811,3 +777,2 @@ case 'clamp': | ||
break; | ||
default: | ||
@@ -824,3 +789,2 @@ texture.wrapT = THREE.RepeatWrapping; | ||
break; | ||
case 'linear': | ||
@@ -830,3 +794,2 @@ texture.magFilter = THREE.LinearFilter; | ||
break; | ||
case 'nearest': | ||
@@ -836,3 +799,2 @@ texture.magFilter = THREE.NearestFilter; | ||
break; | ||
default: | ||
@@ -858,3 +820,2 @@ texture.magFilter = THREE.LinearFilter; | ||
const materialMap = {}; | ||
for ( let i = 0, l = triangleProperties.length; i < l; i ++ ) { | ||
@@ -867,8 +828,8 @@ | ||
} // | ||
} | ||
// | ||
const keys = Object.keys( materialMap ); | ||
const meshes = []; | ||
for ( let i = 0, l = keys.length; i < l; i ++ ) { | ||
@@ -879,8 +840,9 @@ | ||
const basematerialData = basematerials.basematerials[ materialIndex ]; | ||
const material = getBuild( basematerialData, objects, modelData, textureData, objectData, buildBasematerial ); // | ||
const material = getBuild( basematerialData, objects, modelData, textureData, objectData, buildBasematerial ); | ||
// | ||
const geometry = new THREE.BufferGeometry(); | ||
const positionData = []; | ||
const vertices = meshData.vertices; | ||
for ( let j = 0, jl = trianglePropertiesProps.length; j < jl; j ++ ) { | ||
@@ -901,4 +863,6 @@ | ||
geometry.setAttribute( 'position', new THREE.Float32BufferAttribute( positionData, 3 ) ); // | ||
geometry.setAttribute( 'position', new THREE.Float32BufferAttribute( positionData, 3 ) ); | ||
// | ||
const mesh = new THREE.Mesh( geometry, material ); | ||
@@ -916,2 +880,3 @@ meshes.push( mesh ); | ||
// geometry | ||
const geometry = new THREE.BufferGeometry(); | ||
@@ -922,3 +887,2 @@ const positionData = []; | ||
const uvs = texture2dgroup.uvs; | ||
for ( let i = 0, l = triangleProperties.length; i < l; i ++ ) { | ||
@@ -935,4 +899,6 @@ | ||
positionData.push( vertices[ triangleProperty.v3 * 3 + 1 ] ); | ||
positionData.push( vertices[ triangleProperty.v3 * 3 + 2 ] ); // | ||
positionData.push( vertices[ triangleProperty.v3 * 3 + 2 ] ); | ||
// | ||
uvData.push( uvs[ triangleProperty.p1 * 2 + 0 ] ); | ||
@@ -948,4 +914,6 @@ uvData.push( uvs[ triangleProperty.p1 * 2 + 1 ] ); | ||
geometry.setAttribute( 'position', new THREE.Float32BufferAttribute( positionData, 3 ) ); | ||
geometry.setAttribute( 'uv', new THREE.Float32BufferAttribute( uvData, 2 ) ); // material | ||
geometry.setAttribute( 'uv', new THREE.Float32BufferAttribute( uvData, 2 ) ); | ||
// material | ||
const texture = getBuild( texture2dgroup, objects, modelData, textureData, objectData, buildTexture ); | ||
@@ -955,4 +923,6 @@ const material = new THREE.MeshPhongMaterial( { | ||
flatShading: true | ||
} ); // mesh | ||
} ); | ||
// mesh | ||
const mesh = new THREE.Mesh( geometry, material ); | ||
@@ -966,2 +936,3 @@ return mesh; | ||
// geometry | ||
const geometry = new THREE.BufferGeometry(); | ||
@@ -972,3 +943,2 @@ const positionData = []; | ||
const colors = colorgroup.colors; | ||
for ( let i = 0, l = triangleProperties.length; i < l; i ++ ) { | ||
@@ -988,4 +958,6 @@ | ||
positionData.push( vertices[ v3 * 3 + 1 ] ); | ||
positionData.push( vertices[ v3 * 3 + 2 ] ); // | ||
positionData.push( vertices[ v3 * 3 + 2 ] ); | ||
// | ||
const p1 = triangleProperty.p1 !== undefined ? triangleProperty.p1 : objectData.pindex; | ||
@@ -1007,9 +979,13 @@ const p2 = triangleProperty.p2 !== undefined ? triangleProperty.p2 : p1; | ||
geometry.setAttribute( 'position', new THREE.Float32BufferAttribute( positionData, 3 ) ); | ||
geometry.setAttribute( 'color', new THREE.Float32BufferAttribute( colorData, 3 ) ); // material | ||
geometry.setAttribute( 'color', new THREE.Float32BufferAttribute( colorData, 3 ) ); | ||
// material | ||
const material = new THREE.MeshPhongMaterial( { | ||
vertexColors: true, | ||
flatShading: true | ||
} ); // mesh | ||
} ); | ||
// mesh | ||
const mesh = new THREE.Mesh( geometry, material ); | ||
@@ -1038,3 +1014,2 @@ return mesh; | ||
const meshes = []; | ||
for ( let i = 0, il = keys.length; i < il; i ++ ) { | ||
@@ -1045,3 +1020,2 @@ | ||
const resourceType = getResourceType( resourceId, modelData ); | ||
switch ( resourceType ) { | ||
@@ -1052,3 +1026,2 @@ | ||
const newMeshes = buildBasematerialsMeshes( basematerials, triangleProperties, meshData, objects, modelData, textureData, objectData ); | ||
for ( let j = 0, jl = newMeshes.length; j < jl; j ++ ) { | ||
@@ -1061,3 +1034,2 @@ | ||
break; | ||
case 'texture': | ||
@@ -1067,3 +1039,2 @@ const texture2dgroup = modelData.resources.texture2dgroup[ resourceId ]; | ||
break; | ||
case 'vertexColors': | ||
@@ -1073,7 +1044,5 @@ const colorgroup = modelData.resources.colorgroup[ resourceId ]; | ||
break; | ||
case 'default': | ||
meshes.push( buildDefaultMesh( meshData ) ); | ||
break; | ||
default: | ||
@@ -1131,3 +1100,2 @@ console.error( 'THREE.3MFLoader: Unsupported resource type.' ); | ||
const objectPid = objectData.pid; | ||
for ( let i = 0, l = triangleProperties.length; i < l; i ++ ) { | ||
@@ -1152,3 +1120,2 @@ | ||
const meshes = buildMeshes( resourceMap, meshData, objects, modelData, textureData, objectData ); | ||
for ( let i = 0, l = meshes.length; i < l; i ++ ) { | ||
@@ -1174,11 +1141,8 @@ | ||
const keys = Object.keys( extensions ); | ||
for ( let i = 0; i < keys.length; i ++ ) { | ||
const ns = keys[ i ]; | ||
for ( let j = 0; j < scope.availableExtensions.length; j ++ ) { | ||
const extension = scope.availableExtensions[ j ]; | ||
if ( extension.ns === ns ) { | ||
@@ -1216,6 +1180,6 @@ | ||
const pbmetallicdisplayproperties = modelData.resources.pbmetallicdisplayproperties; | ||
if ( displaypropertiesid !== null && pbmetallicdisplayproperties[ displaypropertiesid ] !== undefined ) { | ||
// metallic display property, use StandardMaterial | ||
const pbmetallicdisplayproperty = pbmetallicdisplayproperties[ displaypropertiesid ]; | ||
@@ -1232,2 +1196,3 @@ const metallicData = pbmetallicdisplayproperty.data[ materialData.index ]; | ||
// otherwise use PhongMaterial | ||
material = new THREE.MeshPhongMaterial( { | ||
@@ -1239,4 +1204,6 @@ flatShading: true | ||
material.name = materialData.name; // displaycolor MUST be specified with a value of a 6 or 8 digit hexadecimal number, e.g. "#RRGGBB" or "#RRGGBBAA" | ||
material.name = materialData.name; | ||
// displaycolor MUST be specified with a value of a 6 or 8 digit hexadecimal number, e.g. "#RRGGBB" or "#RRGGBBAA" | ||
const displaycolor = materialData.displaycolor; | ||
@@ -1246,2 +1213,3 @@ const color = displaycolor.substring( 0, 7 ); | ||
material.color.convertSRGBToLinear(); // displaycolor is in sRGB | ||
// process alpha if set | ||
@@ -1262,3 +1230,2 @@ | ||
const composite = new THREE.Group(); | ||
for ( let j = 0; j < compositeData.length; j ++ ) { | ||
@@ -1268,3 +1235,2 @@ | ||
let build = objects[ component.objectId ]; | ||
if ( build === undefined ) { | ||
@@ -1277,6 +1243,7 @@ | ||
const object3D = build.clone(); // apply component transform | ||
const object3D = build.clone(); | ||
// apply component transform | ||
const transform = component.transform; | ||
if ( transform ) { | ||
@@ -1299,3 +1266,2 @@ | ||
const objectData = modelData[ 'resources' ][ 'object' ][ objectId ]; | ||
if ( objectData[ 'mesh' ] ) { | ||
@@ -1330,4 +1296,6 @@ | ||
const modelsKeys = Object.keys( modelsData ); | ||
const textureData = {}; // evaluate model relationships to textures | ||
const textureData = {}; | ||
// evaluate model relationships to textures | ||
if ( modelRels ) { | ||
@@ -1339,3 +1307,2 @@ | ||
const textureKey = modelRel.target.substring( 1 ); | ||
if ( data3mf.texture[ textureKey ] ) { | ||
@@ -1349,4 +1316,5 @@ | ||
} // start build | ||
} | ||
// start build | ||
@@ -1358,3 +1326,2 @@ for ( let i = 0; i < modelsKeys.length; i ++ ) { | ||
const objectIds = Object.keys( modelData[ 'resources' ][ 'object' ] ); | ||
for ( let j = 0; j < objectIds.length; j ++ ) { | ||
@@ -1390,10 +1357,10 @@ | ||
const buildData = data3mf.model[ relationship[ 'target' ].substring( 1 ) ][ 'build' ]; | ||
for ( let i = 0; i < buildData.length; i ++ ) { | ||
const buildItem = buildData[ i ]; | ||
const object3D = objects[ buildItem[ 'objectId' ] ].clone(); // apply transform | ||
const object3D = objects[ buildItem[ 'objectId' ] ].clone(); | ||
// apply transform | ||
const transform = buildItem[ 'transform' ]; | ||
if ( transform ) { | ||
@@ -1418,3 +1385,2 @@ | ||
} | ||
addExtension( extension ) { | ||
@@ -1421,0 +1387,0 @@ |
@@ -26,3 +26,2 @@ ( function () { | ||
} | ||
load( url, onLoad, onProgress, onError ) { | ||
@@ -61,3 +60,2 @@ | ||
} | ||
parse( data ) { | ||
@@ -69,3 +67,2 @@ | ||
const magic = String.fromCharCode( view.getUint8( 0 ), view.getUint8( 1 ) ); | ||
if ( magic === 'PK' ) { | ||
@@ -76,3 +73,2 @@ | ||
console.log( 'THREE.AMFLoader: Loading Zip' ); | ||
try { | ||
@@ -110,3 +106,2 @@ | ||
const xmlData = new DOMParser().parseFromString( fileText, 'application/xml' ); | ||
if ( xmlData.documentElement.nodeName.toLowerCase() !== 'amf' ) { | ||
@@ -127,3 +122,2 @@ | ||
let unit = 'millimeter'; | ||
if ( node.documentElement.attributes.unit !== undefined ) { | ||
@@ -142,3 +136,2 @@ | ||
}; | ||
if ( scaleUnits[ unit ] !== undefined ) { | ||
@@ -166,7 +159,5 @@ | ||
let loadedMaterial = null; | ||
for ( let i = 0; i < node.childNodes.length; i ++ ) { | ||
const matChildEl = node.childNodes[ i ]; | ||
if ( matChildEl.nodeName === 'metadata' && matChildEl.attributes.type !== undefined ) { | ||
@@ -193,3 +184,2 @@ | ||
} ); | ||
if ( color.a !== 1.0 ) { | ||
@@ -217,7 +207,5 @@ | ||
}; | ||
for ( let i = 0; i < node.childNodes.length; i ++ ) { | ||
const matColor = node.childNodes[ i ]; | ||
if ( matColor.nodeName === 'r' ) { | ||
@@ -255,3 +243,2 @@ | ||
let currVolumeNode = node.firstElementChild; | ||
if ( node.attributes.materialid !== undefined ) { | ||
@@ -299,3 +286,2 @@ | ||
let currVerticesNode = node.firstElementChild; | ||
while ( currVerticesNode ) { | ||
@@ -306,3 +292,2 @@ | ||
let vNode = currVerticesNode.firstElementChild; | ||
while ( vNode ) { | ||
@@ -352,3 +337,2 @@ | ||
let currObjNode = node.firstElementChild; | ||
while ( currObjNode ) { | ||
@@ -381,3 +365,2 @@ | ||
}; | ||
while ( currMeshNode ) { | ||
@@ -424,7 +407,5 @@ | ||
let i, j; | ||
for ( i = 0; i < childNodes.length; i ++ ) { | ||
const child = childNodes[ i ]; | ||
if ( child.nodeName === 'metadata' ) { | ||
@@ -468,3 +449,2 @@ | ||
sceneObject.userData.loader = 'AMF'; | ||
for ( const id in amfObjects ) { | ||
@@ -476,3 +456,2 @@ | ||
newObject.name = part.name || ''; | ||
for ( i = 0; i < meshes.length; i ++ ) { | ||
@@ -484,3 +463,2 @@ | ||
let normals = null; | ||
if ( mesh.normals.length ) { | ||
@@ -497,3 +475,2 @@ | ||
objDefaultMaterial.color = new THREE.Color( color.r, color.g, color.b ); | ||
if ( color.a !== 1.0 ) { | ||
@@ -509,3 +486,2 @@ | ||
const volumes = mesh.volumes; | ||
for ( j = 0; j < volumes.length; j ++ ) { | ||
@@ -518,3 +494,2 @@ | ||
newGeometry.setAttribute( 'position', vertices.clone() ); | ||
if ( normals ) { | ||
@@ -521,0 +496,0 @@ |
@@ -17,3 +17,2 @@ ( function () { | ||
const _taskCache = new WeakMap(); | ||
class BasisTextureLoader extends THREE.Loader { | ||
@@ -35,3 +34,2 @@ | ||
} | ||
setTranscoderPath( path ) { | ||
@@ -43,3 +41,2 @@ | ||
} | ||
setWorkerLimit( workerLimit ) { | ||
@@ -51,3 +48,2 @@ | ||
} | ||
detectSupport( renderer ) { | ||
@@ -66,3 +62,2 @@ | ||
} | ||
load( url, onLoad, onProgress, onError ) { | ||
@@ -81,3 +76,2 @@ | ||
const cachedTask = _taskCache.get( buffer ); | ||
return cachedTask.promise.then( onLoad ).catch( onError ); | ||
@@ -99,5 +93,4 @@ | ||
} | ||
/** Low-level transcoding API, exposed for use by KTX2Loader. */ | ||
parseInternalAsync( options ) { | ||
@@ -109,3 +102,2 @@ | ||
const buffers = new Set(); | ||
for ( let i = 0; i < levels.length; i ++ ) { | ||
@@ -117,3 +109,4 @@ | ||
return this._createTexture( Array.from( buffers ), { ...options, | ||
return this._createTexture( Array.from( buffers ), { | ||
...options, | ||
lowLevel: true | ||
@@ -123,2 +116,3 @@ } ); | ||
} | ||
/** | ||
@@ -129,4 +123,2 @@ * @param {ArrayBuffer[]} buffers | ||
*/ | ||
_createTexture( buffers, config = {} ) { | ||
@@ -138,3 +130,2 @@ | ||
let taskCost = 0; | ||
for ( let i = 0; i < buffers.length; i ++ ) { | ||
@@ -180,5 +171,5 @@ | ||
} ); // Note: replaced '.finally()' with '.catch().then()' block - iOS 11 support (#19416) | ||
} ); | ||
// Note: replaced '.finally()' with '.catch().then()' block - iOS 11 support (#19416) | ||
texturePending.catch( () => true ).then( () => { | ||
@@ -193,12 +184,11 @@ | ||
} ); // Cache the task result. | ||
} ); | ||
// Cache the task result. | ||
_taskCache.set( buffers[ 0 ], { | ||
promise: texturePending | ||
} ); | ||
return texturePending; | ||
} | ||
_initTranscoder() { | ||
@@ -216,4 +206,5 @@ | ||
} ); // Load transcoder WASM binary. | ||
} ); | ||
// Load transcoder WASM binary. | ||
const binaryLoader = new THREE.FileLoader( this.manager ); | ||
@@ -242,3 +233,2 @@ binaryLoader.setPath( this.transcoderPath ); | ||
} | ||
_allocateWorker( taskCost ) { | ||
@@ -258,7 +248,5 @@ | ||
} ); | ||
worker.onmessage = function ( e ) { | ||
const message = e.data; | ||
switch ( message.type ) { | ||
@@ -268,10 +256,6 @@ | ||
worker._callbacks[ message.id ].resolve( message ); | ||
break; | ||
case 'error': | ||
worker._callbacks[ message.id ].reject( message ); | ||
break; | ||
default: | ||
@@ -303,3 +287,2 @@ console.error( 'THREE.BasisTextureLoader: Unexpected message, "' + message.type + '"' ); | ||
} | ||
dispose() { | ||
@@ -319,5 +302,5 @@ | ||
} | ||
/* CONSTANTS */ | ||
BasisTextureLoader.BasisFormat = { | ||
@@ -358,2 +341,3 @@ ETC1S: 0, | ||
}; | ||
/* WEB WORKER */ | ||
@@ -367,5 +351,3 @@ | ||
const EngineFormat = _EngineFormat; // eslint-disable-line no-undef | ||
const TranscoderFormat = _TranscoderFormat; // eslint-disable-line no-undef | ||
const BasisFormat = _BasisFormat; // eslint-disable-line no-undef | ||
@@ -376,3 +358,2 @@ | ||
const message = e.data; | ||
switch ( message.type ) { | ||
@@ -384,3 +365,2 @@ | ||
break; | ||
case 'transcode': | ||
@@ -399,3 +379,2 @@ transcoderPending.then( () => { | ||
const buffers = []; | ||
for ( let i = 0; i < mipmaps.length; ++ i ) { | ||
@@ -468,3 +447,2 @@ | ||
const mipmaps = []; | ||
if ( basisFormat === BasisFormat.ETC1S ) { | ||
@@ -480,3 +458,2 @@ | ||
} = taskConfig.globalData; | ||
try { | ||
@@ -489,3 +466,2 @@ | ||
assert( ok, 'THREE.BasisTextureLoader: decodeTables() failed.' ); | ||
for ( let i = 0; i < taskConfig.levels.length; i ++ ) { | ||
@@ -550,3 +526,2 @@ | ||
const hasAlpha = basisFile.getHasAlpha(); | ||
function cleanup() { | ||
@@ -563,3 +538,2 @@ | ||
} = getTranscoderFormat( basisFormat, width, height, hasAlpha ); | ||
if ( ! width || ! height || ! levels ) { | ||
@@ -580,3 +554,2 @@ | ||
const mipmaps = []; | ||
for ( let mip = 0; mip < levels; mip ++ ) { | ||
@@ -588,3 +561,2 @@ | ||
const status = basisFile.transcodeImage( dst, 0, mip, transcoderFormat, 0, hasAlpha ); | ||
if ( ! status ) { | ||
@@ -614,3 +586,6 @@ | ||
} // | ||
} | ||
// | ||
// Optimal choice of a transcoder target format depends on the Basis format (ETC1S or UASTC), | ||
@@ -623,4 +598,2 @@ // device capabilities, and texture dimensions. The list below ranks the formats separately | ||
// chooses RGBA32 only as a last resort and does not expose that option to the caller. | ||
const FORMAT_OPTIONS = [ { | ||
@@ -685,3 +658,2 @@ if: 'astcSupported', | ||
} ); | ||
function getTranscoderFormat( basisFormat, width, height, hasAlpha ) { | ||
@@ -692,3 +664,2 @@ | ||
const options = basisFormat === BasisFormat.ETC1S ? ETC1S_OPTIONS : UASTC_OPTIONS; | ||
for ( let i = 0; i < options.length; i ++ ) { | ||
@@ -740,3 +711,2 @@ | ||
const blockByteLength = BasisModule.getBytesPerBlockOrPixel( transcoderFormat ); | ||
if ( BasisModule.formatIsUncompressed( transcoderFormat ) ) { | ||
@@ -743,0 +713,0 @@ |
@@ -19,3 +19,2 @@ ( function () { | ||
} | ||
load( url, onLoad, onProgress, onError ) { | ||
@@ -53,3 +52,2 @@ | ||
} | ||
parse( text ) { | ||
@@ -66,2 +64,3 @@ | ||
// read model structure | ||
if ( nextLine( lines ) !== 'HIERARCHY' ) { | ||
@@ -74,4 +73,5 @@ | ||
const list = []; // collects flat array of all bones | ||
const root = readNode( lines, nextLine( lines ), list ); | ||
const root = readNode( lines, nextLine( lines ), list ); // read motion data | ||
// read motion data | ||
@@ -82,8 +82,8 @@ if ( nextLine( lines ) !== 'MOTION' ) { | ||
} // number of frames | ||
} | ||
// number of frames | ||
let tokens = nextLine( lines ).split( /[\s]+/ ); | ||
const numFrames = parseInt( tokens[ 1 ] ); | ||
if ( isNaN( numFrames ) ) { | ||
@@ -93,8 +93,8 @@ | ||
} // frame time | ||
} | ||
// frame time | ||
tokens = nextLine( lines ).split( /[\s]+/ ); | ||
const frameTime = parseFloat( tokens[ 2 ] ); | ||
if ( isNaN( frameTime ) ) { | ||
@@ -104,4 +104,5 @@ | ||
} // read frame data line by line | ||
} | ||
// read frame data line by line | ||
@@ -118,2 +119,3 @@ for ( let i = 0; i < numFrames; i ++ ) { | ||
} | ||
/* | ||
@@ -128,9 +130,10 @@ Recursively reads data from a single frame into the bone hierarchy. | ||
*/ | ||
function readFrameData( data, frameTime, bone ) { | ||
// end sites have no motion data | ||
if ( bone.type === 'ENDSITE' ) return; // add keyframe | ||
if ( bone.type === 'ENDSITE' ) return; | ||
// add keyframe | ||
const keyframe = { | ||
@@ -145,4 +148,6 @@ time: frameTime, | ||
const vy = new THREE.Vector3( 0, 1, 0 ); | ||
const vz = new THREE.Vector3( 0, 0, 1 ); // parse values for each channel in node | ||
const vz = new THREE.Vector3( 0, 0, 1 ); | ||
// parse values for each channel in node | ||
for ( let i = 0; i < bone.channels.length; i ++ ) { | ||
@@ -155,11 +160,8 @@ | ||
break; | ||
case 'Yposition': | ||
keyframe.position.y = parseFloat( data.shift().trim() ); | ||
break; | ||
case 'Zposition': | ||
keyframe.position.z = parseFloat( data.shift().trim() ); | ||
break; | ||
case 'Xrotation': | ||
@@ -169,3 +171,2 @@ quat.setFromAxisAngle( vx, parseFloat( data.shift().trim() ) * Math.PI / 180 ); | ||
break; | ||
case 'Yrotation': | ||
@@ -175,3 +176,2 @@ quat.setFromAxisAngle( vy, parseFloat( data.shift().trim() ) * Math.PI / 180 ); | ||
break; | ||
case 'Zrotation': | ||
@@ -181,3 +181,2 @@ quat.setFromAxisAngle( vz, parseFloat( data.shift().trim() ) * Math.PI / 180 ); | ||
break; | ||
default: | ||
@@ -188,4 +187,5 @@ console.warn( 'THREE.BVHLoader: Invalid channel type.' ); | ||
} // parse child nodes | ||
} | ||
// parse child nodes | ||
@@ -199,2 +199,3 @@ for ( let i = 0; i < bone.children.length; i ++ ) { | ||
} | ||
/* | ||
@@ -207,4 +208,2 @@ Recursively parses the HIERACHY section of the BVH file | ||
*/ | ||
function readNode( lines, firstline, list ) { | ||
@@ -217,6 +216,7 @@ | ||
}; | ||
list.push( node ); // parse node type and name | ||
list.push( node ); | ||
// parse node type and name | ||
let tokens = firstline.split( /[\s]+/ ); | ||
if ( tokens[ 0 ].toUpperCase() === 'END' && tokens[ 1 ].toUpperCase() === 'SITE' ) { | ||
@@ -238,7 +238,7 @@ | ||
} // parse OFFSET | ||
} | ||
// parse OFFSET | ||
tokens = nextLine( lines ).split( /[\s]+/ ); | ||
if ( tokens[ 0 ] !== 'OFFSET' ) { | ||
@@ -257,3 +257,2 @@ | ||
const offset = new THREE.Vector3( parseFloat( tokens[ 1 ] ), parseFloat( tokens[ 2 ] ), parseFloat( tokens[ 3 ] ) ); | ||
if ( isNaN( offset.x ) || isNaN( offset.y ) || isNaN( offset.z ) ) { | ||
@@ -265,8 +264,9 @@ | ||
node.offset = offset; // parse CHANNELS definitions | ||
node.offset = offset; | ||
// parse CHANNELS definitions | ||
if ( node.type !== 'ENDSITE' ) { | ||
tokens = nextLine( lines ).split( /[\s]+/ ); | ||
if ( tokens[ 0 ] !== 'CHANNELS' ) { | ||
@@ -282,4 +282,5 @@ | ||
} // read children | ||
} | ||
// read children | ||
@@ -289,3 +290,2 @@ while ( true ) { | ||
const line = nextLine( lines ); | ||
if ( line === '}' ) { | ||
@@ -304,2 +304,3 @@ | ||
} | ||
/* | ||
@@ -311,4 +312,2 @@ recursively converts the internal bvh node structure to a THREE.Bone hierarchy | ||
*/ | ||
function toTHREEBone( source, list ) { | ||
@@ -320,3 +319,2 @@ | ||
bone.name = source.name; | ||
if ( source.type !== 'ENDSITE' ) { | ||
@@ -335,2 +333,3 @@ | ||
} | ||
/* | ||
@@ -341,21 +340,24 @@ builds a THREE.AnimationClip from the keyframe data saved in each bone. | ||
*/ | ||
function toTHREEAnimation( bones ) { | ||
const tracks = []; | ||
function toTHREEAnimation( bones ) { | ||
// create a position and quaternion animation track for each node | ||
const tracks = []; // create a position and quaternion animation track for each node | ||
for ( let i = 0; i < bones.length; i ++ ) { | ||
const bone = bones[ i ]; | ||
if ( bone.type === 'ENDSITE' ) continue; // track data | ||
if ( bone.type === 'ENDSITE' ) continue; | ||
// track data | ||
const times = []; | ||
const positions = []; | ||
const rotations = []; | ||
for ( let j = 0; j < bone.frames.length; j ++ ) { | ||
const frame = bone.frames[ j ]; | ||
times.push( frame.time ); // the animation system animates the position property, | ||
times.push( frame.time ); | ||
// the animation system animates the position property, | ||
// so we have to add the joint offset to all values | ||
@@ -390,11 +392,10 @@ | ||
} | ||
/* | ||
returns the next non-empty line in lines | ||
*/ | ||
function nextLine( lines ) { | ||
let line; // skip empty lines | ||
let line; | ||
// skip empty lines | ||
while ( ( line = lines.shift().trim() ).length === 0 ) {} | ||
@@ -401,0 +402,0 @@ |
@@ -10,3 +10,2 @@ ( function () { | ||
} | ||
parse( buffer, loadMipmaps ) { | ||
@@ -20,8 +19,13 @@ | ||
mipmapCount: 1 | ||
}; // Adapted from @toji's DDS utils | ||
}; | ||
// Adapted from @toji's DDS utils | ||
// https://github.com/toji/webgl-texture-utils/blob/master/texture-util/dds.js | ||
// All values and structures referenced from: | ||
// http://msdn.microsoft.com/en-us/library/bb943991.aspx/ | ||
const DDS_MAGIC = 0x20534444; // const DDSD_CAPS = 0x1; | ||
const DDS_MAGIC = 0x20534444; | ||
// const DDSD_CAPS = 0x1; | ||
// const DDSD_HEIGHT = 0x2; | ||
@@ -31,5 +35,6 @@ // const DDSD_WIDTH = 0x4; | ||
// const DDSD_PIXELFORMAT = 0x1000; | ||
const DDSD_MIPMAPCOUNT = 0x20000; | ||
// const DDSD_LINEARSIZE = 0x80000; | ||
// const DDSD_DEPTH = 0x800000; | ||
const DDSD_MIPMAPCOUNT = 0x20000; // const DDSD_LINEARSIZE = 0x80000; | ||
// const DDSD_DEPTH = 0x800000; | ||
// const DDSCAPS_COMPLEX = 0x8; | ||
@@ -45,3 +50,5 @@ // const DDSCAPS_MIPMAP = 0x400000; | ||
const DDSCAPS2_CUBEMAP_POSITIVEZ = 0x4000; | ||
const DDSCAPS2_CUBEMAP_NEGATIVEZ = 0x8000; // const DDSCAPS2_VOLUME = 0x200000; | ||
const DDSCAPS2_CUBEMAP_NEGATIVEZ = 0x8000; | ||
// const DDSCAPS2_VOLUME = 0x200000; | ||
// const DDPF_ALPHAPIXELS = 0x1; | ||
@@ -73,3 +80,2 @@ // const DDPF_ALPHA = 0x2; | ||
let src = 0; | ||
for ( let y = 0; y < height; y ++ ) { | ||
@@ -89,9 +95,6 @@ | ||
dst ++; //r | ||
byteArray[ dst ] = g; | ||
dst ++; //g | ||
byteArray[ dst ] = b; | ||
dst ++; //b | ||
byteArray[ dst ] = a; | ||
@@ -113,2 +116,3 @@ dst ++; //a | ||
const headerLengthInt = 31; // The header length in 32 bit ints | ||
// Offsets into the header array | ||
@@ -121,4 +125,5 @@ | ||
const off_width = 4; | ||
const off_mipmapCount = 7; // const off_pfFlags = 20; | ||
const off_mipmapCount = 7; | ||
// const off_pfFlags = 20; | ||
const off_pfFourCC = 21; | ||
@@ -129,10 +134,12 @@ const off_RGBBitCount = 22; | ||
const off_BBitMask = 25; | ||
const off_ABitMask = 26; // const off_caps = 27; | ||
const off_ABitMask = 26; | ||
const off_caps2 = 28; // const off_caps3 = 29; | ||
// const off_caps = 27; | ||
const off_caps2 = 28; | ||
// const off_caps3 = 29; | ||
// const off_caps4 = 30; | ||
// Parse header | ||
const header = new Int32Array( buffer, 0, headerLengthInt ); | ||
if ( header[ off_magic ] !== DDS_MAGIC ) { | ||
@@ -148,3 +155,2 @@ | ||
let isRGBAUncompressed = false; | ||
switch ( fourCC ) { | ||
@@ -156,3 +162,2 @@ | ||
break; | ||
case FOURCC_DXT3: | ||
@@ -162,3 +167,2 @@ blockBytes = 16; | ||
break; | ||
case FOURCC_DXT5: | ||
@@ -168,3 +172,2 @@ blockBytes = 16; | ||
break; | ||
case FOURCC_ETC1: | ||
@@ -174,3 +177,2 @@ blockBytes = 8; | ||
break; | ||
default: | ||
@@ -193,3 +195,2 @@ if ( header[ off_RGBBitCount ] === 32 && header[ off_RBitMask ] & 0xff0000 && header[ off_GBitMask ] & 0xff00 && header[ off_BBitMask ] & 0xff && header[ off_ABitMask ] & 0xff000000 ) { | ||
dds.mipmapCount = 1; | ||
if ( header[ off_flags ] & DDSD_MIPMAPCOUNT && loadMipmaps !== false ) { | ||
@@ -203,3 +204,2 @@ | ||
dds.isCubemap = caps2 & DDSCAPS2_CUBEMAP ? true : false; | ||
if ( dds.isCubemap && ( ! ( caps2 & DDSCAPS2_CUBEMAP_POSITIVEX ) || ! ( caps2 & DDSCAPS2_CUBEMAP_NEGATIVEX ) || ! ( caps2 & DDSCAPS2_CUBEMAP_POSITIVEY ) || ! ( caps2 & DDSCAPS2_CUBEMAP_NEGATIVEY ) || ! ( caps2 & DDSCAPS2_CUBEMAP_POSITIVEZ ) || ! ( caps2 & DDSCAPS2_CUBEMAP_NEGATIVEZ ) ) ) { | ||
@@ -214,6 +214,7 @@ | ||
dds.height = header[ off_height ]; | ||
let dataOffset = header[ off_size ] + 4; // Extract mipmaps buffers | ||
let dataOffset = header[ off_size ] + 4; | ||
// Extract mipmaps buffers | ||
const faces = dds.isCubemap ? 6 : 1; | ||
for ( let face = 0; face < faces; face ++ ) { | ||
@@ -223,7 +224,5 @@ | ||
let height = dds.height; | ||
for ( let i = 0; i < dds.mipmapCount; i ++ ) { | ||
let byteArray, dataLength; | ||
if ( isRGBAUncompressed ) { | ||
@@ -230,0 +229,0 @@ |
( function () { | ||
const _taskCache = new WeakMap(); | ||
class DRACOLoader extends THREE.Loader { | ||
@@ -32,3 +31,2 @@ | ||
} | ||
setDecoderPath( path ) { | ||
@@ -40,3 +38,2 @@ | ||
} | ||
setDecoderConfig( config ) { | ||
@@ -48,3 +45,2 @@ | ||
} | ||
setWorkerLimit( workerLimit ) { | ||
@@ -56,3 +52,2 @@ | ||
} | ||
load( url, onLoad, onProgress, onError ) { | ||
@@ -72,3 +67,2 @@ | ||
} | ||
decodeDracoFile( buffer, callback, attributeIDs, attributeTypes ) { | ||
@@ -84,12 +78,11 @@ | ||
} | ||
decodeGeometry( buffer, taskConfig ) { | ||
const taskKey = JSON.stringify( taskConfig ); // Check for an existing task using this buffer. A transferred buffer cannot be transferred | ||
const taskKey = JSON.stringify( taskConfig ); | ||
// Check for an existing task using this buffer. A transferred buffer cannot be transferred | ||
// again from this thread. | ||
if ( _taskCache.has( buffer ) ) { | ||
const cachedTask = _taskCache.get( buffer ); | ||
if ( cachedTask.key === taskKey ) { | ||
@@ -109,10 +102,12 @@ | ||
} // | ||
} | ||
// | ||
let worker; | ||
const taskID = this.workerNextTaskID ++; | ||
const taskCost = buffer.byteLength; // Obtain a worker and assign a task, and construct a geometry instance | ||
const taskCost = buffer.byteLength; | ||
// Obtain a worker and assign a task, and construct a geometry instance | ||
// when the task completes. | ||
const geometryPending = this._getWorker( taskID, taskCost ).then( _worker => { | ||
@@ -132,10 +127,12 @@ | ||
buffer | ||
}, [ buffer ] ); // this.debug(); | ||
}, [ buffer ] ); | ||
// this.debug(); | ||
} ); | ||
} ).then( message => this._createGeometry( message.geometry ) ); // Remove task from the task list. | ||
} ).then( message => this._createGeometry( message.geometry ) ); | ||
// Remove task from the task list. | ||
// Note: replaced '.finally()' with '.catch().then()' block - iOS 11 support (#19416) | ||
geometryPending.catch( () => true ).then( () => { | ||
@@ -145,8 +142,11 @@ | ||
this._releaseTask( worker, taskID ); // this.debug(); | ||
this._releaseTask( worker, taskID ); | ||
// this.debug(); | ||
} | ||
} ); // Cache the task result. | ||
} ); | ||
// Cache the task result. | ||
_taskCache.set( buffer, { | ||
@@ -156,11 +156,8 @@ key: taskKey, | ||
} ); | ||
return geometryPending; | ||
} | ||
_createGeometry( geometryData ) { | ||
const geometry = new THREE.BufferGeometry(); | ||
if ( geometryData.index ) { | ||
@@ -185,3 +182,2 @@ | ||
} | ||
_loadLibrary( url, responseType ) { | ||
@@ -200,11 +196,8 @@ | ||
} | ||
preload() { | ||
this._initDecoder(); | ||
return this; | ||
} | ||
_initDecoder() { | ||
@@ -215,3 +208,2 @@ | ||
const librariesPending = []; | ||
if ( useJS ) { | ||
@@ -231,3 +223,2 @@ | ||
const jsContent = libraries[ 0 ]; | ||
if ( ! useJS ) { | ||
@@ -247,3 +238,2 @@ | ||
} | ||
_getWorker( taskID, taskCost ) { | ||
@@ -263,7 +253,5 @@ | ||
} ); | ||
worker.onmessage = function ( e ) { | ||
const message = e.data; | ||
switch ( message.type ) { | ||
@@ -273,10 +261,6 @@ | ||
worker._callbacks[ message.id ].resolve( message ); | ||
break; | ||
case 'error': | ||
worker._callbacks[ message.id ].reject( message ); | ||
break; | ||
default: | ||
@@ -309,3 +293,2 @@ console.error( 'THREE.DRACOLoader: Unexpected message, "' + message.type + '"' ); | ||
} | ||
_releaseTask( worker, taskID ) { | ||
@@ -318,3 +301,2 @@ | ||
} | ||
debug() { | ||
@@ -325,3 +307,2 @@ | ||
} | ||
dispose() { | ||
@@ -341,5 +322,5 @@ | ||
} | ||
/* WEB WORKER */ | ||
function DRACOWorker() { | ||
@@ -349,7 +330,5 @@ | ||
let decoderPending; | ||
onmessage = function ( e ) { | ||
const message = e.data; | ||
switch ( message.type ) { | ||
@@ -359,5 +338,3 @@ | ||
decoderConfig = message.decoderConfig; | ||
decoderPending = new Promise( function ( resolve | ||
/*, reject*/ | ||
) { | ||
decoderPending = new Promise( function ( resolve /*, reject*/ ) { | ||
@@ -376,4 +353,4 @@ decoderConfig.onModuleLoaded = function ( draco ) { | ||
} ); | ||
break; | ||
case 'decode': | ||
@@ -388,3 +365,2 @@ const buffer = message.buffer; | ||
decoderBuffer.Init( new Int8Array( buffer ), buffer.byteLength ); | ||
try { | ||
@@ -431,3 +407,2 @@ | ||
const geometryType = decoder.GetEncodedGeometryType( decoderBuffer ); | ||
if ( geometryType === draco.TRIANGULAR_MESH ) { | ||
@@ -458,4 +433,5 @@ | ||
attributes: [] | ||
}; // Gather all vertex attributes. | ||
}; | ||
// Gather all vertex attributes. | ||
for ( const attributeName in attributeIDs ) { | ||
@@ -465,7 +441,8 @@ | ||
let attribute; | ||
let attributeID; // A Draco file may be created with default vertex attributes, whose attribute IDs | ||
let attributeID; | ||
// A Draco file may be created with default vertex attributes, whose attribute IDs | ||
// are mapped 1:1 from their semantic name (POSITION, NORMAL, ...). Alternatively, | ||
// a Draco file may contain a custom set of attributes, identified by known unique | ||
// IDs. glTF files always do the latter, and `.drc` files typically do the former. | ||
if ( taskConfig.useUniqueIDs ) { | ||
@@ -486,5 +463,5 @@ | ||
} // Add index. | ||
} | ||
// Add index. | ||
if ( geometryType === draco.TRIANGULAR_MESH ) { | ||
@@ -506,10 +483,6 @@ | ||
const byteLength = numIndices * 4; | ||
const ptr = draco._malloc( byteLength ); | ||
decoder.GetTrianglesUInt32Array( dracoGeometry, byteLength, ptr ); | ||
const index = new Uint32Array( draco.HEAPF32.buffer, ptr, numIndices ).slice(); | ||
draco._free( ptr ); | ||
return { | ||
@@ -529,10 +502,6 @@ array: index, | ||
const dataType = getDracoDataType( draco, attributeType ); | ||
const ptr = draco._malloc( byteLength ); | ||
decoder.GetAttributeDataArrayForAllPoints( dracoGeometry, attribute, dataType, byteLength, ptr ); | ||
const array = new attributeType( draco.HEAPF32.buffer, ptr, numValues ).slice(); | ||
draco._free( ptr ); | ||
return { | ||
@@ -552,18 +521,12 @@ name: attributeName, | ||
return draco.DT_FLOAT32; | ||
case Int8Array: | ||
return draco.DT_INT8; | ||
case Int16Array: | ||
return draco.DT_INT16; | ||
case Int32Array: | ||
return draco.DT_INT32; | ||
case Uint8Array: | ||
return draco.DT_UINT8; | ||
case Uint16Array: | ||
return draco.DT_UINT16; | ||
case Uint32Array: | ||
@@ -570,0 +533,0 @@ return draco.DT_UINT32; |
@@ -10,5 +10,7 @@ ( function () { | ||
*/ | ||
// /* | ||
// Copyright (c) 2014 - 2017, Syoyo Fujita | ||
// All rights reserved. | ||
// Redistribution and use in source and binary forms, with or without | ||
@@ -24,2 +26,3 @@ // modification, are permitted provided that the following conditions are met: | ||
// derived from this software without specific prior written permission. | ||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND | ||
@@ -36,3 +39,5 @@ // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
// */ | ||
// // TinyEXR contains some OpenEXR code, which is licensed under ------------ | ||
// /////////////////////////////////////////////////////////////////////////// | ||
@@ -71,2 +76,3 @@ // // | ||
// /////////////////////////////////////////////////////////////////////////// | ||
// // End of OpenEXR license ------------------------------------------------- | ||
@@ -82,3 +88,2 @@ | ||
} | ||
parse( buffer ) { | ||
@@ -89,9 +94,6 @@ | ||
const HUF_ENCBITS = 16; // literal (value) bit length | ||
const HUF_DECBITS = 14; // decoding bit size (>= 8) | ||
const HUF_ENCSIZE = ( 1 << HUF_ENCBITS ) + 1; // encoding table size | ||
const HUF_DECSIZE = 1 << HUF_DECBITS; // decoding table size | ||
const HUF_DECMASK = HUF_DECSIZE - 1; | ||
@@ -115,7 +117,5 @@ const NBITS = 16; | ||
const logBase = Math.pow( 2.7182818, 2.2 ); | ||
function reverseLutFromBitmap( bitmap, lut ) { | ||
let k = 0; | ||
for ( let i = 0; i < USHORT_RANGE; ++ i ) { | ||
@@ -132,5 +132,3 @@ | ||
const n = k - 1; | ||
while ( k < USHORT_RANGE ) lut[ k ++ ] = 0; | ||
return n; | ||
@@ -158,3 +156,2 @@ | ||
}; | ||
function getBits( nBits, c, lc, uInt8Array, inOffset ) { | ||
@@ -177,11 +174,7 @@ | ||
const hufTableBuffer = new Array( 59 ); | ||
function hufCanonicalCodeTable( hcode ) { | ||
for ( let i = 0; i <= 58; ++ i ) hufTableBuffer[ i ] = 0; | ||
for ( let i = 0; i < HUF_ENCSIZE; ++ i ) hufTableBuffer[ hcode[ i ] ] += 1; | ||
let c = 0; | ||
for ( let i = 58; i > 0; -- i ) { | ||
@@ -209,3 +202,2 @@ | ||
let lc = 0; | ||
for ( ; im <= iM; im ++ ) { | ||
@@ -219,3 +211,2 @@ | ||
hcode[ im ] = l; | ||
if ( l == LONG_ZEROCODE_RUN ) { | ||
@@ -233,3 +224,2 @@ | ||
lc = getBitsReturn.lc; | ||
if ( im + zerun > iM + 1 ) { | ||
@@ -242,3 +232,2 @@ | ||
while ( zerun -- ) hcode[ im ++ ] = 0; | ||
im --; | ||
@@ -249,3 +238,2 @@ | ||
let zerun = l - SHORT_ZEROCODE_RUN + 2; | ||
if ( im + zerun > iM + 1 ) { | ||
@@ -258,3 +246,2 @@ | ||
while ( zerun -- ) hcode[ im ++ ] = 0; | ||
im --; | ||
@@ -288,3 +275,2 @@ | ||
const l = hufLength( hcode[ im ] ); | ||
if ( c >> l ) { | ||
@@ -299,3 +285,2 @@ | ||
const pl = hdecod[ c >> l - HUF_DECBITS ]; | ||
if ( pl.len ) { | ||
@@ -308,3 +293,2 @@ | ||
pl.lit ++; | ||
if ( pl.p ) { | ||
@@ -314,3 +298,2 @@ | ||
pl.p = new Array( pl.lit ); | ||
for ( let i = 0; i < pl.lit - 1; ++ i ) { | ||
@@ -333,7 +316,5 @@ | ||
let plOffset = 0; | ||
for ( let i = 1 << HUF_DECBITS - l; i > 0; i -- ) { | ||
const pl = hdecod[ ( c << HUF_DECBITS - l ) + plOffset ]; | ||
if ( pl.len || pl.p ) { | ||
@@ -363,3 +344,2 @@ | ||
}; | ||
function getChar( c, lc, uInt8Array, inOffset ) { | ||
@@ -378,3 +358,2 @@ | ||
}; | ||
function getCode( po, rlc, c, lc, uInt8Array, inOffset, outBuffer, outBufferOffset, outBufferEndOffset ) { | ||
@@ -395,3 +374,2 @@ | ||
cs = new Uint8Array( [ cs ] )[ 0 ]; | ||
if ( outBufferOffset.value + cs > outBufferEndOffset ) { | ||
@@ -404,3 +382,2 @@ | ||
const s = outBuffer[ outBufferOffset.value - 1 ]; | ||
while ( cs -- > 0 ) { | ||
@@ -444,3 +421,2 @@ | ||
}; | ||
function wdec14( l, h ) { | ||
@@ -477,9 +453,6 @@ | ||
let py; | ||
while ( p <= n ) p <<= 1; | ||
p >>= 1; | ||
p2 = p; | ||
p >>= 1; | ||
while ( p >= 1 ) { | ||
@@ -494,3 +467,2 @@ | ||
let i00, i01, i10, i11; | ||
for ( ; py <= ey; py += oy2 ) { | ||
@@ -500,3 +472,2 @@ | ||
const ex = py + ox * ( nx - p2 ); | ||
for ( ; px <= ex; px += ox2 ) { | ||
@@ -507,3 +478,2 @@ | ||
const p11 = p10 + ox1; | ||
if ( w14 ) { | ||
@@ -559,3 +529,2 @@ | ||
const ex = py + ox * ( nx - p2 ); | ||
for ( ; px <= ex; px += ox2 ) { | ||
@@ -588,3 +557,2 @@ | ||
const inOffsetEnd = Math.trunc( inOffset.value + ( ni + 7 ) / 8 ); | ||
while ( inOffset.value < inOffsetEnd ) { | ||
@@ -595,3 +563,2 @@ | ||
lc = getCharReturn.lc; | ||
while ( lc >= HUF_DECBITS ) { | ||
@@ -601,3 +568,2 @@ | ||
const pl = decodingTable[ index ]; | ||
if ( pl.len ) { | ||
@@ -619,7 +585,5 @@ | ||
let j; | ||
for ( j = 0; j < pl.lit; j ++ ) { | ||
const l = hufLength( encodingTable[ pl.p[ j ] ] ); | ||
while ( lc < l && inOffset.value < inOffsetEnd ) { | ||
@@ -664,7 +628,5 @@ | ||
lc -= i; | ||
while ( lc > 0 ) { | ||
const pl = decodingTable[ c << HUF_DECBITS - lc & HUF_DECMASK ]; | ||
if ( pl.len ) { | ||
@@ -700,3 +662,2 @@ | ||
inOffset.value += 4; | ||
if ( im < 0 || im >= HUF_ENCSIZE || iM < 0 || iM >= HUF_ENCSIZE ) { | ||
@@ -713,3 +674,2 @@ | ||
hufUnpackEncTable( uInt8Array, inOffset, ni, im, iM, freq ); | ||
if ( nBits > 8 * ( nCompressed - ( inOffset.value - initialInOffset ) ) ) { | ||
@@ -753,3 +713,2 @@ | ||
const stop = source.length - 1; | ||
while ( true ) { | ||
@@ -772,7 +731,5 @@ | ||
const reader = new DataView( source ); | ||
while ( size > 0 ) { | ||
const l = reader.getInt8( p ++ ); | ||
if ( l < 0 ) { | ||
@@ -782,3 +739,2 @@ | ||
size -= count + 1; | ||
for ( let i = 0; i < count; i ++ ) { | ||
@@ -795,3 +751,2 @@ | ||
const value = reader.getUint8( p ++ ); | ||
for ( let i = 0; i < count + 1; i ++ ) { | ||
@@ -830,3 +785,2 @@ | ||
const rowOffsets = new Array( numComp ); | ||
for ( let comp = 0; comp < numComp; ++ comp ) { | ||
@@ -847,17 +801,17 @@ | ||
let maxX = 8; | ||
for ( let blockx = 0; blockx < numBlocksX; ++ blockx ) { | ||
if ( blockx == numBlocksX - 1 ) maxX = leftoverX; | ||
for ( let comp = 0; comp < numComp; ++ comp ) { | ||
halfZigBlock[ comp ].fill( 0 ); // set block DC component | ||
halfZigBlock[ comp ].fill( 0 ); | ||
halfZigBlock[ comp ][ 0 ] = dcBuffer[ currDcComp[ comp ] ++ ]; // set block AC components | ||
// set block DC component | ||
halfZigBlock[ comp ][ 0 ] = dcBuffer[ currDcComp[ comp ] ++ ]; | ||
// set block AC components | ||
unRleAC( currAcComp, acBuffer, halfZigBlock[ comp ] ); | ||
unRleAC( currAcComp, acBuffer, halfZigBlock[ comp ] ); // UnZigZag block to float | ||
unZigZag( halfZigBlock[ comp ], dctData[ comp ] ); // decode float dct | ||
// UnZigZag block to float | ||
unZigZag( halfZigBlock[ comp ], dctData[ comp ] ); | ||
// decode float dct | ||
dctInverse( dctData[ comp ] ); | ||
@@ -881,13 +835,9 @@ | ||
let offset = 0; | ||
for ( let comp = 0; comp < numComp; ++ comp ) { | ||
const type = channelData[ cscSet.idx[ comp ] ].type; | ||
for ( let y = 8 * blocky; y < 8 * blocky + maxY; ++ y ) { | ||
offset = rowOffsets[ comp ][ y ]; | ||
for ( let blockx = 0; blockx < numFullBlocksX; ++ blockx ) { | ||
@@ -908,5 +858,5 @@ | ||
} // handle partial X blocks | ||
} | ||
// handle partial X blocks | ||
if ( numFullBlocksX != numBlocksX ) { | ||
@@ -918,3 +868,2 @@ | ||
const src = numFullBlocksX * 64 + ( y & 0x7 ) * 8; | ||
for ( let x = 0; x < maxX; ++ x ) { | ||
@@ -934,6 +883,6 @@ | ||
const halfRow = new Uint16Array( width ); | ||
dataView = new DataView( outBuffer.buffer ); // convert channels back to float, if needed | ||
dataView = new DataView( outBuffer.buffer ); | ||
// convert channels back to float, if needed | ||
for ( let comp = 0; comp < numComp; ++ comp ) { | ||
@@ -944,7 +893,5 @@ | ||
if ( channelData[ comp ].type != 2 ) continue; | ||
for ( let y = 0; y < height; ++ y ) { | ||
const offset = rowOffsets[ comp ][ y ]; | ||
for ( let x = 0; x < width; ++ x ) { | ||
@@ -972,7 +919,5 @@ | ||
let dctComp = 1; | ||
while ( dctComp < 64 ) { | ||
acValue = acBuffer[ currAcComp.value ]; | ||
if ( acValue == 0xff00 ) { | ||
@@ -1081,3 +1026,2 @@ | ||
const gamma = new Array( 4 ); | ||
for ( let row = 0; row < 8; ++ row ) { | ||
@@ -1205,3 +1149,2 @@ | ||
const compressed = info.array.slice( info.offset.value, info.offset.value + info.size ); | ||
if ( typeof fflate === 'undefined' ) { | ||
@@ -1214,3 +1157,2 @@ | ||
const rawBuffer = fflate.unzlibSync( compressed ); // eslint-disable-line no-undef | ||
const tmpBuffer = new Uint8Array( rawBuffer.length ); | ||
@@ -1232,7 +1174,7 @@ predictor( rawBuffer ); // revert predictor | ||
const outBuffer = new Uint16Array( info.width * info.scanlineBlockSize * ( info.channels * info.type ) ); | ||
const bitmap = new Uint8Array( BITMAP_SIZE ); // Setup channel info | ||
const bitmap = new Uint8Array( BITMAP_SIZE ); | ||
// Setup channel info | ||
let outBufferEnd = 0; | ||
const pizChannelData = new Array( info.channels ); | ||
for ( let i = 0; i < info.channels; i ++ ) { | ||
@@ -1248,8 +1190,8 @@ | ||
} // Read range compression data | ||
} | ||
// Read range compression data | ||
const minNonZero = parseUint16( inDataView, inOffset ); | ||
const maxNonZero = parseUint16( inDataView, inOffset ); | ||
if ( maxNonZero >= BITMAP_SIZE ) { | ||
@@ -1269,15 +1211,16 @@ | ||
} // Reverse LUT | ||
} | ||
// Reverse LUT | ||
const lut = new Uint16Array( USHORT_RANGE ); | ||
const maxValue = reverseLutFromBitmap( bitmap, lut ); | ||
const length = parseUint32( inDataView, inOffset ); // Huffman decoding | ||
const length = parseUint32( inDataView, inOffset ); | ||
hufUncompress( info.array, inDataView, inOffset, length, outBuffer, outBufferEnd ); // Wavelet decoding | ||
// Huffman decoding | ||
hufUncompress( info.array, inDataView, inOffset, length, outBuffer, outBufferEnd ); | ||
// Wavelet decoding | ||
for ( let i = 0; i < info.channels; ++ i ) { | ||
const cd = pizChannelData[ i ]; | ||
for ( let j = 0; j < pizChannelData[ i ].size; ++ j ) { | ||
@@ -1289,10 +1232,10 @@ | ||
} // Expand the pixel data to their original range | ||
} | ||
// Expand the pixel data to their original range | ||
applyLut( lut, outBuffer, outBufferEnd ); | ||
applyLut( lut, outBuffer, outBufferEnd ); // Rearrange the pixel data into the format expected by the caller. | ||
// Rearrange the pixel data into the format expected by the caller. | ||
let tmpOffset = 0; | ||
const tmpBuffer = new Uint8Array( outBuffer.buffer.byteLength ); | ||
for ( let y = 0; y < info.lines; y ++ ) { | ||
@@ -1320,3 +1263,2 @@ | ||
const compressed = info.array.slice( info.offset.value, info.offset.value + info.size ); | ||
if ( typeof fflate === 'undefined' ) { | ||
@@ -1335,3 +1277,2 @@ | ||
const ptr = new Array( 4 ); | ||
for ( let y = 0; y < info.lines; y ++ ) { | ||
@@ -1342,3 +1283,2 @@ | ||
let pixel = 0; | ||
switch ( info.type ) { | ||
@@ -1350,3 +1290,2 @@ | ||
tmpBufferEnd = ptr[ 1 ] + info.width; | ||
for ( let j = 0; j < info.width; ++ j ) { | ||
@@ -1362,3 +1301,2 @@ | ||
break; | ||
case 2: | ||
@@ -1369,3 +1307,2 @@ ptr[ 0 ] = tmpBufferEnd; | ||
tmpBufferEnd = ptr[ 2 ] + info.width; | ||
for ( let j = 0; j < info.width; ++ j ) { | ||
@@ -1398,4 +1335,5 @@ | ||
}; | ||
const outBuffer = new Uint8Array( info.width * info.lines * ( info.channels * info.type * INT16_SIZE ) ); // Read compression header information | ||
const outBuffer = new Uint8Array( info.width * info.lines * ( info.channels * info.type * INT16_SIZE ) ); | ||
// Read compression header information | ||
const dwaHeader = { | ||
@@ -1414,7 +1352,7 @@ version: parseInt64( inDataView, inOffset ), | ||
}; | ||
if ( dwaHeader.version < 2 ) throw new Error( 'EXRLoader.parse: ' + EXRHeader.compression + ' version ' + dwaHeader.version + ' is unsupported' ); // Read channel ruleset information | ||
if ( dwaHeader.version < 2 ) throw new Error( 'EXRLoader.parse: ' + EXRHeader.compression + ' version ' + dwaHeader.version + ' is unsupported' ); | ||
// Read channel ruleset information | ||
const channelRules = new Array(); | ||
let ruleSize = parseUint16( inDataView, inOffset ) - INT16_SIZE; | ||
while ( ruleSize > 0 ) { | ||
@@ -1436,8 +1374,7 @@ | ||
} // Classify channels | ||
} | ||
// Classify channels | ||
const channels = EXRHeader.channels; | ||
const channelData = new Array( info.channels ); | ||
for ( let i = 0; i < info.channels; ++ i ) { | ||
@@ -1460,15 +1397,11 @@ | ||
}; | ||
for ( let offset = 0; offset < info.channels; ++ offset ) { | ||
const cd = channelData[ offset ]; | ||
for ( let i = 0; i < channelRules.length; ++ i ) { | ||
const rule = channelRules[ i ]; | ||
if ( cd.name == rule.name ) { | ||
cd.compression = rule.compression; | ||
if ( rule.index >= 0 ) { | ||
@@ -1488,4 +1421,5 @@ | ||
let acBuffer, dcBuffer, rleBuffer; // Read DCT - AC component data | ||
let acBuffer, dcBuffer, rleBuffer; | ||
// Read DCT - AC component data | ||
if ( dwaHeader.acCompressedSize > 0 ) { | ||
@@ -1499,7 +1433,5 @@ | ||
break; | ||
case DEFLATE: | ||
const compressed = info.array.slice( inOffset.value, inOffset.value + dwaHeader.totalAcUncompressedCount ); | ||
const data = fflate.unzlibSync( compressed ); // eslint-disable-line no-undef | ||
acBuffer = new Uint16Array( data.buffer ); | ||
@@ -1511,5 +1443,5 @@ inOffset.value += dwaHeader.totalAcUncompressedCount; | ||
} // Read DCT - DC component data | ||
} | ||
// Read DCT - DC component data | ||
if ( dwaHeader.dcCompressedSize > 0 ) { | ||
@@ -1525,5 +1457,5 @@ | ||
} // Read RLE compressed data | ||
} | ||
// Read RLE compressed data | ||
if ( dwaHeader.rleRawSize > 0 ) { | ||
@@ -1533,12 +1465,10 @@ | ||
const data = fflate.unzlibSync( compressed ); // eslint-disable-line no-undef | ||
rleBuffer = decodeRunLength( data.buffer ); | ||
inOffset.value += dwaHeader.rleCompressedSize; | ||
} // Prepare outbuffer data offset | ||
} | ||
// Prepare outbuffer data offset | ||
let outBufferEnd = 0; | ||
const rowOffsets = new Array( channelData.length ); | ||
for ( let i = 0; i < rowOffsets.length; ++ i ) { | ||
@@ -1559,7 +1489,8 @@ | ||
} // Lossy DCT decode RGB channels | ||
} | ||
// Lossy DCT decode RGB channels | ||
lossyDctDecode( cscSet, rowOffsets, channelData, acBuffer, dcBuffer, outBuffer ); | ||
lossyDctDecode( cscSet, rowOffsets, channelData, acBuffer, dcBuffer, outBuffer ); // Decode other channels | ||
// Decode other channels | ||
for ( let i = 0; i < channelData.length; ++ i ) { | ||
@@ -1569,3 +1500,2 @@ | ||
if ( cd.decoded ) continue; | ||
switch ( cd.compression ) { | ||
@@ -1576,7 +1506,5 @@ | ||
let rleOffset = 0; | ||
for ( let y = 0; y < info.lines; ++ y ) { | ||
let rowOffsetBytes = rowOffsets[ i ][ row ]; | ||
for ( let x = 0; x < cd.width; ++ x ) { | ||
@@ -1599,3 +1527,2 @@ | ||
break; | ||
case LOSSY_DCT: // skip | ||
@@ -1618,3 +1545,2 @@ | ||
let endOffset = 0; | ||
while ( uintBuffer[ offset.value + endOffset ] != 0 ) { | ||
@@ -1708,5 +1634,5 @@ | ||
} // https://stackoverflow.com/questions/5678432/decompressing-half-precision-floats-in-javascript | ||
} | ||
// https://stackoverflow.com/questions/5678432/decompressing-half-precision-floats-in-javascript | ||
function decodeFloat16( binary ) { | ||
@@ -1738,3 +1664,2 @@ | ||
const channels = []; | ||
while ( offset.value < startOffset + size - 1 ) { | ||
@@ -1746,3 +1671,2 @@ | ||
offset.value += 3; // reserved, three chars | ||
const xSampling = parseInt32( dataView, offset ); | ||
@@ -1903,6 +1827,6 @@ const ySampling = parseInt32( dataView, offset ); | ||
const EXRHeader = {}; | ||
if ( dataView.getUint32( 0, true ) != 20000630 ) { | ||
// magic | ||
throw new Error( 'THREE.EXRLoader: provided file doesn\'t appear to be in OpenEXR format.' ); | ||
@@ -1920,12 +1844,12 @@ | ||
multiPart: !! ( spec & 16 ) | ||
}; // start of header | ||
}; | ||
// start of header | ||
offset.value = 8; // start at 8 - after pre-amble | ||
let keepReading = true; | ||
while ( keepReading ) { | ||
const attributeName = parseNullTerminatedString( buffer, offset ); | ||
if ( attributeName == 0 ) { | ||
@@ -1940,3 +1864,2 @@ | ||
const attributeValue = parseValue( dataView, buffer, offset, attributeType, attributeSize ); | ||
if ( attributeValue === undefined ) { | ||
@@ -1959,2 +1882,3 @@ | ||
// unsupported tiled, deep-image, multi-part | ||
console.error( 'EXRHeader:', EXRHeader ); | ||
@@ -1988,3 +1912,2 @@ throw new Error( 'THREE.EXRLoader: provided file is currently unsupported.' ); | ||
}; | ||
switch ( EXRHeader.compression ) { | ||
@@ -1996,3 +1919,2 @@ | ||
break; | ||
case 'RLE_COMPRESSION': | ||
@@ -2002,3 +1924,2 @@ EXRDecoder.lines = 1; | ||
break; | ||
case 'ZIPS_COMPRESSION': | ||
@@ -2008,3 +1929,2 @@ EXRDecoder.lines = 1; | ||
break; | ||
case 'ZIP_COMPRESSION': | ||
@@ -2014,3 +1934,2 @@ EXRDecoder.lines = 16; | ||
break; | ||
case 'PIZ_COMPRESSION': | ||
@@ -2020,3 +1939,2 @@ EXRDecoder.lines = 32; | ||
break; | ||
case 'PXR24_COMPRESSION': | ||
@@ -2026,3 +1944,2 @@ EXRDecoder.lines = 16; | ||
break; | ||
case 'DWAA_COMPRESSION': | ||
@@ -2032,3 +1949,2 @@ EXRDecoder.lines = 32; | ||
break; | ||
case 'DWAB_COMPRESSION': | ||
@@ -2038,3 +1954,2 @@ EXRDecoder.lines = 256; | ||
break; | ||
default: | ||
@@ -2046,3 +1961,2 @@ throw new Error( 'EXRLoader.parse: ' + EXRHeader.compression + ' is unsupported' ); | ||
EXRDecoder.scanlineBlockSize = EXRDecoder.lines; | ||
if ( EXRDecoder.type == 1 ) { | ||
@@ -2057,3 +1971,2 @@ | ||
break; | ||
case THREE.HalfFloatType: | ||
@@ -2075,3 +1988,2 @@ EXRDecoder.getter = parseUint16; | ||
break; | ||
case THREE.HalfFloatType: | ||
@@ -2090,19 +2002,17 @@ EXRDecoder.getter = decodeFloat32; | ||
EXRDecoder.blockCount = ( EXRHeader.dataWindow.yMax + 1 ) / EXRDecoder.scanlineBlockSize; | ||
for ( let i = 0; i < EXRDecoder.blockCount; i ++ ) parseInt64( dataView, offset ); // scanlineOffset | ||
for ( let i = 0; i < EXRDecoder.blockCount; i ++ ) parseInt64( dataView, offset ); // scanlineOffset | ||
// we should be passed the scanline offset table, ready to start reading pixel data. | ||
// RGB images will be converted to RGBA format, preventing software emulation in select devices. | ||
EXRDecoder.outputChannels = EXRDecoder.channels == 3 ? 4 : EXRDecoder.channels; | ||
const size = EXRDecoder.width * EXRDecoder.height * EXRDecoder.outputChannels; | ||
switch ( outputType ) { | ||
case THREE.FloatType: | ||
EXRDecoder.byteArray = new Float32Array( size ); // Fill initially with 1s for the alpha value if the texture is not RGBA, RGB values will be overwritten | ||
EXRDecoder.byteArray = new Float32Array( size ); | ||
// Fill initially with 1s for the alpha value if the texture is not RGBA, RGB values will be overwritten | ||
if ( EXRDecoder.channels < EXRDecoder.outputChannels ) EXRDecoder.byteArray.fill( 1, 0, size ); | ||
break; | ||
case THREE.HalfFloatType: | ||
@@ -2113,3 +2023,2 @@ EXRDecoder.byteArray = new Uint16Array( size ); | ||
break; | ||
default: | ||
@@ -2122,3 +2031,2 @@ console.error( 'THREE.EXRLoader: unsupported type: ', outputType ); | ||
EXRDecoder.bytesPerLine = EXRDecoder.width * EXRDecoder.inputSize * EXRDecoder.channels; | ||
if ( EXRDecoder.outputChannels == 4 ) { | ||
@@ -2138,4 +2046,5 @@ | ||
} // start parsing file [START] | ||
} | ||
// start parsing file [START] | ||
@@ -2146,6 +2055,8 @@ const bufferDataView = new DataView( buffer ); | ||
value: 0 | ||
}; // get header information and validate format. | ||
}; | ||
const EXRHeader = parseHeader( bufferDataView, buffer, offset ); // get input compression information and prepare decoding. | ||
// get header information and validate format. | ||
const EXRHeader = parseHeader( bufferDataView, buffer, offset ); | ||
// get input compression information and prepare decoding. | ||
const EXRDecoder = setupDecoder( EXRHeader, bufferDataView, uInt8Array, offset, this.type ); | ||
@@ -2162,9 +2073,6 @@ const tmpOffset = { | ||
}; | ||
for ( let scanlineBlockIdx = 0; scanlineBlockIdx < EXRDecoder.height / EXRDecoder.scanlineBlockSize; scanlineBlockIdx ++ ) { | ||
const line = parseUint32( bufferDataView, offset ); // line_no | ||
EXRDecoder.size = parseUint32( bufferDataView, offset ); // data_len | ||
EXRDecoder.lines = line + EXRDecoder.scanlineBlockSize > EXRDecoder.height ? EXRDecoder.height - line : EXRDecoder.scanlineBlockSize; | ||
@@ -2174,3 +2082,2 @@ const isCompressed = EXRDecoder.size < EXRDecoder.lines * EXRDecoder.bytesPerLine; | ||
offset.value += EXRDecoder.size; | ||
for ( let line_y = 0; line_y < EXRDecoder.scanlineBlockSize; line_y ++ ) { | ||
@@ -2180,7 +2087,5 @@ | ||
if ( true_y >= EXRDecoder.height ) break; | ||
for ( let channelID = 0; channelID < EXRDecoder.channels; channelID ++ ) { | ||
const cOff = channelOffsets[ EXRHeader.channels[ channelID ].name ]; | ||
for ( let x = 0; x < EXRDecoder.width; x ++ ) { | ||
@@ -2211,3 +2116,2 @@ | ||
} | ||
setDataType( value ) { | ||
@@ -2219,3 +2123,2 @@ | ||
} | ||
load( url, onLoad, onProgress, onError ) { | ||
@@ -2222,0 +2125,0 @@ |
@@ -10,3 +10,2 @@ ( function () { | ||
} | ||
load( url, onLoad, onProgress, onError ) { | ||
@@ -27,3 +26,2 @@ | ||
} | ||
parse( json ) { | ||
@@ -35,4 +33,5 @@ | ||
} // | ||
} | ||
// | ||
@@ -48,3 +47,2 @@ class Font { | ||
} | ||
generateShapes( text, size = 100 ) { | ||
@@ -54,3 +52,2 @@ | ||
const paths = createPaths( text, size, this.data ); | ||
for ( let p = 0, pl = paths.length; p < pl; p ++ ) { | ||
@@ -67,3 +64,2 @@ | ||
} | ||
function createPaths( text, size, data ) { | ||
@@ -77,7 +73,5 @@ | ||
offsetY = 0; | ||
for ( let i = 0; i < chars.length; i ++ ) { | ||
const char = chars[ i ]; | ||
if ( char === '\n' ) { | ||
@@ -105,3 +99,2 @@ | ||
const glyph = data.glyphs[ char ] || data.glyphs[ '?' ]; | ||
if ( ! glyph ) { | ||
@@ -116,11 +109,8 @@ | ||
let x, y, cpx, cpy, cpx1, cpy1, cpx2, cpy2; | ||
if ( glyph.o ) { | ||
const outline = glyph._cachedOutline || ( glyph._cachedOutline = glyph.o.split( ' ' ) ); | ||
for ( let i = 0, l = outline.length; i < l; ) { | ||
const action = outline[ i ++ ]; | ||
switch ( action ) { | ||
@@ -130,2 +120,3 @@ | ||
// moveTo | ||
x = outline[ i ++ ] * scale + offsetX; | ||
@@ -135,5 +126,5 @@ y = outline[ i ++ ] * scale + offsetY; | ||
break; | ||
case 'l': | ||
// lineTo | ||
x = outline[ i ++ ] * scale + offsetX; | ||
@@ -143,5 +134,5 @@ y = outline[ i ++ ] * scale + offsetY; | ||
break; | ||
case 'q': | ||
// quadraticCurveTo | ||
cpx = outline[ i ++ ] * scale + offsetX; | ||
@@ -153,5 +144,5 @@ cpy = outline[ i ++ ] * scale + offsetY; | ||
break; | ||
case 'b': | ||
// bezierCurveTo | ||
cpx = outline[ i ++ ] * scale + offsetX; | ||
@@ -158,0 +149,0 @@ cpy = outline[ i ++ ] * scale + offsetY; |
@@ -20,3 +20,2 @@ ( function () { | ||
} | ||
load( url, onLoad, onProgress, onError ) { | ||
@@ -54,3 +53,2 @@ | ||
} | ||
parse( data ) { | ||
@@ -77,3 +75,2 @@ | ||
extrudingMaterial.name = 'extruded'; | ||
function newLayer( line ) { | ||
@@ -88,5 +85,5 @@ | ||
} //Create lie segment between p1 and p2 | ||
} | ||
//Create lie segment between p1 and p2 | ||
function addSegment( p1, p2 ) { | ||
@@ -127,8 +124,8 @@ | ||
const lines = data.replace( /;.+/g, '' ).split( '\n' ); | ||
for ( let i = 0; i < lines.length; i ++ ) { | ||
const tokens = lines[ i ].split( ' ' ); | ||
const cmd = tokens[ 0 ].toUpperCase(); //Argumments | ||
const cmd = tokens[ 0 ].toUpperCase(); | ||
//Argumments | ||
const args = {}; | ||
@@ -145,5 +142,6 @@ tokens.splice( 1 ).forEach( function ( token ) { | ||
} ); //Process commands | ||
} ); | ||
//Process commands | ||
//G0/G1 – Linear Movement | ||
if ( cmd === 'G0' || cmd === 'G1' ) { | ||
@@ -157,8 +155,8 @@ | ||
f: args.f !== undefined ? absolute( state.f, args.f ) : state.f | ||
}; //Layer change detection is or made by watching Z, it's made by watching when we extrude at a new Z position | ||
}; | ||
//Layer change detection is or made by watching Z, it's made by watching when we extrude at a new Z position | ||
if ( delta( state.e, line.e ) > 0 ) { | ||
state.extruding = delta( state.e, line.e ) > 0; | ||
if ( currentLayer == undefined || line.z != currentLayer.z ) { | ||
@@ -175,3 +173,5 @@ | ||
} else if ( cmd === 'G2' || cmd === 'G3' ) { //G2/G3 - Arc Movement ( G2 clock wise and G3 counter clock wise ) | ||
} else if ( cmd === 'G2' || cmd === 'G3' ) { | ||
//G2/G3 - Arc Movement ( G2 clock wise and G3 counter clock wise ) | ||
//console.warn( 'THREE.GCodeLoader: Arc command not supported' ); | ||
@@ -197,3 +197,5 @@ } else if ( cmd === 'G90' ) { | ||
} else { //console.warn( 'THREE.GCodeLoader: Command not supported:' + cmd ); | ||
} else { | ||
//console.warn( 'THREE.GCodeLoader: Command not supported:' + cmd ); | ||
} | ||
@@ -215,3 +217,2 @@ | ||
object.name = 'gcode'; | ||
if ( this.splitLayer ) { | ||
@@ -231,3 +232,2 @@ | ||
pathVertex = []; | ||
for ( let i = 0; i < layers.length; i ++ ) { | ||
@@ -238,3 +238,2 @@ | ||
const layerPathVertex = layer.pathVertex; | ||
for ( let j = 0; j < layerVertex.length; j ++ ) { | ||
@@ -241,0 +240,0 @@ |
@@ -12,3 +12,2 @@ ( function () { | ||
} | ||
load( urls, onLoad, onProgress, onError ) { | ||
@@ -18,3 +17,2 @@ | ||
texture.type = this.type; | ||
switch ( texture.type ) { | ||
@@ -28,3 +26,2 @@ | ||
break; | ||
case THREE.HalfFloatType: | ||
@@ -41,3 +38,2 @@ texture.encoding = THREE.LinearEncoding; | ||
let loaded = 0; | ||
function loadHDRData( i, onLoad, onProgress, onError ) { | ||
@@ -50,3 +46,2 @@ | ||
if ( ! texData ) return; | ||
if ( texData.data !== undefined ) { | ||
@@ -85,3 +80,2 @@ | ||
} | ||
setDataType( value ) { | ||
@@ -88,0 +82,0 @@ |
@@ -10,3 +10,2 @@ ( function () { | ||
} | ||
load( url, onLoad, onProgress, onError ) { | ||
@@ -45,3 +44,2 @@ | ||
} | ||
parse( data ) { | ||
@@ -67,3 +65,2 @@ | ||
const image = findFile( url ); | ||
if ( image ) { | ||
@@ -81,4 +78,6 @@ | ||
} ); // | ||
} ); | ||
// | ||
const zip = fflate.unzipSync( new Uint8Array( data ) ); // eslint-disable-line no-undef | ||
@@ -91,3 +90,2 @@ | ||
const model = xml.querySelector( 'Placemark Model Link href' ); | ||
if ( model ) { | ||
@@ -103,7 +101,5 @@ | ||
console.warn( 'KMZLoader: Missing doc.kml file.' ); | ||
for ( const path in zip ) { | ||
const extension = path.split( '.' ).pop().toLowerCase(); | ||
if ( extension === 'dae' ) { | ||
@@ -110,0 +106,0 @@ |
@@ -17,3 +17,2 @@ ( function () { | ||
} | ||
parse( buffer, loadMipmaps ) { | ||
@@ -34,6 +33,4 @@ | ||
} | ||
const HEADER_LEN = 12 + 13 * 4; // identifier + header elements (not including key value meta-data pairs) | ||
// load types | ||
const COMPRESSED_2D = 0; // uses a gl.compressedTexImage2D() | ||
@@ -52,12 +49,10 @@ //const COMPRESSED_3D = 1; // uses a gl.compressedTexImage3D() | ||
*/ | ||
constructor( arrayBuffer, facesExpected | ||
/*, threeDExpected, textureArrayExpected */ | ||
) { | ||
constructor( arrayBuffer, facesExpected /*, threeDExpected, textureArrayExpected */ ) { | ||
this.arrayBuffer = arrayBuffer; // Test that it is a ktx formatted file, based on the first 12 bytes, character representation is: | ||
this.arrayBuffer = arrayBuffer; | ||
// Test that it is a ktx formatted file, based on the first 12 bytes, character representation is: | ||
// '´', 'K', 'T', 'X', ' ', '1', '1', 'ª', '\r', '\n', '\x1A', '\n' | ||
// 0xAB, 0x4B, 0x54, 0x58, 0x20, 0x31, 0x31, 0xBB, 0x0D, 0x0A, 0x1A, 0x0A | ||
const identifier = new Uint8Array( this.arrayBuffer, 0, 12 ); | ||
if ( identifier[ 0 ] !== 0xAB || identifier[ 1 ] !== 0x4B || identifier[ 2 ] !== 0x54 || identifier[ 3 ] !== 0x58 || identifier[ 4 ] !== 0x20 || identifier[ 5 ] !== 0x31 || identifier[ 6 ] !== 0x31 || identifier[ 7 ] !== 0xBB || identifier[ 8 ] !== 0x0D || identifier[ 9 ] !== 0x0A || identifier[ 10 ] !== 0x1A || identifier[ 11 ] !== 0x0A ) { | ||
@@ -68,5 +63,5 @@ | ||
} // load the reset of the header in native 32 bit uint | ||
} | ||
// load the reset of the header in native 32 bit uint | ||
const dataSize = Uint32Array.BYTES_PER_ELEMENT; | ||
@@ -77,26 +72,15 @@ const headerDataView = new DataView( this.arrayBuffer, 12, 13 * dataSize ); | ||
this.glType = headerDataView.getUint32( 1 * dataSize, littleEndian ); // must be 0 for compressed textures | ||
this.glTypeSize = headerDataView.getUint32( 2 * dataSize, littleEndian ); // must be 1 for compressed textures | ||
this.glFormat = headerDataView.getUint32( 3 * dataSize, littleEndian ); // must be 0 for compressed textures | ||
this.glInternalFormat = headerDataView.getUint32( 4 * dataSize, littleEndian ); // the value of arg passed to gl.compressedTexImage2D(,,x,,,,) | ||
this.glBaseInternalFormat = headerDataView.getUint32( 5 * dataSize, littleEndian ); // specify GL_RGB, GL_RGBA, GL_ALPHA, etc (un-compressed only) | ||
this.pixelWidth = headerDataView.getUint32( 6 * dataSize, littleEndian ); // level 0 value of arg passed to gl.compressedTexImage2D(,,,x,,,) | ||
this.pixelHeight = headerDataView.getUint32( 7 * dataSize, littleEndian ); // level 0 value of arg passed to gl.compressedTexImage2D(,,,,x,,) | ||
this.pixelDepth = headerDataView.getUint32( 8 * dataSize, littleEndian ); // level 0 value of arg passed to gl.compressedTexImage3D(,,,,,x,,) | ||
this.numberOfArrayElements = headerDataView.getUint32( 9 * dataSize, littleEndian ); // used for texture arrays | ||
this.numberOfFaces = headerDataView.getUint32( 10 * dataSize, littleEndian ); // used for cubemap textures, should either be 1 or 6 | ||
this.numberOfMipmapLevels = headerDataView.getUint32( 11 * dataSize, littleEndian ); // number of levels; disregard possibility of 0 for compressed textures | ||
this.bytesOfKeyValueData = headerDataView.getUint32( 12 * dataSize, littleEndian ); // the amount of space after the header for meta-data | ||
this.bytesOfKeyValueData = headerDataView.getUint32( 12 * dataSize, littleEndian ); // the amount of space after the header for meta-data | ||
// Make sure we have a compressed type. Not only reduces work, but probably better to let dev know they are not compressing. | ||
if ( this.glType !== 0 ) { | ||
@@ -133,14 +117,14 @@ | ||
} // we now have a completely validated file, so could use existence of loadType as success | ||
} | ||
// we now have a completely validated file, so could use existence of loadType as success | ||
// would need to make this more elaborate & adjust checks above to support more than one load type | ||
this.loadType = COMPRESSED_2D; | ||
} | ||
mipmaps( loadMipmaps ) { | ||
const mipmaps = []; // initialize width & height for level 1 | ||
const mipmaps = []; | ||
// initialize width & height for level 1 | ||
let dataOffset = HEADER_LEN + this.bytesOfKeyValueData; | ||
@@ -150,7 +134,5 @@ let width = this.pixelWidth; | ||
const mipmapCount = loadMipmaps ? this.numberOfMipmapLevels : 1; | ||
for ( let level = 0; level < mipmapCount; level ++ ) { | ||
const imageSize = new Int32Array( this.arrayBuffer, dataOffset, 1 )[ 0 ]; // size per face, since not supporting array cubemaps | ||
dataOffset += 4; // size of the image + 4 for the imageSize field | ||
@@ -157,0 +139,0 @@ |
( function () { | ||
// Special surface finish tag types. | ||
// Note: "MATERIAL" tag (e.g. GLITTER, SPECKLE) is not implemented | ||
const FINISH_TYPE_DEFAULT = 0; | ||
@@ -10,5 +10,6 @@ const FINISH_TYPE_CHROME = 1; | ||
const FINISH_TYPE_MATTE_METALLIC = 4; | ||
const FINISH_TYPE_METAL = 5; // State machine to search a subobject path. | ||
const FINISH_TYPE_METAL = 5; | ||
// State machine to search a subobject path. | ||
// The LDraw standard establishes these various possible subfolders. | ||
const FILE_LOCATION_TRY_PARTS = 0; | ||
@@ -23,7 +24,4 @@ const FILE_LOCATION_TRY_P = 1; | ||
const MAIN_EDGE_COLOUR_CODE = '24'; | ||
const _tempVec0 = new THREE.Vector3(); | ||
const _tempVec1 = new THREE.Vector3(); | ||
class LDrawConditionalLineMaterial extends THREE.ShaderMaterial { | ||
@@ -42,5 +40,3 @@ | ||
} ] ), | ||
vertexShader: | ||
/* glsl */ | ||
` | ||
vertexShader: /* glsl */` | ||
attribute vec3 control0; | ||
@@ -92,5 +88,3 @@ attribute vec3 control1; | ||
`, | ||
fragmentShader: | ||
/* glsl */ | ||
` | ||
fragmentShader: /* glsl */` | ||
uniform vec3 diffuse; | ||
@@ -150,3 +144,2 @@ uniform float opacity; | ||
} | ||
class ConditionalLineSegments extends THREE.LineSegments { | ||
@@ -162,3 +155,2 @@ | ||
} | ||
function generateFaceNormals( faces ) { | ||
@@ -173,7 +165,4 @@ | ||
const v2 = vertices[ 2 ]; | ||
_tempVec0.subVectors( v1, v0 ); | ||
_tempVec1.subVectors( v2, v1 ); | ||
face.faceNormal = new THREE.Vector3().crossVectors( _tempVec0, _tempVec1 ).normalize(); | ||
@@ -186,3 +175,2 @@ | ||
const _ray = new THREE.Ray(); | ||
function smoothNormals( faces, lineSegments, checkSubSegments = false ) { | ||
@@ -198,4 +186,4 @@ | ||
// value for the sake of hashing. See "AT-ST mini" dishes. See mrdoob/three#23169. | ||
const hashMultiplier = ( 1 + 1e-10 ) * 1e2; | ||
function hashVertex( v ) { | ||
@@ -214,6 +202,6 @@ | ||
} // converts the two vertices to a ray with a normalized direction and origin of 0, 0, 0 projected | ||
} | ||
// converts the two vertices to a ray with a normalized direction and origin of 0, 0, 0 projected | ||
// onto the original line. | ||
function toNormalizedRay( v0, v1, targetRay ) { | ||
@@ -237,4 +225,5 @@ | ||
const halfEdgeList = {}; | ||
const normals = []; // Save the list of hard edges by hash | ||
const normals = []; | ||
// Save the list of hard edges by hash | ||
for ( let i = 0, l = lineSegments.length; i < l; i ++ ) { | ||
@@ -247,5 +236,6 @@ | ||
hardEdges.add( hashEdge( v0, v1 ) ); | ||
hardEdges.add( hashEdge( v1, v0 ) ); // only generate the hard edge ray map if we're checking subsegments because it's more expensive to check | ||
hardEdges.add( hashEdge( v1, v0 ) ); | ||
// only generate the hard edge ray map if we're checking subsegments because it's more expensive to check | ||
// and requires more memory. | ||
if ( checkSubSegments ) { | ||
@@ -256,3 +246,2 @@ | ||
const rh1 = hashRay( ray ); | ||
if ( ! hardEdgeRays.has( rh1 ) ) { | ||
@@ -269,10 +258,9 @@ | ||
} // store both segments ends in min, max order in the distances array to check if a face edge is a | ||
} | ||
// store both segments ends in min, max order in the distances array to check if a face edge is a | ||
// subsegment later. | ||
const info = hardEdgeRays.get( rh1 ); | ||
let d0 = info.ray.direction.dot( v0 ); | ||
let d1 = info.ray.direction.dot( v1 ); | ||
if ( d0 > d1 ) { | ||
@@ -288,5 +276,5 @@ | ||
} // track the half edges associated with each triangle | ||
} | ||
// track the half edges associated with each triangle | ||
for ( let i = 0, l = faces.length; i < l; i ++ ) { | ||
@@ -297,3 +285,2 @@ | ||
const vertCount = vertices.length; | ||
for ( let i2 = 0; i2 < vertCount; i2 ++ ) { | ||
@@ -305,4 +292,5 @@ | ||
const v1 = vertices[ next ]; | ||
const hash = hashEdge( v0, v1 ); // don't add the triangle if the edge is supposed to be hard | ||
const hash = hashEdge( v0, v1 ); | ||
// don't add the triangle if the edge is supposed to be hard | ||
if ( hardEdges.has( hash ) ) { | ||
@@ -312,5 +300,5 @@ | ||
} // if checking subsegments then check to see if this edge lies on a hard edge ray and whether its within any ray bounds | ||
} | ||
// if checking subsegments then check to see if this edge lies on a hard edge ray and whether its within any ray bounds | ||
if ( checkSubSegments ) { | ||
@@ -320,3 +308,2 @@ | ||
const rayHash = hashRay( _ray ); | ||
if ( hardEdgeRays.has( rayHash ) ) { | ||
@@ -331,3 +318,2 @@ | ||
let d1 = ray.direction.dot( v1 ); | ||
if ( d0 > d1 ) { | ||
@@ -337,7 +323,6 @@ | ||
} // return early if the face edge is found to be a subsegment of a line edge meaning the edge will have "hard" normals | ||
} | ||
// return early if the face edge is found to be a subsegment of a line edge meaning the edge will have "hard" normals | ||
let found = false; | ||
for ( let i = 0, l = distances.length; i < l; i += 2 ) { | ||
@@ -372,5 +357,5 @@ | ||
} // Iterate until we've tried to connect all faces to share normals | ||
} | ||
// Iterate until we've tried to connect all faces to share normals | ||
while ( true ) { | ||
@@ -380,3 +365,2 @@ | ||
let halfEdge = null; | ||
for ( const key in halfEdgeList ) { | ||
@@ -393,7 +377,6 @@ | ||
} // Exhaustively find all connected faces | ||
} | ||
// Exhaustively find all connected faces | ||
const queue = [ halfEdge ]; | ||
while ( queue.length > 0 ) { | ||
@@ -405,6 +388,6 @@ | ||
const vertNormals = tri.normals; | ||
const faceNormal = tri.faceNormal; // Check if any edge is connected to another triangle edge | ||
const faceNormal = tri.faceNormal; | ||
// Check if any edge is connected to another triangle edge | ||
const vertCount = vertices.length; | ||
for ( let i2 = 0; i2 < vertCount; i2 ++ ) { | ||
@@ -415,4 +398,5 @@ | ||
const v0 = vertices[ index ]; | ||
const v1 = vertices[ next ]; // delete this triangle from the list so it won't be found again | ||
const v1 = vertices[ next ]; | ||
// delete this triangle from the list so it won't be found again | ||
const hash = hashEdge( v0, v1 ); | ||
@@ -422,3 +406,2 @@ delete halfEdgeList[ hash ]; | ||
const otherInfo = halfEdgeList[ reverseHash ]; | ||
if ( otherInfo ) { | ||
@@ -430,6 +413,7 @@ | ||
const otherVertCount = otherNormals.length; | ||
const otherFaceNormal = otherTri.faceNormal; // NOTE: If the angle between faces is > 67.5 degrees then assume it's | ||
const otherFaceNormal = otherTri.faceNormal; | ||
// NOTE: If the angle between faces is > 67.5 degrees then assume it's | ||
// hard edge. There are some cases where the line segments do not line up exactly | ||
// with or span multiple triangle edges (see Lunar Vehicle wheels). | ||
if ( Math.abs( otherTri.faceNormal.dot( tri.faceNormal ) ) < 0.25 ) { | ||
@@ -439,7 +423,7 @@ | ||
} // if this triangle has already been traversed then it won't be in | ||
} | ||
// if this triangle has already been traversed then it won't be in | ||
// the halfEdgeList. If it has not then add it to the queue and delete | ||
// it so it won't be found again. | ||
if ( reverseHash in halfEdgeList ) { | ||
@@ -450,7 +434,6 @@ | ||
} // share the first normal | ||
} | ||
// share the first normal | ||
const otherNext = ( otherIndex + 1 ) % otherVertCount; | ||
if ( vertNormals[ index ] && otherNormals[ otherNext ] && vertNormals[ index ] !== otherNormals[ otherNext ] ) { | ||
@@ -464,3 +447,2 @@ | ||
let sharedNormal1 = vertNormals[ index ] || otherNormals[ otherNext ]; | ||
if ( sharedNormal1 === null ) { | ||
@@ -490,5 +472,5 @@ | ||
} // share the second normal | ||
} | ||
// share the second normal | ||
if ( vertNormals[ next ] && otherNormals[ otherIndex ] && vertNormals[ next ] !== otherNormals[ otherIndex ] ) { | ||
@@ -502,3 +484,2 @@ | ||
let sharedNormal2 = vertNormals[ next ] || otherNormals[ otherIndex ]; | ||
if ( sharedNormal2 === null ) { | ||
@@ -533,5 +514,5 @@ | ||
} // The normals of each face have been added up so now we average them by normalizing the vector. | ||
} | ||
// The normals of each face have been added up so now we average them by normalizing the vector. | ||
for ( let i = 0, l = normals.length; i < l; i ++ ) { | ||
@@ -568,3 +549,2 @@ | ||
} | ||
seekNonSpace() { | ||
@@ -575,3 +555,2 @@ | ||
this.currentChar = this.line.charAt( this.currentCharIndex ); | ||
if ( this.currentChar !== ' ' && this.currentChar !== '\t' ) { | ||
@@ -588,11 +567,10 @@ | ||
} | ||
getToken() { | ||
const pos0 = this.currentCharIndex ++; // Seek space | ||
const pos0 = this.currentCharIndex ++; | ||
// Seek space | ||
while ( this.currentCharIndex < this.lineLength ) { | ||
this.currentChar = this.line.charAt( this.currentCharIndex ); | ||
if ( this.currentChar === ' ' || this.currentChar === '\t' ) { | ||
@@ -613,3 +591,2 @@ | ||
} | ||
getVector() { | ||
@@ -620,3 +597,2 @@ | ||
} | ||
getRemainingString() { | ||
@@ -627,3 +603,2 @@ | ||
} | ||
isAtTheEnd() { | ||
@@ -634,3 +609,2 @@ | ||
} | ||
setToEnd() { | ||
@@ -641,3 +615,2 @@ | ||
} | ||
getLineNumberString() { | ||
@@ -649,5 +622,5 @@ | ||
} // Fetches and parses an intermediate representation of LDraw parts files. | ||
} | ||
// Fetches and parses an intermediate representation of LDraw parts files. | ||
class LDrawParsedCache { | ||
@@ -661,8 +634,8 @@ | ||
} | ||
cloneResult( original ) { | ||
const result = {}; // vertices are transformed and normals computed before being converted to geometry | ||
const result = {}; | ||
// vertices are transformed and normals computed before being converted to geometry | ||
// so these pieces must be cloned. | ||
result.faces = original.faces.map( face => { | ||
@@ -697,4 +670,5 @@ | ||
} ); // none if this is subsequently modified | ||
} ); | ||
// none if this is subsequently modified | ||
result.type = original.type; | ||
@@ -713,3 +687,2 @@ result.category = original.category; | ||
} | ||
async fetchData( fileName ) { | ||
@@ -719,7 +692,5 @@ | ||
let locationState = FILE_LOCATION_TRY_PARTS; | ||
while ( locationState !== FILE_LOCATION_NOT_FOUND ) { | ||
let subobjectURL = fileName; | ||
switch ( locationState ) { | ||
@@ -730,3 +701,2 @@ | ||
break; | ||
case FILE_LOCATION_TRY_PARTS: | ||
@@ -736,3 +706,2 @@ subobjectURL = 'parts/' + subobjectURL; | ||
break; | ||
case FILE_LOCATION_TRY_P: | ||
@@ -742,3 +711,2 @@ subobjectURL = 'p/' + subobjectURL; | ||
break; | ||
case FILE_LOCATION_TRY_MODELS: | ||
@@ -748,3 +716,2 @@ subobjectURL = 'models/' + subobjectURL; | ||
break; | ||
case FILE_LOCATION_TRY_RELATIVE: | ||
@@ -754,3 +721,2 @@ subobjectURL = fileName.substring( 0, fileName.lastIndexOf( '/' ) + 1 ) + subobjectURL; | ||
break; | ||
case FILE_LOCATION_TRY_ABSOLUTE: | ||
@@ -781,3 +747,2 @@ if ( triedLowerCase ) { | ||
fileLoader.setWithCredentials( loader.withCredentials ); | ||
try { | ||
@@ -799,7 +764,7 @@ | ||
} | ||
parse( text, fileName = null ) { | ||
const loader = this.loader; // final results | ||
const loader = this.loader; | ||
// final results | ||
const faces = []; | ||
@@ -810,3 +775,2 @@ const lineSegments = []; | ||
const materials = {}; | ||
const getLocalMaterial = colorCode => { | ||
@@ -822,4 +786,5 @@ | ||
let author = null; | ||
let totalFaces = 0; // split into lines | ||
let totalFaces = 0; | ||
// split into lines | ||
if ( text.indexOf( '\r\n' ) !== - 1 ) { | ||
@@ -841,4 +806,5 @@ | ||
let bfcCull = true; | ||
let startingConstructionStep = false; // Parse all line commands | ||
let startingConstructionStep = false; | ||
// Parse all line commands | ||
for ( let lineIndex = 0; lineIndex < numLines; lineIndex ++ ) { | ||
@@ -848,3 +814,2 @@ | ||
if ( line.length === 0 ) continue; | ||
if ( parsingEmbeddedFiles ) { | ||
@@ -855,4 +820,5 @@ | ||
// Save previous embedded file in the cache | ||
this.setData( currentEmbeddedFileName, currentEmbeddedText ); // New embedded text file | ||
this.setData( currentEmbeddedFileName, currentEmbeddedText ); | ||
// New embedded text file | ||
currentEmbeddedFileName = line.substring( 7 ); | ||
@@ -873,3 +839,2 @@ currentEmbeddedText = ''; | ||
lp.seekNonSpace(); | ||
if ( lp.isAtTheEnd() ) { | ||
@@ -880,5 +845,5 @@ | ||
} // Parse the line type | ||
} | ||
// Parse the line type | ||
const lineType = lp.getToken(); | ||
@@ -891,3 +856,2 @@ let material; | ||
let v0, v1, v2, v3, c0, c1; | ||
switch ( lineType ) { | ||
@@ -899,3 +863,2 @@ | ||
const meta = lp.getToken(); | ||
if ( meta ) { | ||
@@ -908,6 +871,4 @@ | ||
break; | ||
case '!COLOUR': | ||
material = loader.parseColorMetaDirective( lp ); | ||
if ( material ) { | ||
@@ -924,10 +885,7 @@ | ||
break; | ||
case '!CATEGORY': | ||
category = lp.getToken(); | ||
break; | ||
case '!KEYWORDS': | ||
const newKeywords = lp.getRemainingString().split( ',' ); | ||
if ( newKeywords.length > 0 ) { | ||
@@ -950,3 +908,2 @@ | ||
break; | ||
case 'FILE': | ||
@@ -965,3 +922,2 @@ if ( lineIndex > 0 ) { | ||
break; | ||
case 'BFC': | ||
@@ -972,3 +928,2 @@ // Changes to the backface culling state | ||
const token = lp.getToken(); | ||
switch ( token ) { | ||
@@ -981,3 +936,2 @@ | ||
break; | ||
case 'CW': | ||
@@ -987,7 +941,5 @@ case 'CCW': | ||
break; | ||
case 'INVERTNEXT': | ||
bfcInverted = true; | ||
break; | ||
case 'CLIP': | ||
@@ -997,3 +949,2 @@ case 'NOCLIP': | ||
break; | ||
default: | ||
@@ -1008,11 +959,8 @@ console.warn( 'THREE.LDrawLoader: BFC directive "' + token + '" is unknown.' ); | ||
break; | ||
case 'STEP': | ||
startingConstructionStep = true; | ||
break; | ||
case 'Author:': | ||
author = lp.getToken(); | ||
break; | ||
default: | ||
@@ -1027,4 +975,4 @@ // Other meta directives are not implemented | ||
break; | ||
// Line type 1: Sub-object file | ||
case '1': | ||
@@ -1047,3 +995,2 @@ colorCode = lp.getToken(); | ||
let fileName = lp.getRemainingString().trim().replace( /\\/g, '/' ); | ||
if ( loader.fileMap[ fileName ] ) { | ||
@@ -1079,4 +1026,4 @@ | ||
break; | ||
// Line type 2: Line segment | ||
case '2': | ||
@@ -1094,4 +1041,4 @@ colorCode = lp.getToken(); | ||
break; | ||
// Line type 5: Conditional Line segment | ||
case '5': | ||
@@ -1112,4 +1059,4 @@ colorCode = lp.getToken(); | ||
break; | ||
// Line type 3: Triangle | ||
case '3': | ||
@@ -1120,3 +1067,2 @@ colorCode = lp.getToken(); | ||
doubleSided = ! bfcCertified || ! bfcCull; | ||
if ( ccw === true ) { | ||
@@ -1144,3 +1090,2 @@ | ||
totalFaces ++; | ||
if ( doubleSided === true ) { | ||
@@ -1160,4 +1105,4 @@ | ||
break; | ||
// Line type 4: Quadrilateral | ||
case '4': | ||
@@ -1168,3 +1113,2 @@ colorCode = lp.getToken(); | ||
doubleSided = ! bfcCertified || ! bfcCull; | ||
if ( ccw === true ) { | ||
@@ -1184,6 +1128,6 @@ | ||
} // specifically place the triangle diagonal in the v0 and v1 slots so we can | ||
} | ||
// specifically place the triangle diagonal in the v0 and v1 slots so we can | ||
// account for the doubling of vertices later when smoothing normals. | ||
faces.push( { | ||
@@ -1197,3 +1141,2 @@ material: material, | ||
totalFaces += 2; | ||
if ( doubleSided === true ) { | ||
@@ -1213,3 +1156,2 @@ | ||
break; | ||
default: | ||
@@ -1244,5 +1186,5 @@ throw new Error( 'LDrawLoader: Unknown line type "' + lineType + '"' + lp.getLineNumberString() + '.' ); | ||
} // returns an (optionally cloned) instance of the data | ||
} | ||
// returns an (optionally cloned) instance of the data | ||
getData( fileName, clone = true ) { | ||
@@ -1252,3 +1194,2 @@ | ||
const result = this._cache[ key ]; | ||
if ( result === null || result instanceof Promise ) { | ||
@@ -1270,10 +1211,9 @@ | ||
} // kicks off a fetch and parse of the requested data if it hasn't already been loaded. Returns when | ||
} | ||
// kicks off a fetch and parse of the requested data if it hasn't already been loaded. Returns when | ||
// the data is ready to use and can be retrieved synchronously with "getData". | ||
async ensureDataLoaded( fileName ) { | ||
const key = fileName.toLowerCase(); | ||
if ( ! ( key in this._cache ) ) { | ||
@@ -1294,5 +1234,5 @@ | ||
} // sets the data in the cache from parsed data | ||
} | ||
// sets the data in the cache from parsed data | ||
setData( fileName, text ) { | ||
@@ -1305,10 +1245,9 @@ | ||
} // returns the material for an associated color code. If the color code is 16 for a face or 24 for | ||
} | ||
// returns the material for an associated color code. If the color code is 16 for a face or 24 for | ||
// an edge then the passthroughColorCode is used. | ||
function getMaterialFromCode( colorCode, parentColorCode, materialHierarchy, forEdge ) { | ||
const isPassthrough = ! forEdge && colorCode === MAIN_COLOUR_CODE || forEdge && colorCode === MAIN_EDGE_COLOUR_CODE; | ||
if ( isPassthrough ) { | ||
@@ -1322,5 +1261,5 @@ | ||
} // Class used to parse and build LDraw parts as three.js objects and cache them if they're a "Part" type. | ||
} | ||
// Class used to parse and build LDraw parts as three.js objects and cache them if they're a "Part" type. | ||
class LDrawPartsGeometryCache { | ||
@@ -1334,5 +1273,5 @@ | ||
} // Convert the given file information into a mesh by processing subobjects. | ||
} | ||
// Convert the given file information into a mesh by processing subobjects. | ||
async processIntoMesh( info ) { | ||
@@ -1342,11 +1281,13 @@ | ||
const parseCache = this.parseCache; | ||
const faceMaterials = new Set(); // Processes the part subobject information to load child parts and merge geometry onto part | ||
const faceMaterials = new Set(); | ||
// Processes the part subobject information to load child parts and merge geometry onto part | ||
// piece object. | ||
const processInfoSubobjects = async ( info, subobject = null ) => { | ||
const subobjects = info.subobjects; | ||
const promises = []; // Trigger load of all subobjects. If a subobject isn't a primitive then load it as a separate | ||
const promises = []; | ||
// Trigger load of all subobjects. If a subobject isn't a primitive then load it as a separate | ||
// group which lets instruction steps apply correctly. | ||
for ( let i = 0, l = subobjects.length; i < l; i ++ ) { | ||
@@ -1358,3 +1299,2 @@ | ||
const subobjectInfo = parseCache.getData( subobject.fileName, false ); | ||
if ( ! isPrimitiveType( subobjectInfo.type ) ) { | ||
@@ -1386,3 +1326,2 @@ | ||
const subobjectInfos = await Promise.all( promises ); | ||
for ( let i = 0, l = subobjectInfos.length; i < l; i ++ ) { | ||
@@ -1392,3 +1331,2 @@ | ||
const subobjectInfo = subobjectInfos[ i ]; | ||
if ( subobjectInfo === null ) { | ||
@@ -1399,5 +1337,5 @@ | ||
} // if the subobject was loaded as a separate group then apply the parent scopes materials | ||
} | ||
// if the subobject was loaded as a separate group then apply the parent scopes materials | ||
if ( subobjectInfo.isGroup ) { | ||
@@ -1414,5 +1352,5 @@ | ||
} // add the subobject group if it has children in case it has both children and primitives | ||
} | ||
// add the subobject group if it has children in case it has both children and primitives | ||
if ( subobjectInfo.group.children.length ) { | ||
@@ -1422,6 +1360,6 @@ | ||
} // transform the primitives into the local space of the parent piece and append them to | ||
} | ||
// transform the primitives into the local space of the parent piece and append them to | ||
// to the parent primitives list. | ||
const parentLineSegments = info.lineSegments; | ||
@@ -1438,3 +1376,2 @@ const parentConditionalSegments = info.conditionalSegments; | ||
const lineColorCode = colorCode === MAIN_COLOUR_CODE ? MAIN_EDGE_COLOUR_CODE : colorCode; | ||
for ( let i = 0, l = lineSegments.length; i < l; i ++ ) { | ||
@@ -1471,3 +1408,2 @@ | ||
const vertices = tri.vertices; | ||
for ( let i = 0, l = vertices.length; i < l; i ++ ) { | ||
@@ -1481,5 +1417,6 @@ | ||
tri.material = tri.material || getMaterialFromCode( tri.colorCode, colorCode, info.materials, false ); | ||
faceMaterials.add( tri.colorCode ); // If the scale of the object is negated then the triangle winding order | ||
faceMaterials.add( tri.colorCode ); | ||
// If the scale of the object is negated then the triangle winding order | ||
// needs to be flipped. | ||
if ( matrixScaleInverted !== inverted ) { | ||
@@ -1497,6 +1434,6 @@ | ||
} // Apply the parent subobjects pass through material code to this object. This is done several times due | ||
} | ||
// Apply the parent subobjects pass through material code to this object. This is done several times due | ||
// to material scoping. | ||
if ( subobject ) { | ||
@@ -1511,5 +1448,5 @@ | ||
}; // Track material use to see if we need to use the normal smooth slow path for hard edges. | ||
}; | ||
// Track material use to see if we need to use the normal smooth slow path for hard edges. | ||
for ( let i = 0, l = info.faces; i < l; i ++ ) { | ||
@@ -1522,3 +1459,2 @@ | ||
await processInfoSubobjects( info ); | ||
if ( loader.smoothNormals ) { | ||
@@ -1530,7 +1466,6 @@ | ||
} // Add the primitive objects and metadata. | ||
} | ||
// Add the primitive objects and metadata. | ||
const group = info.group; | ||
if ( info.faces.length > 0 ) { | ||
@@ -1557,3 +1492,2 @@ | ||
} | ||
hasCachedModel( fileName ) { | ||
@@ -1564,3 +1498,2 @@ | ||
} | ||
async getCachedModel( fileName ) { | ||
@@ -1580,5 +1513,5 @@ | ||
} // Loads and parses the model with the given file name. Returns a cached copy if available. | ||
} | ||
// Loads and parses the model with the given file name. Returns a cached copy if available. | ||
async loadModel( fileName ) { | ||
@@ -1588,3 +1521,2 @@ | ||
const key = fileName.toLowerCase(); | ||
if ( this.hasCachedModel( fileName ) ) { | ||
@@ -1601,6 +1533,7 @@ | ||
const info = parseCache.getData( fileName ); | ||
const promise = this.processIntoMesh( info ); // Now that the file has loaded it's possible that another part parse has been waiting in parallel | ||
const promise = this.processIntoMesh( info ); | ||
// Now that the file has loaded it's possible that another part parse has been waiting in parallel | ||
// so check the cache again to see if it's been added since the last async operation so we don't | ||
// do unnecessary work. | ||
if ( this.hasCachedModel( fileName ) ) { | ||
@@ -1610,5 +1543,5 @@ | ||
} // Cache object if it's a part so it can be reused later. | ||
} | ||
// Cache object if it's a part so it can be reused later. | ||
if ( isPartType( info.type ) ) { | ||
@@ -1618,5 +1551,5 @@ | ||
} // return a copy | ||
} | ||
// return a copy | ||
const group = await promise; | ||
@@ -1627,5 +1560,5 @@ return group.clone(); | ||
} // parses the given model text into a renderable object. Returns cached copy if available. | ||
} | ||
// parses the given model text into a renderable object. Returns cached copy if available. | ||
async parseModel( text ) { | ||
@@ -1635,3 +1568,2 @@ | ||
const info = parseCache.parse( text ); | ||
if ( isPartType( info.type ) && this.hasCachedModel( info.fileName ) ) { | ||
@@ -1648,3 +1580,2 @@ | ||
} | ||
function sortByMaterial( a, b ) { | ||
@@ -1672,5 +1603,5 @@ | ||
// With per face / segment material, implemented with mesh groups and materials array | ||
// Sort the faces or line segments by color code to make later the mesh groups | ||
elements.sort( sortByMaterial ); | ||
if ( totalElements === null ) { | ||
@@ -1691,3 +1622,2 @@ | ||
let offset = 0; | ||
for ( let iElem = 0, nElem = elements.length; iElem < nElem; iElem ++ ) { | ||
@@ -1697,3 +1627,2 @@ | ||
let vertices = elem.vertices; | ||
if ( vertices.length === 4 ) { | ||
@@ -1719,5 +1648,5 @@ | ||
} // create the normals array if this is a set of faces | ||
} | ||
// create the normals array if this is a set of faces | ||
if ( elementSize === 3 ) { | ||
@@ -1730,7 +1659,4 @@ | ||
const v2 = vertices[ 2 ]; | ||
_tempVec0.subVectors( v1, v0 ); | ||
_tempVec1.subVectors( v2, v1 ); | ||
elem.faceNormal = new THREE.Vector3().crossVectors( _tempVec0, _tempVec1 ).normalize(); | ||
@@ -1741,3 +1667,2 @@ | ||
let elemNormals = elem.normals; | ||
if ( elemNormals.length === 4 ) { | ||
@@ -1759,3 +1684,2 @@ | ||
let n = elem.faceNormal; | ||
if ( elemNormals[ j ] ) { | ||
@@ -1785,3 +1709,2 @@ | ||
const material = elem.material; | ||
if ( material !== null ) { | ||
@@ -1836,3 +1759,2 @@ | ||
bufferGeometry.setAttribute( 'position', new THREE.BufferAttribute( positions, 3 ) ); | ||
if ( normals !== null ) { | ||
@@ -1845,3 +1767,2 @@ | ||
let object3d = null; | ||
if ( elementSize === 2 ) { | ||
@@ -1871,3 +1792,2 @@ | ||
const directionArray = new Float32Array( elements.length * 3 * 2 ); | ||
for ( let i = 0, l = elements.length; i < l; i ++ ) { | ||
@@ -1912,4 +1832,5 @@ | ||
} // | ||
} | ||
// | ||
@@ -1920,17 +1841,24 @@ class LDrawLoader extends THREE.Loader { | ||
super( manager ); // Array of THREE.Material | ||
super( manager ); | ||
// Array of THREE.Material | ||
this.materials = []; | ||
this.materialLibrary = {}; // This also allows to handle the embedded text files ("0 FILE" lines) | ||
this.materialLibrary = {}; | ||
this.partsCache = new LDrawPartsGeometryCache( this ); // This object is a map from file names to paths. It agilizes the paths search. If it is not set then files will be searched by trial and error. | ||
// This also allows to handle the embedded text files ("0 FILE" lines) | ||
this.partsCache = new LDrawPartsGeometryCache( this ); | ||
this.fileMap = {}; // Initializes the materials library with default materials | ||
// This object is a map from file names to paths. It agilizes the paths search. If it is not set then files will be searched by trial and error. | ||
this.fileMap = {}; | ||
this.setMaterials( [] ); // If this flag is set to true the vertex normals will be smoothed. | ||
// Initializes the materials library with default materials | ||
this.setMaterials( [] ); | ||
this.smoothNormals = true; // The path to load parts from the LDraw parts library from. | ||
// If this flag is set to true the vertex normals will be smoothed. | ||
this.smoothNormals = true; | ||
this.partsLibraryPath = ''; // Material assigned to not available colors for meshes and edges | ||
// The path to load parts from the LDraw parts library from. | ||
this.partsLibraryPath = ''; | ||
// Material assigned to not available colors for meshes and edges | ||
this.missingColorMaterial = new THREE.MeshStandardMaterial( { | ||
@@ -1955,3 +1883,2 @@ color: 0xFF00FF, | ||
} | ||
setPartsLibraryPath( path ) { | ||
@@ -1963,3 +1890,2 @@ | ||
} | ||
async preloadMaterials( url ) { | ||
@@ -1975,7 +1901,5 @@ | ||
const materials = []; | ||
for ( let i = 0, l = lines.length; i < l; i ++ ) { | ||
const line = lines[ i ]; | ||
if ( colorLineRegex.test( line ) ) { | ||
@@ -1994,3 +1918,2 @@ | ||
} | ||
load( url, onLoad, onProgress, onError ) { | ||
@@ -2016,3 +1939,2 @@ | ||
} | ||
parse( text, onLoad ) { | ||
@@ -2030,3 +1952,2 @@ | ||
} | ||
setMaterials( materials ) { | ||
@@ -2036,3 +1957,2 @@ | ||
this.materials = []; | ||
for ( let i = 0, l = materials.length; i < l; i ++ ) { | ||
@@ -2042,5 +1962,5 @@ | ||
} // Add default main triangle and line edge materials (used in pieces that can be colored with a main color) | ||
} | ||
// Add default main triangle and line edge materials (used in pieces that can be colored with a main color) | ||
this.addMaterial( this.parseColorMetaDirective( new LineParser( 'Main_Colour CODE 16 VALUE #FF8080 EDGE #333333' ) ) ); | ||
@@ -2051,3 +1971,2 @@ this.addMaterial( this.parseColorMetaDirective( new LineParser( 'Edge_Colour CODE 24 VALUE #A0A0A0 EDGE #333333' ) ) ); | ||
} | ||
setFileMap( fileMap ) { | ||
@@ -2059,8 +1978,7 @@ | ||
} | ||
addMaterial( material ) { | ||
// Adds a material to the material library which is on top of the parse scopes stack. And also to the materials array | ||
const matLib = this.materialLibrary; | ||
if ( ! matLib[ material.userData.code ] ) { | ||
@@ -2076,3 +1994,2 @@ | ||
} | ||
getMaterial( colorCode ) { | ||
@@ -2090,6 +2007,6 @@ | ||
} // Applies the appropriate materials to a prebuilt hierarchy of geometry. Assumes that color codes are present | ||
} | ||
// Applies the appropriate materials to a prebuilt hierarchy of geometry. Assumes that color codes are present | ||
// in the material array if they need to be filled in. | ||
applyMaterialsToMesh( group, parentColorCode, materialHierarchy, finalMaterialPass = false ) { | ||
@@ -2124,6 +2041,7 @@ | ||
} ); // Returns the appropriate material for the object (line or face) given color code. If the code is "pass through" | ||
} ); | ||
// Returns the appropriate material for the object (line or face) given color code. If the code is "pass through" | ||
// (24 for lines, 16 for edges) then the pass through color code is used. If that is also pass through then it's | ||
// simply returned for the subsequent material application. | ||
function getMaterial( c, colorCode ) { | ||
@@ -2141,3 +2059,2 @@ | ||
const isPassthrough = ! forEdge && colorCode === MAIN_COLOUR_CODE || forEdge && colorCode === MAIN_EDGE_COLOUR_CODE; | ||
if ( isPassthrough ) { | ||
@@ -2150,3 +2067,2 @@ | ||
let material = null; | ||
if ( colorCode in materialHierarchy ) { | ||
@@ -2161,8 +2077,8 @@ | ||
material = loader.getMaterial( colorCode ); | ||
if ( material === null ) { | ||
// otherwise throw a warning if this is final opportunity to set the material | ||
console.warn( `LDrawLoader: Material properties for code ${colorCode} not available.` ); // And return the 'missing color' material | ||
console.warn( `LDrawLoader: Material properties for code ${colorCode} not available.` ); | ||
// And return the 'missing color' material | ||
material = loader.missingColorMaterial; | ||
@@ -2181,3 +2097,2 @@ | ||
material = material.userData.edgeMaterial; | ||
if ( c.isConditionalLine ) { | ||
@@ -2196,3 +2111,2 @@ | ||
} | ||
getMainMaterial() { | ||
@@ -2203,3 +2117,2 @@ | ||
} | ||
getMainEdgeMaterial() { | ||
@@ -2211,14 +2124,16 @@ | ||
} | ||
parseColorMetaDirective( lineParser ) { | ||
// Parses a color definition and returns a THREE.Material | ||
let code = null; // Triangle and line colors | ||
let code = null; | ||
// Triangle and line colors | ||
let color = 0xFF00FF; | ||
let edgeColor = 0xFF00FF; // Transparency | ||
let edgeColor = 0xFF00FF; | ||
// Transparency | ||
let alpha = 1; | ||
let isTransparent = false; // Self-illumination: | ||
let isTransparent = false; | ||
// Self-illumination: | ||
let luminance = 0; | ||
@@ -2228,3 +2143,2 @@ let finishType = FINISH_TYPE_DEFAULT; | ||
const name = lineParser.getToken(); | ||
if ( ! name ) { | ||
@@ -2234,11 +2148,9 @@ | ||
} // Parse tag tokens and their parameters | ||
} | ||
// Parse tag tokens and their parameters | ||
let token = null; | ||
while ( true ) { | ||
token = lineParser.getToken(); | ||
if ( ! token ) { | ||
@@ -2257,6 +2169,4 @@ | ||
break; | ||
case 'VALUE': | ||
color = lineParser.getToken(); | ||
if ( color.startsWith( '0x' ) ) { | ||
@@ -2273,6 +2183,4 @@ | ||
break; | ||
case 'EDGE': | ||
edgeColor = lineParser.getToken(); | ||
if ( edgeColor.startsWith( '0x' ) ) { | ||
@@ -2286,3 +2194,2 @@ | ||
edgeMaterial = this.getMaterial( edgeColor ); | ||
if ( ! edgeMaterial ) { | ||
@@ -2292,5 +2199,5 @@ | ||
} // Get the edge material for this triangle material | ||
} | ||
// Get the edge material for this triangle material | ||
edgeMaterial = edgeMaterial.userData.edgeMaterial; | ||
@@ -2301,6 +2208,4 @@ | ||
break; | ||
case 'ALPHA': | ||
alpha = parseInt( lineParser.getToken() ); | ||
if ( isNaN( alpha ) ) { | ||
@@ -2313,3 +2218,2 @@ | ||
alpha = Math.max( 0, Math.min( 1, alpha / 255 ) ); | ||
if ( alpha < 1 ) { | ||
@@ -2322,3 +2226,2 @@ | ||
break; | ||
case 'LUMINANCE': | ||
@@ -2332,23 +2235,17 @@ if ( ! parseLuminance( lineParser.getToken() ) ) { | ||
break; | ||
case 'CHROME': | ||
finishType = FINISH_TYPE_CHROME; | ||
break; | ||
case 'PEARLESCENT': | ||
finishType = FINISH_TYPE_PEARLESCENT; | ||
break; | ||
case 'RUBBER': | ||
finishType = FINISH_TYPE_RUBBER; | ||
break; | ||
case 'MATTE_METALLIC': | ||
finishType = FINISH_TYPE_MATTE_METALLIC; | ||
break; | ||
case 'METAL': | ||
finishType = FINISH_TYPE_METAL; | ||
break; | ||
case 'MATERIAL': | ||
@@ -2358,3 +2255,2 @@ // Not implemented | ||
break; | ||
default: | ||
@@ -2370,3 +2266,2 @@ throw new Error( 'LDrawLoader: Unknown token "' + token + '" while parsing material' + lineParser.getLineNumberString() + '.' ); | ||
let material = null; | ||
switch ( finishType ) { | ||
@@ -2381,3 +2276,2 @@ | ||
break; | ||
case FINISH_TYPE_PEARLESCENT: | ||
@@ -2391,3 +2285,2 @@ // Try to imitate pearlescency by making the surface glossy | ||
break; | ||
case FINISH_TYPE_CHROME: | ||
@@ -2401,3 +2294,2 @@ // Mirror finish surface | ||
break; | ||
case FINISH_TYPE_RUBBER: | ||
@@ -2411,3 +2303,2 @@ // Rubber finish | ||
break; | ||
case FINISH_TYPE_MATTE_METALLIC: | ||
@@ -2421,3 +2312,2 @@ // Brushed metal finish | ||
break; | ||
case FINISH_TYPE_METAL: | ||
@@ -2431,3 +2321,2 @@ // Average metal finish | ||
break; | ||
default: | ||
@@ -2446,3 +2335,2 @@ // Should not happen | ||
material.polygonOffsetFactor = 1; | ||
if ( luminance !== 0 ) { | ||
@@ -2465,4 +2353,5 @@ | ||
edgeMaterial.name = name + ' - Edge'; | ||
edgeMaterial.color.convertSRGBToLinear(); // This is the material used for conditional edges | ||
edgeMaterial.color.convertSRGBToLinear(); | ||
// This is the material used for conditional edges | ||
edgeMaterial.userData.conditionalEdgeMaterial = new LDrawConditionalLineMaterial( { | ||
@@ -2486,8 +2375,7 @@ fog: true, | ||
return material; | ||
function parseLuminance( token ) { | ||
// Returns success | ||
let lum; | ||
if ( token.startsWith( 'LUMINANCE' ) ) { | ||
@@ -2515,6 +2403,6 @@ | ||
} | ||
computeConstructionSteps( model ) { | ||
// Sets userdata.constructionStep number in THREE.Group objects and userData.numConstructionSteps number in the root THREE.Group object. | ||
let stepNumber = 0; | ||
@@ -2521,0 +2409,0 @@ model.traverse( c => { |
@@ -11,3 +11,2 @@ ( function () { | ||
} | ||
parse( buffer ) { | ||
@@ -28,3 +27,2 @@ | ||
} | ||
setDataType( value ) { | ||
@@ -37,7 +35,7 @@ | ||
} // from https://github.com/photopea/UTIF.js (MIT License) | ||
} | ||
// from https://github.com/photopea/UTIF.js (MIT License) | ||
const UTIF = {}; | ||
UTIF.decode = function ( buff, prm ) { | ||
@@ -49,8 +47,5 @@ | ||
}; // read MakerNote, debug | ||
var data = new Uint8Array( buff ), | ||
offset = 0; | ||
var id = UTIF._binBE.readASCII( data, offset, 2 ); | ||
offset += 2; | ||
@@ -62,3 +57,2 @@ var bin = id == 'II' ? UTIF._binLE : UTIF._binBE; | ||
var ifds = []; | ||
while ( true ) { | ||
@@ -76,3 +70,2 @@ | ||
UTIF._readIFD( bin, data, ifdo, ifds, 0, prm ); | ||
ifdo = bin.readUint( data, ifdo + 2 + cnt * 12 ); | ||
@@ -91,22 +84,15 @@ if ( ifdo == 0 ) break; | ||
var data = new Uint8Array( buff ); | ||
var id = UTIF._binBE.readASCII( data, 0, 2 ); | ||
if ( img[ 't256' ] == null ) return; // No width => probably not an image | ||
img.isLE = id == 'II'; | ||
img.width = img[ 't256' ][ 0 ]; //delete img["t256"]; | ||
img.height = img[ 't257' ][ 0 ]; //delete img["t257"]; | ||
var cmpr = img[ 't259' ] ? img[ 't259' ][ 0 ] : 1; //delete img["t259"]; | ||
var fo = img[ 't266' ] ? img[ 't266' ][ 0 ] : 1; //delete img["t266"]; | ||
if ( img[ 't284' ] && img[ 't284' ][ 0 ] == 2 ) console.log( 'PlanarConfiguration 2 should not be used!' ); | ||
if ( cmpr == 7 && img[ 't258' ] && img[ 't258' ].length > 3 ) img[ 't258' ] = img[ 't258' ].slice( 0, 3 ); | ||
var bipp; // bits per pixel | ||
if ( img[ 't258' ] ) bipp = Math.min( 32, img[ 't258' ][ 0 ] ) * img[ 't258' ].length; else bipp = img[ 't277' ] ? img[ 't277' ][ 0 ] : 1; // Some .NEF files have t258==14, even though they use 16 bits per pixel | ||
if ( img[ 't258' ] ) bipp = Math.min( 32, img[ 't258' ][ 0 ] ) * img[ 't258' ].length; else bipp = img[ 't277' ] ? img[ 't277' ][ 0 ] : 1; | ||
// Some .NEF files have t258==14, even though they use 16 bits per pixel | ||
if ( cmpr == 1 && img[ 't279' ] != null && img[ 't278' ] && img[ 't262' ][ 0 ] == 32803 ) { | ||
@@ -123,7 +109,6 @@ | ||
if ( cmpr == 1 && soff.length == 1 ) bcnt = [ img.height * ( bipl >>> 3 ) ]; | ||
if ( bcnt == null ) bcnt = img[ 't325' ]; //bcnt[0] = Math.min(bcnt[0], data.length); // Hasselblad, "RAW_HASSELBLAD_H3D39II.3FR" | ||
if ( bcnt == null ) bcnt = img[ 't325' ]; | ||
//bcnt[0] = Math.min(bcnt[0], data.length); // Hasselblad, "RAW_HASSELBLAD_H3D39II.3FR" | ||
var bytes = new Uint8Array( img.height * ( bipl >>> 3 ) ), | ||
bilen = 0; | ||
if ( img[ 't322' ] != null ) { | ||
@@ -136,12 +121,8 @@ | ||
var tbuff = new Uint8Array( Math.ceil( tw * th * bipp / 8 ) | 0 ); | ||
for ( var y = 0; y < ty; y ++ ) for ( var x = 0; x < tx; x ++ ) { | ||
var i = y * tx + x; | ||
for ( var j = 0; j < tbuff.length; j ++ ) tbuff[ j ] = 0; | ||
UTIF.decode._decompress( img, ifds, data, soff[ i ], bcnt[ i ], cmpr, tbuff, 0, fo ); // Might be required for 7 too. Need to check | ||
UTIF.decode._decompress( img, ifds, data, soff[ i ], bcnt[ i ], cmpr, tbuff, 0, fo ); | ||
// Might be required for 7 too. Need to check | ||
if ( cmpr == 6 ) bytes = tbuff; else UTIF._copyTile( tbuff, Math.ceil( tw * bipp / 8 ) | 0, th, bytes, Math.ceil( img.width * bipp / 8 ) | 0, img.height, Math.ceil( x * tw * bipp / 8 ) | 0, y * th ); | ||
@@ -157,7 +138,5 @@ | ||
rps = Math.min( rps, img.height ); | ||
for ( var i = 0; i < soff.length; i ++ ) { | ||
UTIF.decode._decompress( img, ifds, data, soff[ i ], bcnt[ i ], cmpr, bytes, Math.ceil( bilen / 8 ) | 0, fo ); | ||
bilen += bipl * rps; | ||
@@ -179,4 +158,6 @@ | ||
//var time = Date.now(); | ||
if ( cmpr == 34676 ) UTIF.decode._decodeLogLuv32( img, data, off, len, tgt, toff ); else console.log( 'Unsupported compression', cmpr ); //console.log(Date.now()-time); | ||
if ( cmpr == 34676 ) UTIF.decode._decodeLogLuv32( img, data, off, len, tgt, toff ); else console.log( 'Unsupported compression', cmpr ); | ||
//console.log(Date.now()-time); | ||
var bps = img[ 't258' ] ? Math.min( 32, img[ 't258' ][ 0 ] ) : 1; | ||
@@ -186,5 +167,7 @@ var noc = img[ 't277' ] ? img[ 't277' ][ 0 ] : 1, | ||
h = img[ 't278' ] ? img[ 't278' ][ 0 ] : img.height, | ||
bpl = Math.ceil( bps * noc * img.width / 8 ); // convert to Little Endian /* | ||
bpl = Math.ceil( bps * noc * img.width / 8 ); | ||
if ( bps == 16 && ! img.isLE && img[ 't33422' ] == null ) // not DNG | ||
// convert to Little Endian /* | ||
if ( bps == 16 && ! img.isLE && img[ 't33422' ] == null ) | ||
// not DNG | ||
for ( var y = 0; y < h; y ++ ) { | ||
@@ -194,3 +177,2 @@ | ||
var roff = toff + y * bpl; | ||
for ( var x = 1; x < bpl; x += 2 ) { | ||
@@ -237,7 +219,5 @@ | ||
out = new Uint8Array( qw ); | ||
while ( io < len ) { | ||
var oo = 0; | ||
while ( oo < qw ) { | ||
@@ -247,7 +227,5 @@ | ||
io ++; | ||
if ( c < 128 ) { | ||
for ( var j = 0; j < c; j ++ ) out[ oo + j ] = data[ off + io + j ]; | ||
oo += c; | ||
@@ -259,5 +237,3 @@ io += c; | ||
c = c - 126; | ||
for ( var j = 0; j < c; j ++ ) out[ oo + j ] = data[ off + io ]; | ||
oo += c; | ||
@@ -284,5 +260,5 @@ io ++; | ||
UTIF.tags = {}; //UTIF.ttypes = { 256:3,257:3,258:3, 259:3, 262:3, 273:4, 274:3, 277:3,278:4,279:4, 282:5, 283:5, 284:3, 286:5,287:5, 296:3, 305:2, 306:2, 338:3, 513:4, 514:4, 34665:4 }; | ||
UTIF.tags = {}; | ||
//UTIF.ttypes = { 256:3,257:3,258:3, 259:3, 262:3, 273:4, 274:3, 277:3,278:4,279:4, 282:5, 283:5, 284:3, 286:5,287:5, 296:3, 305:2, 306:2, 338:3, 513:4, 514:4, 34665:4 }; | ||
// start at tag 250 | ||
UTIF._types = function () { | ||
@@ -359,3 +335,2 @@ | ||
}(); | ||
UTIF._readIFD = function ( bin, data, offset, ifds, depth, prm ) { | ||
@@ -367,3 +342,2 @@ | ||
if ( prm.debug ) console.log( ' '.repeat( depth ), ifds.length - 1, '>>>----------------' ); | ||
for ( var i = 0; i < cnt; i ++ ) { | ||
@@ -379,4 +353,4 @@ | ||
offset += 4; | ||
var arr = []; //ifd["t"+tag+"-"+UTIF.tags[tag]] = arr; | ||
var arr = []; | ||
//ifd["t"+tag+"-"+UTIF.tags[tag]] = arr; | ||
if ( type == 1 || type == 7 ) { | ||
@@ -412,3 +386,2 @@ | ||
var ri = type == 5 ? bin.readUint : bin.readInt; | ||
for ( var j = 0; j < num; j ++ ) arr.push( [ ri( data, voff + j * 8 ), ri( data, voff + j * 8 + 4 ) ] ); | ||
@@ -452,3 +425,2 @@ | ||
ifd[ 't' + tag ] = arr; | ||
if ( tag == 330 || tag == 34665 || tag == 34853 || tag == 50740 && bin.readUshort( data, bin.readUint( arr, 0 ) ) < 300 || tag == 61440 ) { | ||
@@ -458,9 +430,6 @@ | ||
var subfd = []; | ||
for ( var j = 0; j < oarr.length; j ++ ) UTIF._readIFD( bin, data, oarr[ j ], subfd, depth + 1, prm ); | ||
if ( tag == 330 ) ifd.subIFD = subfd; | ||
if ( tag == 34665 ) ifd.exifIFD = subfd[ 0 ]; | ||
if ( tag == 34853 ) ifd.gpsiIFD = subfd[ 0 ]; //console.log("gps", subfd[0]); } | ||
if ( tag == 50740 ) ifd.dngPrvt = subfd[ 0 ]; | ||
@@ -473,10 +442,8 @@ if ( tag == 61440 ) ifd.fujiIFD = subfd[ 0 ]; | ||
var mn = arr; //console.log(bin.readASCII(mn,0,mn.length), mn); | ||
var mn = arr; | ||
//console.log(bin.readASCII(mn,0,mn.length), mn); | ||
if ( bin.readASCII( mn, 0, 5 ) == 'Nikon' ) ifd.makerNote = UTIF[ 'decode' ]( mn.slice( 10 ).buffer )[ 0 ]; else if ( bin.readUshort( data, voff ) < 300 && bin.readUshort( data, voff + 4 ) <= 12 ) { | ||
var subsub = []; | ||
UTIF._readIFD( bin, data, voff, subsub, depth + 1, prm ); | ||
ifd.makerNote = subsub[ 0 ]; | ||
@@ -503,3 +470,2 @@ | ||
let img; | ||
switch ( type ) { | ||
@@ -510,7 +476,5 @@ | ||
break; | ||
case THREE.FloatType: | ||
img = new Float32Array( area * 4 ); | ||
break; | ||
default: | ||
@@ -524,3 +488,2 @@ console.error( 'THREE.LogLuvLoader: Unsupported texture data type:', type ); | ||
if ( out[ 't262' ] == null && bps == 1 ) intp = 0; | ||
if ( intp == 32845 ) { | ||
@@ -537,16 +500,18 @@ | ||
const u = ( data[ si + 3 ] + 0.5 ) / 410; | ||
const v = ( data[ si + 5 ] + 0.5 ) / 410; // Luv to xyY | ||
const v = ( data[ si + 5 ] + 0.5 ) / 410; | ||
// Luv to xyY | ||
const sX = 9 * u / ( 6 * u - 16 * v + 12 ); | ||
const sY = 4 * v / ( 6 * u - 16 * v + 12 ); | ||
const bY = L; // xyY to XYZ | ||
const bY = L; | ||
// xyY to XYZ | ||
const X = sX * bY / sY, | ||
Y = bY, | ||
Z = ( 1 - sX - sY ) * bY / sY; // XYZ to linear RGB | ||
Z = ( 1 - sX - sY ) * bY / sY; | ||
// XYZ to linear RGB | ||
const r = 2.690 * X - 1.276 * Y - 0.414 * Z; | ||
const g = - 1.022 * X + 1.978 * Y + 0.044 * Z; | ||
const b = 0.061 * X - 0.224 * Y + 1.163 * Z; | ||
if ( type === THREE.HalfFloatType ) { | ||
@@ -586,3 +551,2 @@ | ||
while ( data[ o ] != 0 ) o ++; | ||
return o; | ||
@@ -627,5 +591,3 @@ | ||
var s = ''; | ||
for ( var i = 0; i < l; i ++ ) s += String.fromCharCode( buff[ p + i ] ); | ||
return s; | ||
@@ -637,5 +599,3 @@ | ||
var a = UTIF._binBE.ui8; | ||
for ( var i = 0; i < 4; i ++ ) a[ i ] = buff[ p + 3 - i ]; | ||
return UTIF._binBE.fl32[ 0 ]; | ||
@@ -647,5 +607,3 @@ | ||
var a = UTIF._binBE.ui8; | ||
for ( var i = 0; i < 8; i ++ ) a[ i ] = buff[ p + 7 - i ]; | ||
return UTIF._binBE.fl64[ 0 ]; | ||
@@ -686,3 +644,2 @@ | ||
UTIF._binBE.fl64[ 0 ] = n; | ||
for ( var i = 0; i < 8; i ++ ) buff[ p + i ] = UTIF._binBE.ui8[ 7 - i ]; | ||
@@ -737,5 +694,3 @@ | ||
var a = UTIF._binBE.ui8; | ||
for ( var i = 0; i < 4; i ++ ) a[ i ] = buff[ p + i ]; | ||
return UTIF._binBE.fl32[ 0 ]; | ||
@@ -747,5 +702,3 @@ | ||
var a = UTIF._binBE.ui8; | ||
for ( var i = 0; i < 8; i ++ ) a[ i ] = buff[ p + i ]; | ||
return UTIF._binBE.fl64[ 0 ]; | ||
@@ -780,3 +733,2 @@ | ||
}; | ||
UTIF._copyTile = function ( tb, tw, th, b, w, h, xoff, yoff ) { | ||
@@ -787,3 +739,2 @@ | ||
var ylim = Math.min( th, h - yoff ); | ||
for ( var y = 0; y < ylim; y ++ ) { | ||
@@ -793,3 +744,2 @@ | ||
var sof = y * tw; | ||
for ( var x = 0; x < xlim; x ++ ) b[ tof + x ] = tb[ sof + x ]; | ||
@@ -796,0 +746,0 @@ |
@@ -10,3 +10,2 @@ ( function () { | ||
} | ||
load( url, onLoad, onProgress, onError ) { | ||
@@ -22,3 +21,5 @@ | ||
const data = JSON.parse( text ); // bodymoving uses container.offetWidth and offsetHeight | ||
const data = JSON.parse( text ); | ||
// lottie uses container.offetWidth and offsetHeight | ||
// to define width/height | ||
@@ -30,3 +31,3 @@ | ||
document.body.appendChild( container ); | ||
const animation = bodymovin.loadAnimation( { | ||
const animation = lottie.loadAnimation( { | ||
container: container, | ||
@@ -49,3 +50,2 @@ animType: 'canvas', | ||
container.style.display = 'none'; | ||
if ( onLoad !== undefined ) { | ||
@@ -52,0 +52,0 @@ |
@@ -36,3 +36,2 @@ ( function () { | ||
} | ||
parse( str ) { | ||
@@ -42,8 +41,8 @@ | ||
str = str.replace( /^#.*?(\n|\r)/gm, '' ).replace( /^\s*?(\n|\r)/gm, '' ).trim(); | ||
const lines = str.split( /[\n\r]+/g ); // first line is the positions on the grid that are provided by the LUT | ||
const lines = str.split( /[\n\r]+/g ); | ||
// first line is the positions on the grid that are provided by the LUT | ||
const gridLines = lines[ 0 ].trim().split( /\s+/g ).map( e => parseFloat( e ) ); | ||
const gridStep = gridLines[ 1 ] - gridLines[ 0 ]; | ||
const size = gridLines.length; | ||
for ( let i = 1, l = gridLines.length; i < l; i ++ ) { | ||
@@ -62,3 +61,2 @@ | ||
let maxOutputValue = 0.0; | ||
for ( let i = 1, l = lines.length; i < l; i ++ ) { | ||
@@ -74,4 +72,5 @@ | ||
const gLayer = Math.floor( index / size ) % size; | ||
const rLayer = Math.floor( index / ( size * size ) ) % size; // b grows first, then g, then r | ||
const rLayer = Math.floor( index / ( size * size ) ) % size; | ||
// b grows first, then g, then r | ||
const pixelIndex = bLayer * size * size + gLayer * size + rLayer; | ||
@@ -84,9 +83,8 @@ dataArray[ 4 * pixelIndex + 0 ] = r; | ||
} // Find the apparent bit depth of the stored RGB values and map the | ||
} | ||
// Find the apparent bit depth of the stored RGB values and map the | ||
// values to [ 0, 255 ]. | ||
const bits = Math.ceil( Math.log2( maxOutputValue ) ); | ||
const maxBitValue = Math.pow( 2.0, bits ); | ||
for ( let i = 0, l = dataArray.length; i < l; i += 4 ) { | ||
@@ -98,5 +96,3 @@ | ||
dataArray[ i + 0 ] = 255 * r / maxBitValue; // r | ||
dataArray[ i + 1 ] = 255 * g / maxBitValue; // g | ||
dataArray[ i + 2 ] = 255 * b / maxBitValue; // b | ||
@@ -103,0 +99,0 @@ |
@@ -36,3 +36,2 @@ ( function () { | ||
} | ||
parse( str ) { | ||
@@ -49,3 +48,2 @@ | ||
let currIndex = 0; | ||
for ( let i = 0, l = lines.length; i < l; i ++ ) { | ||
@@ -55,3 +53,2 @@ | ||
const split = line.split( /\s/g ); | ||
switch ( split[ 0 ] ) { | ||
@@ -62,3 +59,2 @@ | ||
break; | ||
case 'LUT_3D_SIZE': | ||
@@ -71,3 +67,2 @@ // TODO: A .CUBE LUT file specifies floating point values and could be represented with | ||
break; | ||
case 'DOMAIN_MIN': | ||
@@ -78,3 +73,2 @@ domainMin.x = parseFloat( split[ 1 ] ); | ||
break; | ||
case 'DOMAIN_MAX': | ||
@@ -85,3 +79,2 @@ domainMax.x = parseFloat( split[ 1 ] ); | ||
break; | ||
default: | ||
@@ -91,3 +84,2 @@ const r = parseFloat( split[ 0 ] ); | ||
const b = parseFloat( split[ 2 ] ); | ||
if ( r > 1.0 || r < 0.0 || g > 1.0 || g < 0.0 || b > 1.0 || b < 0.0 ) { | ||
@@ -94,0 +86,0 @@ |
@@ -36,6 +36,6 @@ ( function () { | ||
**/ | ||
function IFFParser() { | ||
this.debugger = new Debugger(); // this.debugger.enable(); // un-comment to log IFF hierarchy. | ||
this.debugger = new Debugger(); | ||
// this.debugger.enable(); // un-comment to log IFF hierarchy. | ||
@@ -54,4 +54,5 @@ } | ||
textures: [] | ||
}; // start out at the top level to add any data before first layer is encountered | ||
}; | ||
// start out at the top level to add any data before first layer is encountered | ||
this.currentLayer = this.tree; | ||
@@ -61,7 +62,5 @@ this.currentForm = this.tree; | ||
if ( this.tree.format === undefined ) return; | ||
if ( this.tree.format === 'LWO2' ) { | ||
this.parser = new THREE.LWO2Parser( this ); | ||
while ( ! this.reader.endOfFile() ) this.parser.parseBlock(); | ||
@@ -72,3 +71,2 @@ | ||
this.parser = new THREE.LWO3Parser( this ); | ||
while ( ! this.reader.endOfFile() ) this.parser.parseBlock(); | ||
@@ -83,3 +81,2 @@ | ||
}, | ||
parseTopForm() { | ||
@@ -89,3 +86,2 @@ | ||
var topForm = this.reader.getIDTag(); | ||
if ( topForm !== 'FORM' ) { | ||
@@ -102,3 +98,2 @@ | ||
var type = this.reader.getIDTag(); | ||
if ( type === 'LWO2' ) { | ||
@@ -120,6 +115,6 @@ | ||
}, | ||
/// | ||
// FORM PARSING METHODS | ||
/// | ||
// Forms are organisational and can contain any number of sub chunks and sub forms | ||
@@ -130,3 +125,2 @@ // FORM ::= 'FORM'[ID4], length[U4], type[ID4], ( chunk[CHUNK] | form[FORM] ) * } | ||
var type = this.reader.getIDTag(); | ||
switch ( type ) { | ||
@@ -136,8 +130,6 @@ | ||
// if skipForm( length ) is called, the entire form and any sub forms and chunks are skipped | ||
case 'ISEQ': // Image sequence | ||
case 'ANIM': // plug in animation | ||
case 'STCC': // Color-cycling Still | ||
case 'VPVL': | ||
@@ -147,5 +139,3 @@ case 'VPRM': | ||
case 'WRPW': // image wrap w ( for cylindrical and spherical projections) | ||
case 'WRPH': // image wrap h | ||
case 'FUNC': | ||
@@ -155,7 +145,7 @@ case 'FALL': | ||
case 'GRAD': // gradient texture | ||
case 'ENVS': | ||
case 'VMOP': | ||
case 'VMBG': // Car Material FORMS | ||
case 'VMBG': | ||
// Car Material FORMS | ||
case 'OMAX': | ||
@@ -169,7 +159,6 @@ case 'STEX': | ||
this.skipForm( length ); // not currently supported | ||
break; | ||
break; | ||
// if break; is called directly, the position in the lwoTree is not created | ||
// any sub chunks and forms are added to the parent form instead | ||
case 'META': | ||
@@ -181,10 +170,8 @@ case 'NNDS': | ||
case 'AOVS': | ||
case 'BLOK': // used by texture nodes | ||
case 'BLOK': | ||
// used by texture nodes | ||
case 'IBGC': // imageBackgroundColor | ||
case 'IOPC': // imageOpacity | ||
case 'IIMG': // hold reference to image path | ||
case 'TXTR': | ||
@@ -195,11 +182,6 @@ // this.setupForm( type, length ); | ||
break; | ||
case 'IFAL': // imageFallof | ||
case 'ISCL': // imageScale | ||
case 'IPOS': // imagePosition | ||
case 'IROT': // imageRotation | ||
case 'IBMP': | ||
@@ -210,6 +192,6 @@ case 'IUTD': | ||
break; | ||
case 'ENVL': | ||
this.parseEnvelope( length ); | ||
break; | ||
// CLIP FORM AND SUB FORMS | ||
@@ -229,17 +211,15 @@ | ||
break; | ||
case 'STIL': | ||
this.parseImage(); | ||
break; | ||
case 'XREF': | ||
// clone of another STIL | ||
this.reader.skip( 8 ); // unknown | ||
this.currentForm.referenceTexture = { | ||
index: this.reader.getUint32(), | ||
refName: this.reader.getString() // internal unique ref | ||
}; | ||
}; | ||
break; | ||
// Not in spec, used by texture nodes | ||
@@ -250,2 +230,3 @@ | ||
break; | ||
// SURF FORM AND SUB FORMS | ||
@@ -256,3 +237,2 @@ | ||
break; | ||
case 'VALU': | ||
@@ -262,9 +242,6 @@ // Not in spec | ||
break; | ||
case 'NTAG': | ||
this.parseSubNode( length ); | ||
break; | ||
case 'ATTR': // BSDF Node Attributes | ||
case 'SATR': | ||
@@ -274,7 +251,5 @@ // Standard Node Attributes | ||
break; | ||
case 'NCON': | ||
this.parseConnections( length ); | ||
break; | ||
case 'SSHA': | ||
@@ -285,7 +260,5 @@ this.parentForm = this.currentForm; | ||
break; | ||
case 'SSHD': | ||
this.setupForm( 'surfaceShaderData', length ); | ||
break; | ||
case 'ENTR': | ||
@@ -295,2 +268,3 @@ // Not in spec | ||
break; | ||
// Image Map Layer | ||
@@ -301,6 +275,6 @@ | ||
break; | ||
case 'TAMP': | ||
this.parseXVAL( 'amplitude', length ); | ||
break; | ||
//Texture Mapping Form | ||
@@ -311,15 +285,11 @@ | ||
break; | ||
case 'CNTR': | ||
this.parseXVAL3( 'center', length ); | ||
break; | ||
case 'SIZE': | ||
this.parseXVAL3( 'scale', length ); | ||
break; | ||
case 'ROTA': | ||
this.parseXVAL3( 'rotation', length ); | ||
break; | ||
default: | ||
@@ -335,3 +305,2 @@ this.parseUnknownForm( type, length ); | ||
}, | ||
setupForm( type, length ) { | ||
@@ -342,3 +311,2 @@ | ||
this.parentForm = this.currentForm; | ||
if ( ! this.currentForm[ type ] ) { | ||
@@ -358,3 +326,2 @@ | ||
}, | ||
skipForm( length ) { | ||
@@ -365,3 +332,2 @@ | ||
}, | ||
parseUnknownForm( type, length ) { | ||
@@ -374,3 +340,2 @@ | ||
}, | ||
parseSurfaceForm( length ) { | ||
@@ -397,3 +362,2 @@ | ||
}, | ||
parseSurfaceLwo2( length ) { | ||
@@ -417,3 +381,2 @@ | ||
}, | ||
parseSubNode( length ) { | ||
@@ -424,4 +387,4 @@ | ||
// some subnodes can be renamed, but Input and Surface cannot | ||
this.reader.skip( 8 ); // NRNM + length | ||
var name = this.reader.getString(); | ||
@@ -436,3 +399,2 @@ var node = { | ||
}, | ||
// collect attributes from all nodes at the top level of a surface | ||
@@ -446,3 +408,2 @@ parseConnections( length ) { | ||
}, | ||
// surface node attribute data, e.g. specular, roughness etc | ||
@@ -452,3 +413,2 @@ parseEntryForm( length ) { | ||
this.reader.skip( 8 ); // NAME + length | ||
var name = this.reader.getString(); | ||
@@ -459,3 +419,2 @@ this.currentForm = this.currentNode.attributes; | ||
}, | ||
// parse values from material - doesn't match up to other LWO3 data types | ||
@@ -468,3 +427,2 @@ // sub form of entry form | ||
var valueType = this.reader.getString(); | ||
if ( valueType === 'double' ) { | ||
@@ -491,3 +449,2 @@ | ||
}, | ||
// holds various data about texture node image state | ||
@@ -502,3 +459,2 @@ // Data other thanmipMapLevel unknown | ||
}, | ||
// LWO2 style image data node OR LWO3 textures defined at top level in editor (not as SURF node) | ||
@@ -528,23 +484,17 @@ parseImageMap( length ) { | ||
break; | ||
case 'IPOS': | ||
this.currentNode.position = this.reader.getFloat32Array( 3 ); | ||
break; | ||
case 'IROT': | ||
this.currentNode.rotation = this.reader.getFloat32Array( 3 ); | ||
break; | ||
case 'IFAL': | ||
this.currentNode.falloff = this.reader.getFloat32Array( 3 ); | ||
break; | ||
case 'IBMP': | ||
this.currentNode.amplitude = this.reader.getFloat32(); | ||
break; | ||
case 'IUTD': | ||
this.currentNode.uTiles = this.reader.getFloat32(); | ||
break; | ||
case 'IVTD': | ||
@@ -570,2 +520,3 @@ this.currentNode.vTiles = this.reader.getFloat32(); | ||
/// | ||
// clips can either be defined inside a surface node, or at the top | ||
@@ -575,4 +526,5 @@ // level and they have a different format in each case | ||
var tag = this.reader.getIDTag(); // inside surface node | ||
var tag = this.reader.getIDTag(); | ||
// inside surface node | ||
if ( tag === 'FORM' ) { | ||
@@ -584,5 +536,5 @@ | ||
} // otherwise top level | ||
} | ||
// otherwise top level | ||
this.reader.setOffset( this.reader.offset - 4 ); | ||
@@ -600,3 +552,2 @@ this.currentFormEnd = this.reader.offset + length; | ||
}, | ||
parseClipLwo2( length ) { | ||
@@ -607,4 +558,5 @@ | ||
fileName: '' | ||
}; // seach STIL block | ||
}; | ||
// seach STIL block | ||
while ( true ) { | ||
@@ -614,3 +566,2 @@ | ||
var n_length = this.reader.getUint16(); | ||
if ( tag === 'STIL' ) { | ||
@@ -635,11 +586,8 @@ | ||
}, | ||
parseImage() { | ||
this.reader.skip( 8 ); // unknown | ||
this.currentForm.fileName = this.reader.getString(); | ||
}, | ||
parseXVAL( type, length ) { | ||
@@ -666,3 +614,2 @@ | ||
}, | ||
// Tags associated with an object | ||
@@ -678,3 +625,2 @@ // OTAG { type[ID4], tag-string[S0] } | ||
}, | ||
// Signals the start of a new layer. All the data chunks which follow will be included in this layer until another layer chunk is encountered. | ||
@@ -695,4 +641,4 @@ // LAYR: number[U2], flags[U2], pivot[VEC12], name[S0], parent[U2] | ||
var parsedLength = 16 + stringOffset( this.currentLayer.name ); // index ( 2 ) + flags( 2 ) + pivot( 12 ) + stringlength | ||
// if we have not reached then end of the layer block, there must be a parent defined | ||
this.currentLayer.parent = parsedLength < length ? this.reader.getUint16() : - 1; // omitted or -1 for no parent | ||
@@ -708,3 +654,2 @@ | ||
this.currentPoints = []; | ||
for ( var i = 0; i < length / 4; i += 3 ) { | ||
@@ -718,6 +663,6 @@ | ||
}, | ||
// parse VMAP or VMAD | ||
// Associates a set of floating-point vectors with a set of points. | ||
// VMAP: { type[ID4], dimension[U2], name[S0], ( vert[VX], value[F4] # dimension ) * } | ||
// VMAD Associates a set of floating-point vectors with the vertices of specific polygons. | ||
@@ -733,3 +678,2 @@ // Similar to VMAP UVs, but associates with polygon vertices rather than points | ||
var channelName = this.reader.getString(); | ||
if ( this.reader.offset === finalOffset ) { | ||
@@ -741,12 +685,10 @@ | ||
} // otherwise reset to initial length and parse normal VMAP CHUNK | ||
} | ||
// otherwise reset to initial length and parse normal VMAP CHUNK | ||
this.reader.setOffset( this.reader.offset - stringOffset( channelName ) ); | ||
var type = this.reader.getIDTag(); | ||
this.reader.getUint16(); // dimension | ||
var name = this.reader.getString(); | ||
var remainingLength = length - 6 - stringOffset( name ); | ||
switch ( type ) { | ||
@@ -757,10 +699,7 @@ | ||
break; | ||
case 'MORF': | ||
case 'SPOT': | ||
this.parseMorphTargets( name, finalOffset, type ); // can't be discontinuous | ||
break; | ||
// unsupported VMAPs | ||
case 'APSL': | ||
@@ -775,3 +714,2 @@ case 'NORM': | ||
break; | ||
default: | ||
@@ -784,3 +722,2 @@ console.warn( 'LWOLoader: unknown vertex map type: ' + type ); | ||
}, | ||
parseUVMapping( name, finalOffset, discontinuous ) { | ||
@@ -791,3 +728,2 @@ | ||
var uvs = []; | ||
while ( this.reader.offset < finalOffset ) { | ||
@@ -821,3 +757,2 @@ | ||
}, | ||
parseMorphTargets( name, finalOffset, type ) { | ||
@@ -828,7 +763,6 @@ | ||
type = type === 'MORF' ? 'relative' : 'absolute'; | ||
while ( this.reader.offset < finalOffset ) { | ||
indices.push( this.reader.getVariableLengthIndex() ); // z -> -z to match three.js right handed coords | ||
indices.push( this.reader.getVariableLengthIndex() ); | ||
// z -> -z to match three.js right handed coords | ||
points.push( this.reader.getFloat32(), this.reader.getFloat32(), - this.reader.getFloat32() ); | ||
@@ -846,3 +780,2 @@ | ||
}, | ||
// A list of polygons for the current layer. | ||
@@ -854,14 +787,13 @@ // POLS { type[ID4], ( numvert+flags[U2], vert[VX] # numvert ) * } | ||
var type = this.reader.getIDTag(); | ||
var indices = []; // hold a list of polygon sizes, to be split up later | ||
var indices = []; | ||
// hold a list of polygon sizes, to be split up later | ||
var polygonDimensions = []; | ||
while ( this.reader.offset < finalOffset ) { | ||
var numverts = this.reader.getUint16(); //var flags = numverts & 64512; // 6 high order bits are flags - ignoring for now | ||
var numverts = this.reader.getUint16(); | ||
//var flags = numverts & 64512; // 6 high order bits are flags - ignoring for now | ||
numverts = numverts & 1023; // remaining ten low order bits are vertex num | ||
polygonDimensions.push( numverts ); | ||
for ( var j = 0; j < numverts; j ++ ) indices.push( this.reader.getVariableLengthIndex() ); | ||
@@ -876,4 +808,5 @@ | ||
points: this.currentPoints | ||
}; // Note: assuming that all polys will be lines or points if the first is | ||
}; | ||
// Note: assuming that all polys will be lines or points if the first is | ||
if ( polygonDimensions[ 0 ] === 1 ) geometryData.type = 'points'; else if ( polygonDimensions[ 0 ] === 2 ) geometryData.type = 'lines'; | ||
@@ -883,3 +816,2 @@ this.currentLayer.geometry = geometryData; | ||
}, | ||
// Lists the tag strings that can be associated with polygons by the PTAG chunk. | ||
@@ -892,3 +824,2 @@ // TAGS { tag-string[S0] * } | ||
}, | ||
// Associates tags of a given type with polygons in the most recent POLS chunk. | ||
@@ -903,2 +834,3 @@ // PTAG { type[ID4], ( poly[VX], tag[U2] ) * } | ||
//PART, SMGP, COLR not supported | ||
this.reader.skip( length - 4 ); | ||
@@ -909,3 +841,2 @@ | ||
}, | ||
parseMaterialIndices( finalOffset ) { | ||
@@ -915,3 +846,2 @@ | ||
this.currentLayer.geometry.materialIndices = []; | ||
while ( this.reader.offset < finalOffset ) { | ||
@@ -926,6 +856,7 @@ | ||
}, | ||
parseUnknownCHUNK( blockID, length ) { | ||
console.warn( 'LWOLoader: unknown chunk type: ' + blockID + ' length: ' + length ); // print the chunk plus some bytes padding either side | ||
console.warn( 'LWOLoader: unknown chunk type: ' + blockID + ' length: ' + length ); | ||
// print the chunk plus some bytes padding either side | ||
// printBuffer( this.reader.dv.buffer, this.reader.offset - 20, length + 40 ); | ||
@@ -937,5 +868,3 @@ | ||
} | ||
}; | ||
function DataViewReader( buffer ) { | ||
@@ -955,3 +884,2 @@ | ||
}, | ||
setOffset( offset ) { | ||
@@ -970,3 +898,2 @@ | ||
}, | ||
endOfFile: function () { | ||
@@ -1029,3 +956,2 @@ | ||
var a = []; | ||
for ( var i = 0; i < size; i ++ ) { | ||
@@ -1050,3 +976,2 @@ | ||
var a = []; | ||
for ( var i = 0; i < size; i ++ ) { | ||
@@ -1061,3 +986,2 @@ | ||
}, | ||
// get variable-length index data type | ||
@@ -1072,3 +996,2 @@ // VX ::= index[U2] | (index + 0xFF000000)[U4] | ||
var firstByte = this.getUint8(); | ||
if ( firstByte === 255 ) { | ||
@@ -1083,3 +1006,2 @@ | ||
}, | ||
// An ID tag is a sequence of 4 bytes containing 7-bit ASCII values | ||
@@ -1091,9 +1013,8 @@ getIDTag() { | ||
}, | ||
getString: function ( size ) { | ||
if ( size === 0 ) return; // note: safari 9 doesn't support Uint8Array.indexOf; create intermediate array instead | ||
if ( size === 0 ) return; | ||
// note: safari 9 doesn't support Uint8Array.indexOf; create intermediate array instead | ||
var a = []; | ||
if ( size ) { | ||
@@ -1111,3 +1032,2 @@ | ||
var len = 0; | ||
while ( currentChar !== 0 ) { | ||
@@ -1135,4 +1055,6 @@ | ||
} | ||
}; // ************** DEBUGGER ************** | ||
}; | ||
// ************** DEBUGGER ************** | ||
function Debugger() { | ||
@@ -1157,3 +1079,2 @@ | ||
var nodeType; | ||
switch ( this.node ) { | ||
@@ -1164,7 +1085,5 @@ | ||
break; | ||
case 1: | ||
nodeType = 'CHK'; | ||
break; | ||
case 2: | ||
@@ -1177,3 +1096,2 @@ nodeType = 'S-CHK'; | ||
console.log( '| '.repeat( this.depth ) + nodeType, this.nodeID, `( ${this.offset} ) -> ( ${this.dataOffset + this.length} )`, this.node == 0 ? ' {' : '', this.skipped ? 'SKIPPED' : '', this.node == 0 && this.skipped ? '}' : '' ); | ||
if ( this.node == 0 && ! this.skipped ) { | ||
@@ -1192,3 +1110,2 @@ | ||
if ( ! this.active ) return; | ||
for ( var i = this.formList.length - 1; i >= 0; i -- ) { | ||
@@ -1207,4 +1124,6 @@ | ||
} | ||
}; // ************** UTILITY FUNCTIONS ************** | ||
}; | ||
// ************** UTILITY FUNCTIONS ************** | ||
function isEven( num ) { | ||
@@ -1214,6 +1133,6 @@ | ||
} // calculate the length of the string in the buffer | ||
} | ||
// calculate the length of the string in the buffer | ||
// this will be string.length + nullbyte + optional padbyte to make the length even | ||
function stringOffset( string ) { | ||
@@ -1223,6 +1142,6 @@ | ||
} // for testing purposes, dump buffer to console | ||
} | ||
// for testing purposes, dump buffer to console | ||
// printBuffer( this.reader.dv.buffer, this.reader.offset, length ); | ||
function printBuffer( buffer, from, to ) { | ||
@@ -1229,0 +1148,0 @@ |
@@ -10,3 +10,2 @@ ( function () { | ||
} | ||
parseBlock() { | ||
@@ -18,3 +17,2 @@ | ||
let length = this.IFF.reader.getUint32(); // size of data in bytes | ||
if ( length > this.IFF.reader.dv.byteLength - this.IFF.reader.offset ) { | ||
@@ -28,4 +26,5 @@ | ||
this.IFF.debugger.dataOffset = this.IFF.reader.offset; | ||
this.IFF.debugger.length = length; // Data types may be found in either LWO2 OR LWO3 spec | ||
this.IFF.debugger.length = length; | ||
// Data types may be found in either LWO2 OR LWO3 spec | ||
switch ( blockID ) { | ||
@@ -37,2 +36,3 @@ | ||
break; | ||
// SKIPPED CHUNKS | ||
@@ -42,19 +42,18 @@ // if break; is called directly, the position in the lwoTree is not created | ||
// MISC skipped | ||
case 'ICON': // Thumbnail Icon Image | ||
case 'VMPA': // Vertex Map Parameter | ||
case 'BBOX': // bounding box | ||
// case 'VMMD': | ||
// case 'VTYP': | ||
// normal maps can be specified, normally on models imported from other applications. Currently ignored | ||
case 'NORM': | ||
case 'NORM': // ENVL FORM skipped | ||
// ENVL FORM skipped | ||
case 'PRE ': | ||
case 'POST': | ||
case 'KEY ': | ||
case 'SPAN': // CLIP FORM skipped | ||
case 'SPAN': | ||
// CLIP FORM skipped | ||
case 'TIME': | ||
@@ -72,4 +71,5 @@ case 'CLRS': | ||
case 'IFLT': | ||
case 'PFLT': // Image Map Layer skipped | ||
case 'PFLT': | ||
// Image Map Layer skipped | ||
case 'PROJ': | ||
@@ -80,8 +80,10 @@ case 'AXIS': | ||
case 'AUVO': | ||
case 'STCK': // Procedural Textures skipped | ||
case 'STCK': | ||
// Procedural Textures skipped | ||
case 'PROC': | ||
case 'VALU': | ||
case 'FUNC': // Gradient Textures skipped | ||
case 'FUNC': | ||
// Gradient Textures skipped | ||
case 'PNAM': | ||
@@ -93,12 +95,13 @@ case 'INAM': | ||
case 'FKEY': | ||
case 'IKEY': // Texture Mapping Form skipped | ||
case 'IKEY': | ||
case 'CSYS': // Surface CHUNKs skipped | ||
// Texture Mapping Form skipped | ||
case 'CSYS': | ||
// Surface CHUNKs skipped | ||
case 'OPAQ': // top level 'opacity' checkbox | ||
case 'CMAP': // clip map | ||
case 'CMAP': // clip map | ||
// Surface node CHUNKS skipped | ||
// These mainly specify the node editor setup in LW | ||
case 'NLOC': | ||
@@ -109,8 +112,5 @@ case 'NZOM': | ||
case 'NVSK': // unknown | ||
case 'NCRD': | ||
case 'WRPW': // image wrap w ( for cylindrical and spherical projections) | ||
case 'WRPH': // image wrap h | ||
case 'NMOD': | ||
@@ -124,4 +124,5 @@ case 'NSEL': | ||
case 'TAG ': | ||
case 'OPAC': // Car Material CHUNKS | ||
case 'OPAC': | ||
// Car Material CHUNKS | ||
case 'CGMD': | ||
@@ -140,3 +141,2 @@ case 'CGTY': | ||
case 'GVAL': // glow intensity | ||
case 'SHRP': | ||
@@ -158,30 +158,19 @@ case 'RFOP': | ||
break; | ||
case 'SURF': | ||
this.IFF.parseSurfaceLwo2( length ); | ||
break; | ||
case 'CLIP': | ||
this.IFF.parseClipLwo2( length ); | ||
break; | ||
// Texture node chunks (not in spec) | ||
case 'IPIX': // usePixelBlending | ||
case 'IMIP': // useMipMaps | ||
case 'IMOD': // imageBlendingMode | ||
case 'AMOD': // unknown | ||
case 'IINV': // imageInvertAlpha | ||
case 'INCR': // imageInvertColor | ||
case 'IAXS': // imageAxis ( for non-UV maps) | ||
case 'IFOT': // imageFallofType | ||
case 'ITIM': // timing for animated textures | ||
case 'IWRL': | ||
@@ -196,19 +185,14 @@ case 'IUTI': | ||
break; | ||
case 'OTAG': | ||
this.IFF.parseObjectTag(); | ||
break; | ||
case 'LAYR': | ||
this.IFF.parseLayer( length ); | ||
break; | ||
case 'PNTS': | ||
this.IFF.parsePoints( length ); | ||
break; | ||
case 'VMAP': | ||
this.IFF.parseVertexMapping( length ); | ||
break; | ||
case 'AUVU': | ||
@@ -218,22 +202,17 @@ case 'AUVN': | ||
this.IFF.reader.getVariableLengthIndex(); // VX | ||
break; | ||
case 'POLS': | ||
this.IFF.parsePolygonList( length ); | ||
break; | ||
case 'TAGS': | ||
this.IFF.parseTagStrings( length ); | ||
break; | ||
case 'PTAG': | ||
this.IFF.parsePolygonTagMapping( length ); | ||
break; | ||
case 'VMAD': | ||
this.IFF.parseVertexMapping( length, true ); | ||
break; | ||
// Misc CHUNKS | ||
case 'DESC': | ||
@@ -243,3 +222,2 @@ // Description Line | ||
break; | ||
case 'TEXT': | ||
@@ -250,9 +228,9 @@ case 'CMNT': | ||
break; | ||
// Envelope Form | ||
case 'NAME': | ||
this.IFF.currentForm.channelName = this.IFF.reader.getString(); | ||
break; | ||
// Image Map Layer | ||
case 'WRAP': | ||
@@ -264,3 +242,2 @@ this.IFF.currentForm.wrap = { | ||
break; | ||
case 'IMAG': | ||
@@ -270,30 +247,26 @@ const index = this.IFF.reader.getVariableLengthIndex(); | ||
break; | ||
// Texture Mapping Form | ||
case 'OREF': | ||
this.IFF.currentForm.referenceObject = this.IFF.reader.getString(); | ||
break; | ||
case 'ROID': | ||
this.IFF.currentForm.referenceObjectID = this.IFF.reader.getUint32(); | ||
break; | ||
// Surface Blocks | ||
case 'SSHN': | ||
this.IFF.currentSurface.surfaceShaderName = this.IFF.reader.getString(); | ||
break; | ||
case 'AOVN': | ||
this.IFF.currentSurface.surfaceCustomAOVName = this.IFF.reader.getString(); | ||
break; | ||
// Nodal Blocks | ||
case 'NSTA': | ||
this.IFF.currentForm.disabled = this.IFF.reader.getUint16(); | ||
break; | ||
case 'NRNM': | ||
this.IFF.currentForm.realName = this.IFF.reader.getString(); | ||
break; | ||
case 'NNME': | ||
@@ -303,4 +276,4 @@ this.IFF.currentForm.refName = this.IFF.reader.getString(); | ||
break; | ||
// Nodal Blocks : connections | ||
case 'INME': | ||
@@ -310,3 +283,2 @@ if ( ! this.IFF.currentForm.nodeName ) this.IFF.currentForm.nodeName = []; | ||
break; | ||
case 'IINN': | ||
@@ -316,3 +288,2 @@ if ( ! this.IFF.currentForm.inputNodeName ) this.IFF.currentForm.inputNodeName = []; | ||
break; | ||
case 'IINM': | ||
@@ -322,3 +293,2 @@ if ( ! this.IFF.currentForm.inputName ) this.IFF.currentForm.inputName = []; | ||
break; | ||
case 'IONM': | ||
@@ -328,7 +298,5 @@ if ( ! this.IFF.currentForm.inputOutputName ) this.IFF.currentForm.inputOutputName = []; | ||
break; | ||
case 'FNAM': | ||
this.IFF.currentForm.fileName = this.IFF.reader.getString(); | ||
break; | ||
case 'CHAN': | ||
@@ -338,4 +306,4 @@ // NOTE: ENVL Forms may also have CHAN chunk, however ENVL is currently ignored | ||
break; | ||
// LWO2 Spec chunks: these are needed since the SURF FORMs are often in LWO2 format | ||
case 'SMAN': | ||
@@ -345,4 +313,4 @@ const maxSmoothingAngle = this.IFF.reader.getFloat32(); | ||
break; | ||
// LWO2: Basic Surface Parameters | ||
case 'COLR': | ||
@@ -353,5 +321,3 @@ this.IFF.currentSurface.attributes.Color = { | ||
this.IFF.reader.skip( 2 ); // VX: envelope | ||
break; | ||
case 'LUMI': | ||
@@ -363,3 +329,2 @@ this.IFF.currentSurface.attributes.Luminosity = { | ||
break; | ||
case 'SPEC': | ||
@@ -371,3 +336,2 @@ this.IFF.currentSurface.attributes.Specular = { | ||
break; | ||
case 'DIFF': | ||
@@ -379,3 +343,2 @@ this.IFF.currentSurface.attributes.Diffuse = { | ||
break; | ||
case 'REFL': | ||
@@ -387,3 +350,2 @@ this.IFF.currentSurface.attributes.Reflection = { | ||
break; | ||
case 'GLOS': | ||
@@ -395,3 +357,2 @@ this.IFF.currentSurface.attributes.Glossiness = { | ||
break; | ||
case 'TRAN': | ||
@@ -401,3 +362,2 @@ this.IFF.currentSurface.attributes.opacity = this.IFF.reader.getFloat32(); | ||
break; | ||
case 'BUMP': | ||
@@ -407,11 +367,8 @@ this.IFF.currentSurface.attributes.bumpStrength = this.IFF.reader.getFloat32(); | ||
break; | ||
case 'SIDE': | ||
this.IFF.currentSurface.attributes.side = this.IFF.reader.getUint16(); | ||
break; | ||
case 'RIMG': | ||
this.IFF.currentSurface.attributes.reflectionMap = this.IFF.reader.getVariableLengthIndex(); | ||
break; | ||
case 'RIND': | ||
@@ -421,17 +378,12 @@ this.IFF.currentSurface.attributes.refractiveIndex = this.IFF.reader.getFloat32(); | ||
break; | ||
case 'TIMG': | ||
this.IFF.currentSurface.attributes.refractionMap = this.IFF.reader.getVariableLengthIndex(); | ||
break; | ||
case 'IMAP': | ||
this.IFF.reader.skip( 2 ); | ||
break; | ||
case 'TMAP': | ||
this.IFF.debugger.skipped = true; | ||
this.IFF.reader.skip( length ); // needs implementing | ||
break; | ||
case 'IUVI': | ||
@@ -441,3 +393,2 @@ // uv channel name | ||
break; | ||
case 'IUTL': | ||
@@ -447,3 +398,2 @@ // widthWrappingMode: 0 = Reset, 1 = Repeat, 2 = Mirror, 3 = Edge | ||
break; | ||
case 'IVTL': | ||
@@ -453,8 +403,7 @@ // heightWrappingMode | ||
break; | ||
// LWO2 USE | ||
case 'BLOK': | ||
// skip | ||
break; | ||
default: | ||
@@ -461,0 +410,0 @@ this.IFF.parseUnknownCHUNK( blockID, length ); |
@@ -10,3 +10,2 @@ ( function () { | ||
} | ||
parseBlock() { | ||
@@ -20,4 +19,5 @@ | ||
this.IFF.debugger.dataOffset = this.IFF.reader.offset; | ||
this.IFF.debugger.length = length; // Data types may be found in either LWO2 OR LWO3 spec | ||
this.IFF.debugger.length = length; | ||
// Data types may be found in either LWO2 OR LWO3 spec | ||
switch ( blockID ) { | ||
@@ -29,23 +29,21 @@ | ||
break; | ||
// SKIPPED CHUNKS | ||
// MISC skipped | ||
case 'ICON': // Thumbnail Icon Image | ||
case 'VMPA': // Vertex Map Parameter | ||
case 'BBOX': // bounding box | ||
// case 'VMMD': | ||
// case 'VTYP': | ||
// normal maps can be specified, normally on models imported from other applications. Currently ignored | ||
case 'NORM': | ||
case 'NORM': // ENVL FORM skipped | ||
// ENVL FORM skipped | ||
case 'PRE ': // Pre-loop behavior for the keyframe | ||
case 'POST': // Post-loop behavior for the keyframe | ||
case 'KEY ': | ||
case 'SPAN': // CLIP FORM skipped | ||
case 'SPAN': | ||
// CLIP FORM skipped | ||
case 'TIME': | ||
@@ -63,4 +61,5 @@ case 'CLRS': | ||
case 'IFLT': | ||
case 'PFLT': // Image Map Layer skipped | ||
case 'PFLT': | ||
// Image Map Layer skipped | ||
case 'PROJ': | ||
@@ -70,6 +69,8 @@ case 'AXIS': | ||
case 'PIXB': | ||
case 'STCK': // Procedural Textures skipped | ||
case 'STCK': | ||
case 'VALU': // Gradient Textures skipped | ||
// Procedural Textures skipped | ||
case 'VALU': | ||
// Gradient Textures skipped | ||
case 'PNAM': | ||
@@ -81,12 +82,13 @@ case 'INAM': | ||
case 'FKEY': | ||
case 'IKEY': // Texture Mapping Form skipped | ||
case 'IKEY': | ||
case 'CSYS': // Surface CHUNKs skipped | ||
// Texture Mapping Form skipped | ||
case 'CSYS': | ||
// Surface CHUNKs skipped | ||
case 'OPAQ': // top level 'opacity' checkbox | ||
case 'CMAP': // clip map | ||
case 'CMAP': // clip map | ||
// Surface node CHUNKS skipped | ||
// These mainly specify the node editor setup in LW | ||
case 'NLOC': | ||
@@ -103,4 +105,5 @@ case 'NZOM': | ||
case 'ENUM': | ||
case 'TAG ': // Car Material CHUNKS | ||
case 'TAG ': | ||
// Car Material CHUNKS | ||
case 'CGMD': | ||
@@ -134,22 +137,13 @@ case 'CGTY': | ||
break; | ||
// Texture node chunks (not in spec) | ||
case 'IPIX': // usePixelBlending | ||
case 'IMIP': // useMipMaps | ||
case 'IMOD': // imageBlendingMode | ||
case 'AMOD': // unknown | ||
case 'IINV': // imageInvertAlpha | ||
case 'INCR': // imageInvertColor | ||
case 'IAXS': // imageAxis ( for non-UV maps) | ||
case 'IFOT': // imageFallofType | ||
case 'ITIM': // timing for animated textures | ||
case 'IWRL': | ||
@@ -164,36 +158,28 @@ case 'IUTI': | ||
break; | ||
case 'OTAG': | ||
this.IFF.parseObjectTag(); | ||
break; | ||
case 'LAYR': | ||
this.IFF.parseLayer( length ); | ||
break; | ||
case 'PNTS': | ||
this.IFF.parsePoints( length ); | ||
break; | ||
case 'VMAP': | ||
this.IFF.parseVertexMapping( length ); | ||
break; | ||
case 'POLS': | ||
this.IFF.parsePolygonList( length ); | ||
break; | ||
case 'TAGS': | ||
this.IFF.parseTagStrings( length ); | ||
break; | ||
case 'PTAG': | ||
this.IFF.parsePolygonTagMapping( length ); | ||
break; | ||
case 'VMAD': | ||
this.IFF.parseVertexMapping( length, true ); | ||
break; | ||
// Misc CHUNKS | ||
case 'DESC': | ||
@@ -203,3 +189,2 @@ // Description Line | ||
break; | ||
case 'TEXT': | ||
@@ -210,9 +195,9 @@ case 'CMNT': | ||
break; | ||
// Envelope Form | ||
case 'NAME': | ||
this.IFF.currentForm.channelName = this.IFF.reader.getString(); | ||
break; | ||
// Image Map Layer | ||
case 'WRAP': | ||
@@ -224,3 +209,2 @@ this.IFF.currentForm.wrap = { | ||
break; | ||
case 'IMAG': | ||
@@ -230,30 +214,26 @@ const index = this.IFF.reader.getVariableLengthIndex(); | ||
break; | ||
// Texture Mapping Form | ||
case 'OREF': | ||
this.IFF.currentForm.referenceObject = this.IFF.reader.getString(); | ||
break; | ||
case 'ROID': | ||
this.IFF.currentForm.referenceObjectID = this.IFF.reader.getUint32(); | ||
break; | ||
// Surface Blocks | ||
case 'SSHN': | ||
this.IFF.currentSurface.surfaceShaderName = this.IFF.reader.getString(); | ||
break; | ||
case 'AOVN': | ||
this.IFF.currentSurface.surfaceCustomAOVName = this.IFF.reader.getString(); | ||
break; | ||
// Nodal Blocks | ||
case 'NSTA': | ||
this.IFF.currentForm.disabled = this.IFF.reader.getUint16(); | ||
break; | ||
case 'NRNM': | ||
this.IFF.currentForm.realName = this.IFF.reader.getString(); | ||
break; | ||
case 'NNME': | ||
@@ -263,4 +243,4 @@ this.IFF.currentForm.refName = this.IFF.reader.getString(); | ||
break; | ||
// Nodal Blocks : connections | ||
case 'INME': | ||
@@ -270,3 +250,2 @@ if ( ! this.IFF.currentForm.nodeName ) this.IFF.currentForm.nodeName = []; | ||
break; | ||
case 'IINN': | ||
@@ -276,3 +255,2 @@ if ( ! this.IFF.currentForm.inputNodeName ) this.IFF.currentForm.inputNodeName = []; | ||
break; | ||
case 'IINM': | ||
@@ -282,3 +260,2 @@ if ( ! this.IFF.currentForm.inputName ) this.IFF.currentForm.inputName = []; | ||
break; | ||
case 'IONM': | ||
@@ -288,7 +265,5 @@ if ( ! this.IFF.currentForm.inputOutputName ) this.IFF.currentForm.inputOutputName = []; | ||
break; | ||
case 'FNAM': | ||
this.IFF.currentForm.fileName = this.IFF.reader.getString(); | ||
break; | ||
case 'CHAN': | ||
@@ -298,4 +273,4 @@ // NOTE: ENVL Forms may also have CHAN chunk, however ENVL is currently ignored | ||
break; | ||
// LWO2 Spec chunks: these are needed since the SURF FORMs are often in LWO2 format | ||
case 'SMAN': | ||
@@ -305,4 +280,4 @@ const maxSmoothingAngle = this.IFF.reader.getFloat32(); | ||
break; | ||
// LWO2: Basic Surface Parameters | ||
case 'COLR': | ||
@@ -313,5 +288,3 @@ this.IFF.currentSurface.attributes.Color = { | ||
this.IFF.reader.skip( 2 ); // VX: envelope | ||
break; | ||
case 'LUMI': | ||
@@ -323,3 +296,2 @@ this.IFF.currentSurface.attributes.Luminosity = { | ||
break; | ||
case 'SPEC': | ||
@@ -331,3 +303,2 @@ this.IFF.currentSurface.attributes.Specular = { | ||
break; | ||
case 'DIFF': | ||
@@ -339,3 +310,2 @@ this.IFF.currentSurface.attributes.Diffuse = { | ||
break; | ||
case 'REFL': | ||
@@ -347,3 +317,2 @@ this.IFF.currentSurface.attributes.Reflection = { | ||
break; | ||
case 'GLOS': | ||
@@ -355,3 +324,2 @@ this.IFF.currentSurface.attributes.Glossiness = { | ||
break; | ||
case 'TRAN': | ||
@@ -361,3 +329,2 @@ this.IFF.currentSurface.attributes.opacity = this.IFF.reader.getFloat32(); | ||
break; | ||
case 'BUMP': | ||
@@ -367,11 +334,8 @@ this.IFF.currentSurface.attributes.bumpStrength = this.IFF.reader.getFloat32(); | ||
break; | ||
case 'SIDE': | ||
this.IFF.currentSurface.attributes.side = this.IFF.reader.getUint16(); | ||
break; | ||
case 'RIMG': | ||
this.IFF.currentSurface.attributes.reflectionMap = this.IFF.reader.getVariableLengthIndex(); | ||
break; | ||
case 'RIND': | ||
@@ -381,11 +345,8 @@ this.IFF.currentSurface.attributes.refractiveIndex = this.IFF.reader.getFloat32(); | ||
break; | ||
case 'TIMG': | ||
this.IFF.currentSurface.attributes.refractionMap = this.IFF.reader.getVariableLengthIndex(); | ||
break; | ||
case 'IMAP': | ||
this.IFF.currentSurface.attributes.imageMapIndex = this.IFF.reader.getUint32(); | ||
break; | ||
case 'IUVI': | ||
@@ -395,3 +356,2 @@ // uv channel name | ||
break; | ||
case 'IUTL': | ||
@@ -401,3 +361,2 @@ // widthWrappingMode: 0 = Reset, 1 = Repeat, 2 = Mirror, 3 = Edge | ||
break; | ||
case 'IVTL': | ||
@@ -407,3 +366,2 @@ // heightWrappingMode | ||
break; | ||
default: | ||
@@ -410,0 +368,0 @@ this.IFF.parseUnknownCHUNK( blockID, length ); |
@@ -15,5 +15,3 @@ ( function () { | ||
**/ | ||
let _lwoTree; | ||
class LWOLoader extends THREE.Loader { | ||
@@ -27,8 +25,8 @@ | ||
} | ||
load( url, onLoad, onProgress, onError ) { | ||
const scope = this; | ||
const path = scope.path === '' ? extractParentUrl( url, 'Objects' ) : scope.path; // give the mesh a default name based on the filename | ||
const path = scope.path === '' ? extractParentUrl( url, 'Objects' ) : scope.path; | ||
// give the mesh a default name based on the filename | ||
const modelName = url.split( path ).pop().split( '.' )[ 0 ]; | ||
@@ -41,2 +39,3 @@ const loader = new THREE.FileLoader( this.manager ); | ||
// console.time( 'Total parsing: ' ); | ||
try { | ||
@@ -60,12 +59,15 @@ | ||
} // console.timeEnd( 'Total parsing: ' ); | ||
} | ||
// console.timeEnd( 'Total parsing: ' ); | ||
}, onProgress, onError ); | ||
} | ||
parse( iffBuffer, path, modelName ) { | ||
_lwoTree = new THREE.IFFParser().parse( iffBuffer ); // console.log( 'lwoTree', lwoTree ); | ||
_lwoTree = new THREE.IFFParser().parse( iffBuffer ); | ||
// console.log( 'lwoTree', lwoTree ); | ||
const textureLoader = new THREE.TextureLoader( this.manager ).setPath( this.resourcePath || path ).setCrossOrigin( this.crossOrigin ); | ||
@@ -76,5 +78,5 @@ return new LWOTreeParser( textureLoader ).parse( modelName ); | ||
} // Parse the lwoTree object | ||
} | ||
// Parse the lwoTree object | ||
class LWOTreeParser { | ||
@@ -87,3 +89,2 @@ | ||
} | ||
parse( modelName ) { | ||
@@ -100,12 +101,11 @@ | ||
} | ||
parseLayers() { | ||
// array of all meshes for building hierarchy | ||
const meshes = []; // final array containing meshes with scene graph hierarchy set up | ||
const meshes = []; | ||
// final array containing meshes with scene graph hierarchy set up | ||
const finalMeshes = []; | ||
const geometryParser = new GeometryParser(); | ||
const scope = this; | ||
_lwoTree.layers.forEach( function ( layer ) { | ||
@@ -119,3 +119,2 @@ | ||
} ); | ||
this.applyPivots( finalMeshes ); | ||
@@ -125,3 +124,2 @@ return finalMeshes; | ||
} | ||
parseMesh( geometry, layer ) { | ||
@@ -137,5 +135,5 @@ | ||
} // TODO: may need to be reversed in z to convert LWO to three.js coordinates | ||
} | ||
// TODO: may need to be reversed in z to convert LWO to three.js coordinates | ||
applyPivots( meshes ) { | ||
@@ -151,3 +149,2 @@ | ||
child.position.z += pivot[ 2 ]; | ||
if ( child.parent ) { | ||
@@ -167,3 +164,2 @@ | ||
} | ||
getMaterials( namesArray, type ) { | ||
@@ -177,4 +173,5 @@ | ||
} ); // convert materials to line or point mats if required | ||
} ); | ||
// convert materials to line or point mats if required | ||
if ( type === 'points' || type === 'lines' ) { | ||
@@ -187,3 +184,2 @@ | ||
}; | ||
if ( type === 'points' ) { | ||
@@ -203,5 +199,5 @@ | ||
} // if there is only one material, return that directly instead of array | ||
} | ||
// if there is only one material, return that directly instead of array | ||
const filtered = materials.filter( Boolean ); | ||
@@ -212,3 +208,2 @@ if ( filtered.length === 1 ) return filtered[ 0 ]; | ||
} | ||
getMaterialByName( name ) { | ||
@@ -222,9 +217,8 @@ | ||
} // If the material has an aoMap, duplicate UVs | ||
} | ||
// If the material has an aoMap, duplicate UVs | ||
duplicateUVs( geometry, materials ) { | ||
let duplicateUVs = false; | ||
if ( ! Array.isArray( materials ) ) { | ||
@@ -250,3 +244,2 @@ | ||
} | ||
class MaterialParser { | ||
@@ -259,3 +252,2 @@ | ||
} | ||
parse() { | ||
@@ -265,3 +257,2 @@ | ||
this.textures = {}; | ||
for ( const name in _lwoTree.materials ) { | ||
@@ -284,3 +275,2 @@ | ||
} | ||
parseMaterial( materialData, name, textures ) { | ||
@@ -306,7 +296,4 @@ | ||
} | ||
parseMaterialLwo2( materialData, name /*, textures*/ ) { | ||
parseMaterialLwo2( materialData, name | ||
/*, textures*/ | ||
) { | ||
let params = { | ||
@@ -321,11 +308,10 @@ name: name, | ||
} // Note: converting from left to right handed coords by switching x -> -x in vertices, and | ||
} | ||
// Note: converting from left to right handed coords by switching x -> -x in vertices, and | ||
// then switching mat THREE.FrontSide -> THREE.BackSide | ||
// NB: this means that THREE.FrontSide and THREE.BackSide have been switched! | ||
getSide( attributes ) { | ||
if ( ! attributes.side ) return THREE.BackSide; | ||
switch ( attributes.side ) { | ||
@@ -336,6 +322,4 @@ | ||
return THREE.BackSide; | ||
case 2: | ||
return THREE.FrontSide; | ||
case 3: | ||
@@ -347,3 +331,2 @@ return THREE.DoubleSide; | ||
} | ||
getSmooth( attributes ) { | ||
@@ -355,3 +338,2 @@ | ||
} | ||
parseConnections( connections, nodes ) { | ||
@@ -390,3 +372,2 @@ | ||
} | ||
getNodeByRefName( refName, nodes ) { | ||
@@ -401,7 +382,5 @@ | ||
} | ||
parseTextureNodes( textureNodes ) { | ||
const maps = {}; | ||
for ( const name in textureNodes ) { | ||
@@ -415,3 +394,2 @@ | ||
if ( node.heightWrappingMode !== undefined ) texture.wrapT = this.getWrappingType( node.heightWrappingMode ); | ||
switch ( name ) { | ||
@@ -422,3 +400,2 @@ | ||
break; | ||
case 'Roughness': | ||
@@ -428,3 +405,2 @@ maps.roughnessMap = texture; | ||
break; | ||
case 'Specular': | ||
@@ -434,3 +410,2 @@ maps.specularMap = texture; | ||
break; | ||
case 'Luminous': | ||
@@ -440,7 +415,5 @@ maps.emissiveMap = texture; | ||
break; | ||
case 'Luminous THREE.Color': | ||
maps.emissive = 0x808080; | ||
break; | ||
case 'Metallic': | ||
@@ -450,3 +423,2 @@ maps.metalnessMap = texture; | ||
break; | ||
case 'Transparency': | ||
@@ -457,3 +429,2 @@ case 'Alpha': | ||
break; | ||
case 'Normal': | ||
@@ -463,3 +434,2 @@ maps.normalMap = texture; | ||
break; | ||
case 'Bump': | ||
@@ -471,12 +441,12 @@ maps.bumpMap = texture; | ||
} // LWO BSDF materials can have both spec and rough, but this is not valid in three | ||
} | ||
// LWO BSDF materials can have both spec and rough, but this is not valid in three | ||
if ( maps.roughnessMap && maps.specularMap ) delete maps.specularMap; | ||
return maps; | ||
} // maps can also be defined on individual material attributes, parse those here | ||
} | ||
// maps can also be defined on individual material attributes, parse those here | ||
// This occurs on Standard (Phong) surfaces | ||
parseAttributeImageMaps( attributes, textures, maps ) { | ||
@@ -487,3 +457,2 @@ | ||
const attribute = attributes[ name ]; | ||
if ( attribute.maps ) { | ||
@@ -497,3 +466,2 @@ | ||
if ( mapData.wrap !== undefined ) texture.wrapT = this.getWrappingType( mapData.wrap.h ); | ||
switch ( name ) { | ||
@@ -504,7 +472,5 @@ | ||
break; | ||
case 'Diffuse': | ||
maps.aoMap = texture; | ||
break; | ||
case 'Roughness': | ||
@@ -514,3 +480,2 @@ maps.roughnessMap = texture; | ||
break; | ||
case 'Specular': | ||
@@ -520,3 +485,2 @@ maps.specularMap = texture; | ||
break; | ||
case 'Luminosity': | ||
@@ -526,3 +490,2 @@ maps.emissiveMap = texture; | ||
break; | ||
case 'Metallic': | ||
@@ -532,3 +495,2 @@ maps.metalnessMap = texture; | ||
break; | ||
case 'Transparency': | ||
@@ -539,7 +501,5 @@ case 'Alpha': | ||
break; | ||
case 'Normal': | ||
maps.normalMap = texture; | ||
break; | ||
case 'Bump': | ||
@@ -556,7 +516,7 @@ maps.bumpMap = texture; | ||
} | ||
parseAttributes( attributes, maps ) { | ||
const params = {}; // don't use color data if color map is present | ||
const params = {}; | ||
// don't use color data if color map is present | ||
if ( attributes.Color && ! maps.map ) { | ||
@@ -567,3 +527,2 @@ | ||
} else params.color = new THREE.Color(); | ||
if ( attributes.Transparency && attributes.Transparency.value !== 0 ) { | ||
@@ -583,11 +542,7 @@ | ||
} | ||
parsePhysicalAttributes( params, attributes /*, maps*/ ) { | ||
parsePhysicalAttributes( params, attributes | ||
/*, maps*/ | ||
) { | ||
if ( attributes.Clearcoat && attributes.Clearcoat.value > 0 ) { | ||
params.clearcoat = attributes.Clearcoat.value; | ||
if ( attributes[ 'Clearcoat Gloss' ] ) { | ||
@@ -602,3 +557,2 @@ | ||
} | ||
parseStandardAttributes( params, attributes, maps ) { | ||
@@ -609,3 +563,2 @@ | ||
params.emissiveIntensity = attributes.Luminous.value; | ||
if ( attributes[ 'Luminous THREE.Color' ] && ! maps.emissive ) { | ||
@@ -627,3 +580,2 @@ | ||
} | ||
parsePhongAttributes( params, attributes, maps ) { | ||
@@ -633,3 +585,2 @@ | ||
if ( attributes.Diffuse ) params.color.multiplyScalar( attributes.Diffuse.value ); | ||
if ( attributes.Reflection ) { | ||
@@ -645,3 +596,2 @@ | ||
params.emissiveIntensity = attributes.Luminosity.value; | ||
if ( ! maps.emissiveMap && ! maps.map ) { | ||
@@ -657,5 +607,5 @@ | ||
} // parse specular if there is no roughness - we will interpret the material as 'Phong' in this case | ||
} | ||
// parse specular if there is no roughness - we will interpret the material as 'Phong' in this case | ||
if ( ! attributes.Roughness && attributes.Specular && ! maps.specularMap ) { | ||
@@ -678,3 +628,2 @@ | ||
} | ||
parseEnvMap( connections, maps, attributes ) { | ||
@@ -685,7 +634,7 @@ | ||
const envMap = this.loadTexture( connections.envMap ); | ||
if ( attributes.transparent && attributes.opacity < 0.999 ) { | ||
envMap.mapping = THREE.EquirectangularRefractionMapping; // Reflectivity and refraction mapping don't work well together in Phong materials | ||
envMap.mapping = THREE.EquirectangularRefractionMapping; | ||
// Reflectivity and refraction mapping don't work well together in Phong materials | ||
if ( attributes.reflectivity !== undefined ) { | ||
@@ -707,3 +656,2 @@ | ||
} else envMap.mapping = THREE.EquirectangularReflectionMapping; | ||
maps.envMap = envMap; | ||
@@ -713,5 +661,5 @@ | ||
} // get texture defined at top level by its index | ||
} | ||
// get texture defined at top level by its index | ||
getTexturePathByIndex( index ) { | ||
@@ -721,3 +669,2 @@ | ||
if ( ! _lwoTree.textures ) return fileName; | ||
_lwoTree.textures.forEach( function ( texture ) { | ||
@@ -728,7 +675,5 @@ | ||
} ); | ||
return fileName; | ||
} | ||
loadTexture( path ) { | ||
@@ -744,5 +689,5 @@ | ||
} // 0 = Reset, 1 = Repeat, 2 = Mirror, 3 = Edge | ||
} | ||
// 0 = Reset, 1 = Repeat, 2 = Mirror, 3 = Edge | ||
getWrappingType( num ) { | ||
@@ -755,9 +700,6 @@ | ||
return THREE.ClampToEdgeWrapping; | ||
case 1: | ||
return THREE.RepeatWrapping; | ||
case 2: | ||
return THREE.MirroredRepeatWrapping; | ||
case 3: | ||
@@ -769,3 +711,2 @@ return THREE.ClampToEdgeWrapping; | ||
} | ||
getMaterialType( nodeData ) { | ||
@@ -780,3 +721,2 @@ | ||
} | ||
class GeometryParser { | ||
@@ -793,5 +733,8 @@ | ||
this.parseUVs( geometry, layer, indices ); | ||
this.parseMorphTargets( geometry, layer, indices ); // TODO: z may need to be reversed to account for coordinate system change | ||
this.parseMorphTargets( geometry, layer, indices ); | ||
geometry.translate( - layer.pivot[ 0 ], - layer.pivot[ 1 ], - layer.pivot[ 2 ] ); // let userData = geometry.userData; | ||
// TODO: z may need to be reversed to account for coordinate system change | ||
geometry.translate( - layer.pivot[ 0 ], - layer.pivot[ 1 ], - layer.pivot[ 2 ] ); | ||
// let userData = geometry.userData; | ||
// geometry = geometry.toNonIndexed() | ||
@@ -802,5 +745,5 @@ // geometry.userData = userData; | ||
} // split quads into tris | ||
} | ||
// split quads into tris | ||
splitIndices( indices, polygonDimensions ) { | ||
@@ -837,5 +780,5 @@ | ||
} // NOTE: currently ignoring poly indices and assuming that they are intelligently ordered | ||
} | ||
// NOTE: currently ignoring poly indices and assuming that they are intelligently ordered | ||
parseGroups( geometry, geoData ) { | ||
@@ -850,3 +793,2 @@ | ||
let indexNum = 0; // create new indices in numerical order | ||
const indexPairs = {}; // original indices mapped to numerical indices | ||
@@ -858,3 +800,2 @@ | ||
let currentCount = 0; | ||
for ( let i = 0; i < remappedIndices.length; i += 2 ) { | ||
@@ -865,7 +806,5 @@ | ||
if ( prevMaterialIndex === undefined ) prevMaterialIndex = materialIndex; | ||
if ( materialIndex !== prevMaterialIndex ) { | ||
let currentIndex; | ||
if ( indexPairs[ tags[ prevMaterialIndex ] ] ) { | ||
@@ -893,9 +832,8 @@ | ||
} // the loop above doesn't add the last group, do that here. | ||
} | ||
// the loop above doesn't add the last group, do that here. | ||
if ( geometry.groups.length > 0 ) { | ||
let currentIndex; | ||
if ( indexPairs[ tags[ materialIndex ] ] ) { | ||
@@ -915,9 +853,8 @@ | ||
} // Mat names from TAGS chunk, used to build up an array of materials for this geometry | ||
} | ||
// Mat names from TAGS chunk, used to build up an array of materials for this geometry | ||
geometry.userData.matNames = matNames; | ||
} | ||
splitMaterialIndices( polygonDimensions, indices ) { | ||
@@ -950,3 +887,5 @@ | ||
} // UV maps: | ||
} | ||
// UV maps: | ||
// 1: are defined via index into an array of points, not into a geometry | ||
@@ -960,4 +899,2 @@ // - the geometry is also defined by an index into this array, but the indexes may not match | ||
// VMADs are currently not supported | ||
parseUVs( geometry, layer ) { | ||
@@ -971,3 +908,2 @@ | ||
} ); | ||
for ( const name in layer.uvs ) { | ||
@@ -989,7 +925,5 @@ | ||
} | ||
parseMorphTargets( geometry, layer ) { | ||
let num = 0; | ||
for ( const name in layer.morphTargets ) { | ||
@@ -1029,4 +963,5 @@ | ||
} // ************** UTILITY FUNCTIONS ************** | ||
} | ||
// ************** UTILITY FUNCTIONS ************** | ||
@@ -1033,0 +968,0 @@ function extractParentUrl( url, dir ) { |
( function () { | ||
const _normalData = [[ - 0.525731, 0.000000, 0.850651 ], [ - 0.442863, 0.238856, 0.864188 ], [ - 0.295242, 0.000000, 0.955423 ], [ - 0.309017, 0.500000, 0.809017 ], [ - 0.162460, 0.262866, 0.951056 ], [ 0.000000, 0.000000, 1.000000 ], [ 0.000000, 0.850651, 0.525731 ], [ - 0.147621, 0.716567, 0.681718 ], [ 0.147621, 0.716567, 0.681718 ], [ 0.000000, 0.525731, 0.850651 ], [ 0.309017, 0.500000, 0.809017 ], [ 0.525731, 0.000000, 0.850651 ], [ 0.295242, 0.000000, 0.955423 ], [ 0.442863, 0.238856, 0.864188 ], [ 0.162460, 0.262866, 0.951056 ], [ - 0.681718, 0.147621, 0.716567 ], [ - 0.809017, 0.309017, 0.500000 ], [ - 0.587785, 0.425325, 0.688191 ], [ - 0.850651, 0.525731, 0.000000 ], [ - 0.864188, 0.442863, 0.238856 ], [ - 0.716567, 0.681718, 0.147621 ], [ - 0.688191, 0.587785, 0.425325 ], [ - 0.500000, 0.809017, 0.309017 ], [ - 0.238856, 0.864188, 0.442863 ], [ - 0.425325, 0.688191, 0.587785 ], [ - 0.716567, 0.681718, - 0.147621 ], [ - 0.500000, 0.809017, - 0.309017 ], [ - 0.525731, 0.850651, 0.000000 ], [ 0.000000, 0.850651, - 0.525731 ], [ - 0.238856, 0.864188, - 0.442863 ], [ 0.000000, 0.955423, - 0.295242 ], [ - 0.262866, 0.951056, - 0.162460 ], [ 0.000000, 1.000000, 0.000000 ], [ 0.000000, 0.955423, 0.295242 ], [ - 0.262866, 0.951056, 0.162460 ], [ 0.238856, 0.864188, 0.442863 ], [ 0.262866, 0.951056, 0.162460 ], [ 0.500000, 0.809017, 0.309017 ], [ 0.238856, 0.864188, - 0.442863 ], [ 0.262866, 0.951056, - 0.162460 ], [ 0.500000, 0.809017, - 0.309017 ], [ 0.850651, 0.525731, 0.000000 ], [ 0.716567, 0.681718, 0.147621 ], [ 0.716567, 0.681718, - 0.147621 ], [ 0.525731, 0.850651, 0.000000 ], [ 0.425325, 0.688191, 0.587785 ], [ 0.864188, 0.442863, 0.238856 ], [ 0.688191, 0.587785, 0.425325 ], [ 0.809017, 0.309017, 0.500000 ], [ 0.681718, 0.147621, 0.716567 ], [ 0.587785, 0.425325, 0.688191 ], [ 0.955423, 0.295242, 0.000000 ], [ 1.000000, 0.000000, 0.000000 ], [ 0.951056, 0.162460, 0.262866 ], [ 0.850651, - 0.525731, 0.000000 ], [ 0.955423, - 0.295242, 0.000000 ], [ 0.864188, - 0.442863, 0.238856 ], [ 0.951056, - 0.162460, 0.262866 ], [ 0.809017, - 0.309017, 0.500000 ], [ 0.681718, - 0.147621, 0.716567 ], [ 0.850651, 0.000000, 0.525731 ], [ 0.864188, 0.442863, - 0.238856 ], [ 0.809017, 0.309017, - 0.500000 ], [ 0.951056, 0.162460, - 0.262866 ], [ 0.525731, 0.000000, - 0.850651 ], [ 0.681718, 0.147621, - 0.716567 ], [ 0.681718, - 0.147621, - 0.716567 ], [ 0.850651, 0.000000, - 0.525731 ], [ 0.809017, - 0.309017, - 0.500000 ], [ 0.864188, - 0.442863, - 0.238856 ], [ 0.951056, - 0.162460, - 0.262866 ], [ 0.147621, 0.716567, - 0.681718 ], [ 0.309017, 0.500000, - 0.809017 ], [ 0.425325, 0.688191, - 0.587785 ], [ 0.442863, 0.238856, - 0.864188 ], [ 0.587785, 0.425325, - 0.688191 ], [ 0.688191, 0.587785, - 0.425325 ], [ - 0.147621, 0.716567, - 0.681718 ], [ - 0.309017, 0.500000, - 0.809017 ], [ 0.000000, 0.525731, - 0.850651 ], [ - 0.525731, 0.000000, - 0.850651 ], [ - 0.442863, 0.238856, - 0.864188 ], [ - 0.295242, 0.000000, - 0.955423 ], [ - 0.162460, 0.262866, - 0.951056 ], [ 0.000000, 0.000000, - 1.000000 ], [ 0.295242, 0.000000, - 0.955423 ], [ 0.162460, 0.262866, - 0.951056 ], [ - 0.442863, - 0.238856, - 0.864188 ], [ - 0.309017, - 0.500000, - 0.809017 ], [ - 0.162460, - 0.262866, - 0.951056 ], [ 0.000000, - 0.850651, - 0.525731 ], [ - 0.147621, - 0.716567, - 0.681718 ], [ 0.147621, - 0.716567, - 0.681718 ], [ 0.000000, - 0.525731, - 0.850651 ], [ 0.309017, - 0.500000, - 0.809017 ], [ 0.442863, - 0.238856, - 0.864188 ], [ 0.162460, - 0.262866, - 0.951056 ], [ 0.238856, - 0.864188, - 0.442863 ], [ 0.500000, - 0.809017, - 0.309017 ], [ 0.425325, - 0.688191, - 0.587785 ], [ 0.716567, - 0.681718, - 0.147621 ], [ 0.688191, - 0.587785, - 0.425325 ], [ 0.587785, - 0.425325, - 0.688191 ], [ 0.000000, - 0.955423, - 0.295242 ], [ 0.000000, - 1.000000, 0.000000 ], [ 0.262866, - 0.951056, - 0.162460 ], [ 0.000000, - 0.850651, 0.525731 ], [ 0.000000, - 0.955423, 0.295242 ], [ 0.238856, - 0.864188, 0.442863 ], [ 0.262866, - 0.951056, 0.162460 ], [ 0.500000, - 0.809017, 0.309017 ], [ 0.716567, - 0.681718, 0.147621 ], [ 0.525731, - 0.850651, 0.000000 ], [ - 0.238856, - 0.864188, - 0.442863 ], [ - 0.500000, - 0.809017, - 0.309017 ], [ - 0.262866, - 0.951056, - 0.162460 ], [ - 0.850651, - 0.525731, 0.000000 ], [ - 0.716567, - 0.681718, - 0.147621 ], [ - 0.716567, - 0.681718, 0.147621 ], [ - 0.525731, - 0.850651, 0.000000 ], [ - 0.500000, - 0.809017, 0.309017 ], [ - 0.238856, - 0.864188, 0.442863 ], [ - 0.262866, - 0.951056, 0.162460 ], [ - 0.864188, - 0.442863, 0.238856 ], [ - 0.809017, - 0.309017, 0.500000 ], [ - 0.688191, - 0.587785, 0.425325 ], [ - 0.681718, - 0.147621, 0.716567 ], [ - 0.442863, - 0.238856, 0.864188 ], [ - 0.587785, - 0.425325, 0.688191 ], [ - 0.309017, - 0.500000, 0.809017 ], [ - 0.147621, - 0.716567, 0.681718 ], [ - 0.425325, - 0.688191, 0.587785 ], [ - 0.162460, - 0.262866, 0.951056 ], [ 0.442863, - 0.238856, 0.864188 ], [ 0.162460, - 0.262866, 0.951056 ], [ 0.309017, - 0.500000, 0.809017 ], [ 0.147621, - 0.716567, 0.681718 ], [ 0.000000, - 0.525731, 0.850651 ], [ 0.425325, - 0.688191, 0.587785 ], [ 0.587785, - 0.425325, 0.688191 ], [ 0.688191, - 0.587785, 0.425325 ], [ - 0.955423, 0.295242, 0.000000 ], [ - 0.951056, 0.162460, 0.262866 ], [ - 1.000000, 0.000000, 0.000000 ], [ - 0.850651, 0.000000, 0.525731 ], [ - 0.955423, - 0.295242, 0.000000 ], [ - 0.951056, - 0.162460, 0.262866 ], [ - 0.864188, 0.442863, - 0.238856 ], [ - 0.951056, 0.162460, - 0.262866 ], [ - 0.809017, 0.309017, - 0.500000 ], [ - 0.864188, - 0.442863, - 0.238856 ], [ - 0.951056, - 0.162460, - 0.262866 ], [ - 0.809017, - 0.309017, - 0.500000 ], [ - 0.681718, 0.147621, - 0.716567 ], [ - 0.681718, - 0.147621, - 0.716567 ], [ - 0.850651, 0.000000, - 0.525731 ], [ - 0.688191, 0.587785, - 0.425325 ], [ - 0.587785, 0.425325, - 0.688191 ], [ - 0.425325, 0.688191, - 0.587785 ], [ - 0.425325, - 0.688191, - 0.587785 ], [ - 0.587785, - 0.425325, - 0.688191 ], [ - 0.688191, - 0.587785, - 0.425325 ]]; | ||
class MD2Loader extends THREE.Loader { | ||
@@ -12,3 +11,2 @@ | ||
} | ||
load( url, onLoad, onProgress, onError ) { | ||
@@ -47,10 +45,10 @@ | ||
} | ||
parse( buffer ) { | ||
const data = new DataView( buffer ); // http://tfc.duke.free.fr/coding/md2-specs-en.html | ||
const data = new DataView( buffer ); | ||
// http://tfc.duke.free.fr/coding/md2-specs-en.html | ||
const header = {}; | ||
const headerNames = [ 'ident', 'version', 'skinwidth', 'skinheight', 'framesize', 'num_skins', 'num_vertices', 'num_st', 'num_tris', 'num_glcmds', 'num_frames', 'offset_skins', 'offset_st', 'offset_tris', 'offset_frames', 'offset_glcmds', 'offset_end' ]; | ||
for ( let i = 0; i < headerNames.length; i ++ ) { | ||
@@ -74,10 +72,12 @@ | ||
} // | ||
} | ||
// | ||
const geometry = new THREE.BufferGeometry(); // uvs | ||
const geometry = new THREE.BufferGeometry(); | ||
// uvs | ||
const uvsTemp = []; | ||
let offset = header.offset_st; | ||
for ( let i = 0, l = header.num_st; i < l; i ++ ) { | ||
@@ -90,4 +90,5 @@ | ||
} // triangles | ||
} | ||
// triangles | ||
@@ -97,3 +98,2 @@ offset = header.offset_tris; | ||
const uvIndices = []; | ||
for ( let i = 0, l = header.num_tris; i < l; i ++ ) { | ||
@@ -105,4 +105,5 @@ | ||
} // frames | ||
} | ||
// frames | ||
@@ -113,3 +114,2 @@ const translation = new THREE.Vector3(); | ||
offset = header.offset_frames; | ||
for ( let i = 0, l = header.num_frames; i < l; i ++ ) { | ||
@@ -121,3 +121,2 @@ | ||
const string = []; | ||
for ( let j = 0; j < 16; j ++ ) { | ||
@@ -137,3 +136,2 @@ | ||
offset += 16; | ||
for ( let j = 0; j < header.num_vertices; j ++ ) { | ||
@@ -144,5 +142,3 @@ | ||
let z = data.getUint8( offset ++ ); | ||
const n = _normalData[ data.getUint8( offset ++ ) ]; | ||
x = x * scale.x + translation.x; | ||
@@ -152,3 +148,2 @@ y = y * scale.y + translation.y; | ||
frame.vertices.push( x, z, y ); // convert to Y-up | ||
frame.normals.push( n[ 0 ], n[ 2 ], n[ 1 ] ); // convert to Y-up | ||
@@ -160,4 +155,5 @@ | ||
} // static | ||
} | ||
// static | ||
@@ -169,18 +165,23 @@ const positions = []; | ||
const normalsTemp = frames[ 0 ].normals; | ||
for ( let i = 0, l = vertexIndices.length; i < l; i ++ ) { | ||
const vertexIndex = vertexIndices[ i ]; | ||
let stride = vertexIndex * 3; // | ||
let stride = vertexIndex * 3; | ||
// | ||
const x = verticesTemp[ stride ]; | ||
const y = verticesTemp[ stride + 1 ]; | ||
const z = verticesTemp[ stride + 2 ]; | ||
positions.push( x, y, z ); // | ||
positions.push( x, y, z ); | ||
// | ||
const nx = normalsTemp[ stride ]; | ||
const ny = normalsTemp[ stride + 1 ]; | ||
const nz = normalsTemp[ stride + 2 ]; | ||
normals.push( nx, ny, nz ); // | ||
normals.push( nx, ny, nz ); | ||
// | ||
const uvIndex = uvIndices[ i ]; | ||
@@ -196,7 +197,8 @@ stride = uvIndex * 2; | ||
geometry.setAttribute( 'normal', new THREE.Float32BufferAttribute( normals, 3 ) ); | ||
geometry.setAttribute( 'uv', new THREE.Float32BufferAttribute( uvs, 2 ) ); // animation | ||
geometry.setAttribute( 'uv', new THREE.Float32BufferAttribute( uvs, 2 ) ); | ||
// animation | ||
const morphPositions = []; | ||
const morphNormals = []; | ||
for ( let i = 0, l = frames.length; i < l; i ++ ) { | ||
@@ -206,7 +208,5 @@ | ||
const attributeName = frame.name; | ||
if ( frame.vertices.length > 0 ) { | ||
const positions = []; | ||
for ( let j = 0, jl = vertexIndices.length; j < jl; j ++ ) { | ||
@@ -232,3 +232,2 @@ | ||
const normals = []; | ||
for ( let j = 0, jl = vertexIndices.length; j < jl; j ++ ) { | ||
@@ -235,0 +234,0 @@ |
@@ -14,3 +14,2 @@ ( function () { | ||
*/ | ||
class MDDLoader extends THREE.Loader { | ||
@@ -23,3 +22,2 @@ | ||
} | ||
load( url, onLoad, onProgress, onError ) { | ||
@@ -38,3 +36,2 @@ | ||
} | ||
parse( data ) { | ||
@@ -45,7 +42,8 @@ | ||
const totalPoints = view.getUint32( 4 ); | ||
let offset = 8; // animation clip | ||
let offset = 8; | ||
// animation clip | ||
const times = new Float32Array( totalFrames ); | ||
const values = new Float32Array( totalFrames * totalFrames ).fill( 0 ); | ||
for ( let i = 0; i < totalFrames; i ++ ) { | ||
@@ -60,10 +58,10 @@ | ||
const track = new THREE.NumberKeyframeTrack( '.morphTargetInfluences', times, values ); | ||
const clip = new THREE.AnimationClip( 'default', times[ times.length - 1 ], [ track ] ); // morph targets | ||
const clip = new THREE.AnimationClip( 'default', times[ times.length - 1 ], [ track ] ); | ||
// morph targets | ||
const morphTargets = []; | ||
for ( let i = 0; i < totalFrames; i ++ ) { | ||
const morphTarget = new Float32Array( totalPoints * 3 ); | ||
for ( let j = 0; j < totalPoints; j ++ ) { | ||
@@ -74,6 +72,4 @@ | ||
offset += 4; // x | ||
morphTarget[ stride + 1 ] = view.getFloat32( offset ); | ||
offset += 4; // y | ||
morphTarget[ stride + 2 ] = view.getFloat32( offset ); | ||
@@ -80,0 +76,0 @@ offset += 4; // z |
@@ -35,3 +35,2 @@ ( function () { | ||
*/ | ||
class MMDLoader extends THREE.Loader { | ||
@@ -44,3 +43,2 @@ | ||
this.parser = null; // lazy generation | ||
this.meshBuilder = new MeshBuilder( this.manager ); | ||
@@ -50,2 +48,3 @@ this.animationBuilder = new AnimationBuilder(); | ||
} | ||
/** | ||
@@ -55,4 +54,2 @@ * @param {string} animationPath | ||
*/ | ||
setAnimationPath( animationPath ) { | ||
@@ -63,4 +60,6 @@ | ||
} // Load MMD assets as Three.js Object | ||
} | ||
// Load MMD assets as Three.js Object | ||
/** | ||
@@ -74,10 +73,9 @@ * Loads Model file (.pmd or .pmx) as a THREE.SkinnedMesh. | ||
*/ | ||
load( url, onLoad, onProgress, onError ) { | ||
const builder = this.meshBuilder.setCrossOrigin( this.crossOrigin ); | ||
load( url, onLoad, onProgress, onError ) { | ||
// resource path | ||
const builder = this.meshBuilder.setCrossOrigin( this.crossOrigin ); // resource path | ||
let resourcePath; | ||
if ( this.resourcePath !== '' ) { | ||
@@ -97,5 +95,5 @@ | ||
const modelExtension = this._extractExtension( url ).toLowerCase(); // Should I detect by seeing header? | ||
const modelExtension = this._extractExtension( url ).toLowerCase(); | ||
// Should I detect by seeing header? | ||
if ( modelExtension !== 'pmd' && modelExtension !== 'pmx' ) { | ||
@@ -115,2 +113,3 @@ | ||
} | ||
/** | ||
@@ -126,4 +125,2 @@ * Loads Motion file(s) (.vmd) as a THREE.AnimationClip. | ||
*/ | ||
loadAnimation( url, object, onLoad, onProgress, onError ) { | ||
@@ -139,2 +136,3 @@ | ||
} | ||
/** | ||
@@ -151,4 +149,2 @@ * Loads mode file and motion file(s) as an object containing | ||
*/ | ||
loadWithAnimation( modelUrl, vmdUrl, onLoad, onProgress, onError ) { | ||
@@ -170,4 +166,6 @@ | ||
} // Load MMD assets as Object data parsed by MMDParser | ||
} | ||
// Load MMD assets as Object data parsed by MMDParser | ||
/** | ||
@@ -181,8 +179,5 @@ * Loads .pmd file as an Object. | ||
*/ | ||
loadPMD( url, onLoad, onProgress, onError ) { | ||
const parser = this._getParser(); | ||
this.loader.setMimeType( undefined ).setPath( this.path ).setResponseType( 'arraybuffer' ).setRequestHeader( this.requestHeader ).setWithCredentials( this.withCredentials ).load( url, function ( buffer ) { | ||
@@ -195,2 +190,3 @@ | ||
} | ||
/** | ||
@@ -204,8 +200,5 @@ * Loads .pmx file as an Object. | ||
*/ | ||
loadPMX( url, onLoad, onProgress, onError ) { | ||
const parser = this._getParser(); | ||
this.loader.setMimeType( undefined ).setPath( this.path ).setResponseType( 'arraybuffer' ).setRequestHeader( this.requestHeader ).setWithCredentials( this.withCredentials ).load( url, function ( buffer ) { | ||
@@ -218,2 +211,3 @@ | ||
} | ||
/** | ||
@@ -228,4 +222,2 @@ * Loads .vmd file as an Object. If two or more files are specified | ||
*/ | ||
loadVMD( url, onLoad, onProgress, onError ) { | ||
@@ -236,7 +228,4 @@ | ||
const vmdNum = urls.length; | ||
const parser = this._getParser(); | ||
this.loader.setMimeType( undefined ).setPath( this.animationPath ).setResponseType( 'arraybuffer' ).setRequestHeader( this.requestHeader ).setWithCredentials( this.withCredentials ); | ||
for ( let i = 0, il = urls.length; i < il; i ++ ) { | ||
@@ -254,2 +243,3 @@ | ||
} | ||
/** | ||
@@ -264,8 +254,5 @@ * Loads .vpd file as an Object. | ||
*/ | ||
loadVPD( url, isUnicode, onLoad, onProgress, onError ) { | ||
const parser = this._getParser(); | ||
this.loader.setMimeType( isUnicode ? undefined : 'text/plain; charset=shift_jis' ).setPath( this.animationPath ).setResponseType( 'text' ).setRequestHeader( this.requestHeader ).setWithCredentials( this.withCredentials ).load( url, function ( text ) { | ||
@@ -277,4 +264,5 @@ | ||
} // private methods | ||
} | ||
// private methods | ||
@@ -287,3 +275,2 @@ _extractExtension( url ) { | ||
} | ||
_getParser() { | ||
@@ -307,4 +294,6 @@ | ||
} // Utilities | ||
} | ||
// Utilities | ||
/* | ||
@@ -314,11 +303,10 @@ * base64 encoded defalut toon textures toon00.bmp - toon10.bmp. | ||
*/ | ||
const DEFAULT_TOON_TEXTURES = [ 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAL0lEQVRYR+3QQREAAAzCsOFfNJPBJ1XQS9r2hsUAAQIECBAgQIAAAQIECBAgsBZ4MUx/ofm2I/kAAAAASUVORK5CYII=', 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAN0lEQVRYR+3WQREAMBACsZ5/bWiiMvgEBTt5cW37hjsBBAgQIECAwFwgyfYPCCBAgAABAgTWAh8aBHZBl14e8wAAAABJRU5ErkJggg==', 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAOUlEQVRYR+3WMREAMAwDsYY/yoDI7MLwIiP40+RJklfcCCBAgAABAgTqArfb/QMCCBAgQIAAgbbAB3z/e0F3js2cAAAAAElFTkSuQmCC', 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAN0lEQVRYR+3WQREAMBACsZ5/B5ilMvgEBTt5cW37hjsBBAgQIECAwFwgyfYPCCBAgAABAgTWAh81dWyx0gFwKAAAAABJRU5ErkJggg==', 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAOklEQVRYR+3WoREAMAwDsWb/UQtCy9wxTOQJ/oQ8SXKKGwEECBAgQIBAXeDt7f4BAQQIECBAgEBb4AOz8Hzx7WLY4wAAAABJRU5ErkJggg==', 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAABPUlEQVRYR+1XwW7CMAy1+f9fZOMysSEOEweEOPRNdm3HbdOyIhAcklPrOs/PLy9RygBALxzcCDQFmgJNgaZAU6Ap0BR4PwX8gsRMVLssMRH5HcpzJEaWL7EVg9F1IHRlyqQohgVr4FGUlUcMJSjcUlDw0zvjeun70cLWmneoyf7NgBTQSniBTQQSuJAZsOnnaczjIMb5hCiuHKxokCrJfVnrctyZL0PkJAJe1HMil4nxeyi3Ypfn1kX51jpPvo/JeCNC4PhVdHdJw2XjBR8brF8PEIhNVn12AgP7uHsTBguBn53MUZCqv7Lp07Pn5k1Ro+uWmUNn7D+M57rtk7aG0Vo73xyF/fbFf0bPJjDXngnGocDTdFhygZjwUQrMNrDcmZlQT50VJ/g/UwNyHpu778+yW+/ksOz/BFo54P4AsUXMfRq7XWsAAAAASUVORK5CYII=', 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAACMElEQVRYR+2Xv4pTQRTGf2dubhLdICiii2KnYKHVolhauKWPoGAnNr6BD6CvIVaihYuI2i1ia0BY0MZGRHQXjZj/mSPnnskfNWiWZUlzJ5k7M2cm833nO5Mziej2DWWJRUoCpQKlAntSQCqgw39/iUWAGmh37jrRnVsKlgpiqmkoGVABA7E57fvY+pJDdgKqF6HzFCSADkDq+F6AHABtQ+UMVE5D7zXod7fFNhTEckTbj5XQgHzNN+5tQvc5NG7C6BNkp6D3EmpXHDR+dQAjFLchW3VS9rlw3JBh+B7ys5Cf9z0GW1C/7P32AyBAOAz1q4jGliIH3YPuBnSfQX4OGreTIgEYQb/pBDtPnEQ4CivXYPAWBk13oHrB54yA9QuSn2H4AcKRpEILDt0BUzj+RLR1V5EqjD66NPRBVpLcQwjHoHYJOhsQv6U4mnzmrIXJCFr4LDwm/xBUoboG9XX4cc9VKdYoSA2yk5NQLJaKDUjTBoveG3Z2TElTxwjNK4M3LEZgUdDdruvcXzKBpStgp2NPiWi3ks9ZXxIoFVi+AvHLdc9TqtjL3/aYjpPlrzOcEnK62Szhimdd7xX232zFDTgtxezOu3WNMRLjiKgjtOhHVMd1loynVHvOgjuIIJMaELEqhJAV/RCSLbWTcfPFakFgFlALTRRvx+ok6Hlp/Q+v3fmx90bMyUzaEAhmM3KvHlXTL5DxnbGf/1M8RNNACLL5MNtPxP/mypJAqcDSFfgFhpYqWUzhTEAAAAAASUVORK5CYII=', 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAL0lEQVRYR+3QQREAAAzCsOFfNJPBJ1XQS9r2hsUAAQIECBAgQIAAAQIECBAgsBZ4MUx/ofm2I/kAAAAASUVORK5CYII=', 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAL0lEQVRYR+3QQREAAAzCsOFfNJPBJ1XQS9r2hsUAAQIECBAgQIAAAQIECBAgsBZ4MUx/ofm2I/kAAAAASUVORK5CYII=', 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAL0lEQVRYR+3QQREAAAzCsOFfNJPBJ1XQS9r2hsUAAQIECBAgQIAAAQIECBAgsBZ4MUx/ofm2I/kAAAAASUVORK5CYII=', 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAL0lEQVRYR+3QQREAAAzCsOFfNJPBJ1XQS9r2hsUAAQIECBAgQIAAAQIECBAgsBZ4MUx/ofm2I/kAAAAASUVORK5CYII=' ]; | ||
const NON_ALPHA_CHANNEL_FORMATS = [ THREE.RGB_S3TC_DXT1_Format, THREE.RGB_PVRTC_4BPPV1_Format, THREE.RGB_PVRTC_2BPPV1_Format, THREE.RGB_ETC1_Format, THREE.RGB_ETC2_Format ]; | ||
// Builders. They build Three.js object from Object data parsed by MMDParser. | ||
const DEFAULT_TOON_TEXTURES = [ 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAL0lEQVRYR+3QQREAAAzCsOFfNJPBJ1XQS9r2hsUAAQIECBAgQIAAAQIECBAgsBZ4MUx/ofm2I/kAAAAASUVORK5CYII=', 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAN0lEQVRYR+3WQREAMBACsZ5/bWiiMvgEBTt5cW37hjsBBAgQIECAwFwgyfYPCCBAgAABAgTWAh8aBHZBl14e8wAAAABJRU5ErkJggg==', 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAOUlEQVRYR+3WMREAMAwDsYY/yoDI7MLwIiP40+RJklfcCCBAgAABAgTqArfb/QMCCBAgQIAAgbbAB3z/e0F3js2cAAAAAElFTkSuQmCC', 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAN0lEQVRYR+3WQREAMBACsZ5/B5ilMvgEBTt5cW37hjsBBAgQIECAwFwgyfYPCCBAgAABAgTWAh81dWyx0gFwKAAAAABJRU5ErkJggg==', 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAOklEQVRYR+3WoREAMAwDsWb/UQtCy9wxTOQJ/oQ8SXKKGwEECBAgQIBAXeDt7f4BAQQIECBAgEBb4AOz8Hzx7WLY4wAAAABJRU5ErkJggg==', 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAABPUlEQVRYR+1XwW7CMAy1+f9fZOMysSEOEweEOPRNdm3HbdOyIhAcklPrOs/PLy9RygBALxzcCDQFmgJNgaZAU6Ap0BR4PwX8gsRMVLssMRH5HcpzJEaWL7EVg9F1IHRlyqQohgVr4FGUlUcMJSjcUlDw0zvjeun70cLWmneoyf7NgBTQSniBTQQSuJAZsOnnaczjIMb5hCiuHKxokCrJfVnrctyZL0PkJAJe1HMil4nxeyi3Ypfn1kX51jpPvo/JeCNC4PhVdHdJw2XjBR8brF8PEIhNVn12AgP7uHsTBguBn53MUZCqv7Lp07Pn5k1Ro+uWmUNn7D+M57rtk7aG0Vo73xyF/fbFf0bPJjDXngnGocDTdFhygZjwUQrMNrDcmZlQT50VJ/g/UwNyHpu778+yW+/ksOz/BFo54P4AsUXMfRq7XWsAAAAASUVORK5CYII=', 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAACMElEQVRYR+2Xv4pTQRTGf2dubhLdICiii2KnYKHVolhauKWPoGAnNr6BD6CvIVaihYuI2i1ia0BY0MZGRHQXjZj/mSPnnskfNWiWZUlzJ5k7M2cm833nO5Mziej2DWWJRUoCpQKlAntSQCqgw39/iUWAGmh37jrRnVsKlgpiqmkoGVABA7E57fvY+pJDdgKqF6HzFCSADkDq+F6AHABtQ+UMVE5D7zXod7fFNhTEckTbj5XQgHzNN+5tQvc5NG7C6BNkp6D3EmpXHDR+dQAjFLchW3VS9rlw3JBh+B7ys5Cf9z0GW1C/7P32AyBAOAz1q4jGliIH3YPuBnSfQX4OGreTIgEYQb/pBDtPnEQ4CivXYPAWBk13oHrB54yA9QuSn2H4AcKRpEILDt0BUzj+RLR1V5EqjD66NPRBVpLcQwjHoHYJOhsQv6U4mnzmrIXJCFr4LDwm/xBUoboG9XX4cc9VKdYoSA2yk5NQLJaKDUjTBoveG3Z2TElTxwjNK4M3LEZgUdDdruvcXzKBpStgp2NPiWi3ks9ZXxIoFVi+AvHLdc9TqtjL3/aYjpPlrzOcEnK62Szhimdd7xX232zFDTgtxezOu3WNMRLjiKgjtOhHVMd1loynVHvOgjuIIJMaELEqhJAV/RCSLbWTcfPFakFgFlALTRRvx+ok6Hlp/Q+v3fmx90bMyUzaEAhmM3KvHlXTL5DxnbGf/1M8RNNACLL5MNtPxP/mypJAqcDSFfgFhpYqWUzhTEAAAAAASUVORK5CYII=', 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAL0lEQVRYR+3QQREAAAzCsOFfNJPBJ1XQS9r2hsUAAQIECBAgQIAAAQIECBAgsBZ4MUx/ofm2I/kAAAAASUVORK5CYII=', 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAL0lEQVRYR+3QQREAAAzCsOFfNJPBJ1XQS9r2hsUAAQIECBAgQIAAAQIECBAgsBZ4MUx/ofm2I/kAAAAASUVORK5CYII=', 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAL0lEQVRYR+3QQREAAAzCsOFfNJPBJ1XQS9r2hsUAAQIECBAgQIAAAQIECBAgsBZ4MUx/ofm2I/kAAAAASUVORK5CYII=', 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAL0lEQVRYR+3QQREAAAzCsOFfNJPBJ1XQS9r2hsUAAQIECBAgQIAAAQIECBAgsBZ4MUx/ofm2I/kAAAAASUVORK5CYII=' ]; | ||
const NON_ALPHA_CHANNEL_FORMATS = [ THREE.RGB_S3TC_DXT1_Format, THREE.RGB_PVRTC_4BPPV1_Format, THREE.RGB_PVRTC_2BPPV1_Format, THREE.RGB_ETC1_Format, THREE.RGB_ETC2_Format ]; // Builders. They build Three.js object from Object data parsed by MMDParser. | ||
/** | ||
* @param {THREE.LoadingManager} manager | ||
*/ | ||
class MeshBuilder { | ||
@@ -333,2 +321,3 @@ | ||
} | ||
/** | ||
@@ -338,4 +327,2 @@ * @param {string} crossOrigin | ||
*/ | ||
setCrossOrigin( crossOrigin ) { | ||
@@ -347,2 +334,3 @@ | ||
} | ||
/** | ||
@@ -355,4 +343,2 @@ * @param {Object} data - parsed PMD/PMX data | ||
*/ | ||
build( data, resourcePath, onProgress, onError ) { | ||
@@ -364,4 +350,6 @@ | ||
const skeleton = new THREE.Skeleton( initBones( mesh ) ); | ||
mesh.bind( skeleton ); // console.log( mesh ); // for console debug | ||
mesh.bind( skeleton ); | ||
// console.log( mesh ); // for console debug | ||
return mesh; | ||
@@ -371,4 +359,5 @@ | ||
} // TODO: Try to remove this function | ||
} | ||
// TODO: Try to remove this function | ||
@@ -379,13 +368,17 @@ function initBones( mesh ) { | ||
const bones = []; | ||
if ( geometry && geometry.bones !== undefined ) { | ||
// first, create array of 'Bone' objects from geometry data | ||
for ( let i = 0, il = geometry.bones.length; i < il; i ++ ) { | ||
const gbone = geometry.bones[ i ]; // create new 'Bone' object | ||
const gbone = geometry.bones[ i ]; | ||
// create new 'Bone' object | ||
const bone = new THREE.Bone(); | ||
bones.push( bone ); // apply values | ||
bones.push( bone ); | ||
// apply values | ||
bone.name = gbone.name; | ||
@@ -396,4 +389,5 @@ bone.position.fromArray( gbone.pos ); | ||
} // second, create bone hierarchy | ||
} | ||
// second, create bone hierarchy | ||
@@ -403,6 +397,6 @@ for ( let i = 0, il = geometry.bones.length; i < il; i ++ ) { | ||
const gbone = geometry.bones[ i ]; | ||
if ( gbone.parent !== - 1 && gbone.parent !== null && bones[ gbone.parent ] !== undefined ) { | ||
// subsequent bones in the hierarchy | ||
bones[ gbone.parent ].add( bones[ i ] ); | ||
@@ -413,2 +407,3 @@ | ||
// topmost bone, immediate child of the skinned mesh | ||
mesh.add( bones[ i ] ); | ||
@@ -420,11 +415,13 @@ | ||
} // now the bones are part of the scene graph and children of the skinned mesh. | ||
} | ||
// now the bones are part of the scene graph and children of the skinned mesh. | ||
// let's update the corresponding matrices | ||
mesh.updateMatrixWorld( true ); | ||
return bones; | ||
} // | ||
} | ||
// | ||
@@ -453,11 +450,13 @@ class GeometryBuilder { | ||
const rigidBodies = []; | ||
const constraints = []; // for work | ||
const constraints = []; | ||
// for work | ||
let offset = 0; | ||
const boneTypeTable = {}; // positions, normals, uvs, skinIndices, skinWeights | ||
const boneTypeTable = {}; | ||
// positions, normals, uvs, skinIndices, skinWeights | ||
for ( let i = 0; i < data.metadata.vertexCount; i ++ ) { | ||
const v = data.vertices[ i ]; | ||
for ( let j = 0, jl = v.position.length; j < jl; j ++ ) { | ||
@@ -493,4 +492,5 @@ | ||
} // indices | ||
} | ||
// indices | ||
@@ -500,3 +500,2 @@ for ( let i = 0; i < data.metadata.faceCount; i ++ ) { | ||
const face = data.faces[ i ]; | ||
for ( let j = 0, jl = face.indices.length; j < jl; j ++ ) { | ||
@@ -508,4 +507,5 @@ | ||
} // groups | ||
} | ||
// groups | ||
@@ -521,4 +521,5 @@ for ( let i = 0; i < data.metadata.materialCount; i ++ ) { | ||
} // bones | ||
} | ||
// bones | ||
@@ -528,4 +529,5 @@ for ( let i = 0; i < data.metadata.rigidBodyCount; i ++ ) { | ||
const body = data.rigidBodies[ i ]; | ||
let value = boneTypeTable[ body.boneIndex ]; // keeps greater number if already value is set without any special reasons | ||
let value = boneTypeTable[ body.boneIndex ]; | ||
// keeps greater number if already value is set without any special reasons | ||
value = value === undefined ? body.type : Math.max( body.type, value ); | ||
@@ -549,3 +551,2 @@ boneTypeTable[ body.boneIndex ] = value; | ||
}; | ||
if ( bone.parent !== - 1 ) { | ||
@@ -561,6 +562,7 @@ | ||
} // iks | ||
// TODO: remove duplicated codes between PMD and PMX | ||
} | ||
// iks | ||
// TODO: remove duplicated codes between PMD and PMX | ||
if ( data.metadata.format === 'pmd' ) { | ||
@@ -578,3 +580,2 @@ | ||
}; | ||
for ( let j = 0, jl = ik.links.length; j < jl; j ++ ) { | ||
@@ -585,3 +586,2 @@ | ||
link.enabled = true; | ||
if ( data.bones[ link.index ].name.indexOf( 'ひざ' ) >= 0 ) { | ||
@@ -614,3 +614,2 @@ | ||
}; | ||
for ( let j = 0, jl = ik.links.length; j < jl; j ++ ) { | ||
@@ -621,3 +620,2 @@ | ||
link.enabled = true; | ||
if ( ik.links[ j ].angleLimitation === 1 ) { | ||
@@ -627,4 +625,7 @@ | ||
// link.limitation = new THREE.Vector3( 1.0, 0.0, 0.0 ); | ||
const rotationMin = ik.links[ j ].lowerLimitationAngle; | ||
const rotationMax = ik.links[ j ].upperLimitationAngle; // Convert Left to Right coordinate by myself because | ||
const rotationMax = ik.links[ j ].upperLimitationAngle; | ||
// Convert Left to Right coordinate by myself because | ||
// MMDParser doesn't convert. It's a MMDParser's bug | ||
@@ -647,5 +648,6 @@ | ||
iks.push( param ); // Save the reference even from bone data for efficiently | ||
iks.push( param ); | ||
// Save the reference even from bone data for efficiently | ||
// simulating PMX animation system | ||
bones[ i ].ik = param; | ||
@@ -655,4 +657,5 @@ | ||
} // grants | ||
} | ||
// grants | ||
@@ -663,3 +666,2 @@ if ( data.metadata.format === 'pmx' ) { | ||
const grantEntryMap = {}; | ||
for ( let i = 0; i < data.metadata.boneCount; i ++ ) { | ||
@@ -693,4 +695,6 @@ | ||
visited: false | ||
}; // Build a tree representing grant hierarchy | ||
}; | ||
// Build a tree representing grant hierarchy | ||
for ( const boneIndex in grantEntryMap ) { | ||
@@ -703,7 +707,8 @@ | ||
} // Sort grant parameters from parents to children because | ||
} | ||
// Sort grant parameters from parents to children because | ||
// grant uses parent's transform that parent's grant is already applied | ||
// so grant should be applied in order from parents to children | ||
function traverse( entry ) { | ||
@@ -713,5 +718,6 @@ | ||
grants.push( entry.param ); // Save the reference even from bone data for efficiently | ||
grants.push( entry.param ); | ||
// Save the reference even from bone data for efficiently | ||
// simulating PMX animation system | ||
bones[ entry.param.index ].grant = entry.param; | ||
@@ -722,7 +728,7 @@ | ||
entry.visited = true; | ||
for ( let i = 0, il = entry.children.length; i < il; i ++ ) { | ||
const child = entry.children[ i ]; // Cut off a loop if exists. (Is a grant loop invalid?) | ||
const child = entry.children[ i ]; | ||
// Cut off a loop if exists. (Is a grant loop invalid?) | ||
if ( ! child.visited ) traverse( child ); | ||
@@ -736,4 +742,5 @@ | ||
} // morph | ||
} | ||
// morph | ||
@@ -746,3 +753,2 @@ function updateAttributes( attribute, morph, ratio ) { | ||
let index; | ||
if ( data.metadata.format === 'pmd' ) { | ||
@@ -774,3 +780,2 @@ | ||
attribute.name = morph.name; | ||
for ( let j = 0; j < data.metadata.vertexCount * 3; j ++ ) { | ||
@@ -795,2 +800,3 @@ | ||
// group | ||
for ( let j = 0; j < morph.elementCount; j ++ ) { | ||
@@ -800,3 +806,2 @@ | ||
const ratio = morph.elements[ j ].ratio; | ||
if ( morph2.type === 1 ) { | ||
@@ -806,3 +811,5 @@ | ||
} else { // TODO: implement | ||
} else { | ||
// TODO: implement | ||
} | ||
@@ -815,17 +822,25 @@ | ||
// vertex | ||
updateAttributes( attribute, morph, 1.0 ); | ||
} else if ( morph.type === 2 ) { // bone | ||
// TODO: implement | ||
} else if ( morph.type === 3 ) { // uv | ||
// TODO: implement | ||
} else if ( morph.type === 4 ) { // additional uv1 | ||
// TODO: implement | ||
} else if ( morph.type === 5 ) { // additional uv2 | ||
// TODO: implement | ||
} else if ( morph.type === 6 ) { // additional uv3 | ||
// TODO: implement | ||
} else if ( morph.type === 7 ) { // additional uv4 | ||
// TODO: implement | ||
} else if ( morph.type === 8 ) { // material | ||
// TODO: implement | ||
@@ -839,4 +854,5 @@ } | ||
} // rigid bodies from rigidBodies field. | ||
} | ||
// rigid bodies from rigidBodies field. | ||
@@ -847,3 +863,2 @@ for ( let i = 0; i < data.metadata.rigidBodyCount; i ++ ) { | ||
const params = {}; | ||
for ( const key in rigidBody ) { | ||
@@ -854,2 +869,3 @@ | ||
} | ||
/* | ||
@@ -860,4 +876,2 @@ * RigidBody position parameter in PMX seems global position | ||
*/ | ||
if ( data.metadata.format === 'pmx' ) { | ||
@@ -878,4 +892,5 @@ | ||
} // constraints from constraints field. | ||
} | ||
// constraints from constraints field. | ||
@@ -886,3 +901,2 @@ for ( let i = 0; i < data.metadata.constraintCount; i ++ ) { | ||
const params = {}; | ||
for ( const key in constraint ) { | ||
@@ -895,4 +909,5 @@ | ||
const bodyA = rigidBodies[ params.rigidBodyIndex1 ]; | ||
const bodyB = rigidBodies[ params.rigidBodyIndex2 ]; // Refer to http://www20.atpages.jp/katwat/wp/?p=4135 | ||
const bodyB = rigidBodies[ params.rigidBodyIndex2 ]; | ||
// Refer to http://www20.atpages.jp/katwat/wp/?p=4135 | ||
if ( bodyA.type !== 0 && bodyB.type === 2 ) { | ||
@@ -910,4 +925,5 @@ | ||
} // build THREE.BufferGeometry. | ||
} | ||
// build THREE.BufferGeometry. | ||
@@ -921,3 +937,2 @@ const geometry = new THREE.BufferGeometry(); | ||
geometry.setIndex( indices ); | ||
for ( let i = 0, il = groups.length; i < il; i ++ ) { | ||
@@ -946,9 +961,9 @@ | ||
} // | ||
} | ||
// | ||
/** | ||
* @param {THREE.LoadingManager} manager | ||
*/ | ||
class MaterialBuilder { | ||
@@ -966,2 +981,3 @@ | ||
} | ||
/** | ||
@@ -971,4 +987,2 @@ * @param {string} crossOrigin | ||
*/ | ||
setCrossOrigin( crossOrigin ) { | ||
@@ -980,2 +994,3 @@ | ||
} | ||
/** | ||
@@ -985,4 +1000,2 @@ * @param {string} resourcePath | ||
*/ | ||
setResourcePath( resourcePath ) { | ||
@@ -994,2 +1007,3 @@ | ||
} | ||
/** | ||
@@ -1002,12 +1016,10 @@ * @param {Object} data - parsed PMD/PMX data | ||
*/ | ||
build( data, geometry /*, onProgress, onError */ ) { | ||
build( data, geometry | ||
/*, onProgress, onError */ | ||
) { | ||
const materials = []; | ||
const textures = {}; | ||
this.textureLoader.setCrossOrigin( this.crossOrigin ); // materials | ||
this.textureLoader.setCrossOrigin( this.crossOrigin ); | ||
// materials | ||
for ( let i = 0; i < data.metadata.materialCount; i ++ ) { | ||
@@ -1022,2 +1034,3 @@ | ||
if ( material.name !== undefined ) params.name = material.name; | ||
/* | ||
@@ -1033,3 +1046,2 @@ * THREE.Color | ||
*/ | ||
params.diffuse = new THREE.Color().fromArray( material.diffuse ); | ||
@@ -1040,6 +1052,10 @@ params.opacity = material.diffuse[ 3 ]; | ||
params.emissive = new THREE.Color().fromArray( material.ambient ); | ||
params.transparent = params.opacity !== 1.0; // | ||
params.transparent = params.opacity !== 1.0; | ||
params.fog = true; // blend | ||
// | ||
params.fog = true; | ||
// blend | ||
params.blending = THREE.CustomBlending; | ||
@@ -1049,4 +1065,6 @@ params.blendSrc = THREE.SrcAlphaFactor; | ||
params.blendSrcAlpha = THREE.SrcAlphaFactor; | ||
params.blendDstAlpha = THREE.DstAlphaFactor; // side | ||
params.blendDstAlpha = THREE.DstAlphaFactor; | ||
// side | ||
if ( data.metadata.format === 'pmx' && ( material.flag & 0x1 ) === 1 ) { | ||
@@ -1065,10 +1083,12 @@ | ||
// map, envMap | ||
if ( material.fileName ) { | ||
const fileName = material.fileName; | ||
const fileNames = fileName.split( '*' ); // fileNames[ 0 ]: mapFileName | ||
const fileNames = fileName.split( '*' ); | ||
// fileNames[ 0 ]: mapFileName | ||
// fileNames[ 1 ]: envMapFileName( optional ) | ||
params.map = this._loadTexture( fileNames[ 0 ], textures ); | ||
if ( fileNames.length > 1 ) { | ||
@@ -1082,4 +1102,5 @@ | ||
} // gradientMap | ||
} | ||
// gradientMap | ||
@@ -1090,4 +1111,6 @@ const toonFileName = material.toonIndex === - 1 ? 'toon00.bmp' : data.toonTextures[ material.toonIndex ].fileName; | ||
isDefaultToonTexture: this._isDefaultToonTexture( toonFileName ) | ||
} ); // parameters for OutlineEffect | ||
} ); | ||
// parameters for OutlineEffect | ||
params.userData.outlineParameters = { | ||
@@ -1103,25 +1126,29 @@ thickness: material.edgeFlag === 1 ? 0.003 : 0.0, | ||
// map | ||
if ( material.textureIndex !== - 1 ) { | ||
params.map = this._loadTexture( data.textures[ material.textureIndex ], textures ); // Since PMX spec don't have standard to list map files except color map and env map, | ||
params.map = this._loadTexture( data.textures[ material.textureIndex ], textures ); | ||
// Since PMX spec don't have standard to list map files except color map and env map, | ||
// we need to save file name for further mapping, like matching normal map file names after model loaded. | ||
// ref: https://gist.github.com/felixjones/f8a06bd48f9da9a4539f#texture | ||
params.userData.MMD.mapFileName = data.textures[ material.textureIndex ]; | ||
} // envMap TODO: support m.envFlag === 3 | ||
} | ||
// envMap TODO: support m.envFlag === 3 | ||
if ( material.envTextureIndex !== - 1 && ( material.envFlag === 1 || material.envFlag == 2 ) ) { | ||
params.matcap = this._loadTexture( data.textures[ material.envTextureIndex ], textures ); // Same as color map above, keep file name in userData for further usage. | ||
params.matcap = this._loadTexture( data.textures[ material.envTextureIndex ], textures ); | ||
// Same as color map above, keep file name in userData for further usage. | ||
params.userData.MMD.matcapFileName = data.textures[ material.envTextureIndex ]; | ||
params.matcapCombine = material.envFlag === 1 ? THREE.MultiplyOperation : THREE.AddOperation; | ||
} // gradientMap | ||
} | ||
// gradientMap | ||
let toonFileName, isDefaultToon; | ||
if ( material.toonIndex === - 1 || material.toonFlag !== 0 ) { | ||
@@ -1142,4 +1169,5 @@ | ||
isDefaultToonTexture: isDefaultToon | ||
} ); // parameters for OutlineEffect | ||
} ); | ||
// parameters for OutlineEffect | ||
params.userData.outlineParameters = { | ||
@@ -1174,2 +1202,3 @@ thickness: material.edgeSize / 300, | ||
// set transparent true if alpha morph is defined. | ||
function checkAlphaMorph( elements, materials ) { | ||
@@ -1182,3 +1211,2 @@ | ||
const material = materials[ element.index ]; | ||
if ( material.opacity !== element.diffuse[ 3 ] ) { | ||
@@ -1198,3 +1226,2 @@ | ||
const elements = morph.elements; | ||
if ( morph.type === 0 ) { | ||
@@ -1222,4 +1249,5 @@ | ||
} // private methods | ||
} | ||
// private methods | ||
@@ -1243,3 +1271,2 @@ _getTGALoader() { | ||
} | ||
_isDefaultToonTexture( name ) { | ||
@@ -1251,3 +1278,2 @@ | ||
} | ||
_loadTexture( filePath, textures, params, onProgress, onError ) { | ||
@@ -1258,7 +1284,5 @@ | ||
let fullPath; | ||
if ( params.isDefaultToonTexture === true ) { | ||
let index; | ||
try { | ||
@@ -1285,3 +1309,2 @@ | ||
let loader = this.manager.getHandler( fullPath ); | ||
if ( loader === null ) { | ||
@@ -1309,3 +1332,2 @@ | ||
t.wrapT = THREE.RepeatWrapping; | ||
for ( let i = 0; i < texture.readyCallbacks.length; i ++ ) { | ||
@@ -1325,3 +1347,2 @@ | ||
} | ||
_getRotatedImage( image ) { | ||
@@ -1338,3 +1359,2 @@ | ||
context.rotate( 0.5 * Math.PI ); // 90.0 * Math.PI / 180.0 | ||
context.translate( - width / 2.0, - height / 2.0 ); | ||
@@ -1344,5 +1364,5 @@ context.drawImage( image, 0, 0 ); | ||
} // Check if the partial image area used by the texture is transparent. | ||
} | ||
// Check if the partial image area used by the texture is transparent. | ||
_checkImageTransparency( map, geometry, groupIndex ) { | ||
@@ -1371,3 +1391,2 @@ | ||
if ( data.length / ( width * height ) !== 4 ) return false; | ||
for ( let i = 0; i < indices.length; i += 3 ) { | ||
@@ -1379,3 +1398,2 @@ | ||
}; | ||
for ( let j = 0; j < 3; j ++ ) { | ||
@@ -1403,2 +1421,3 @@ | ||
} | ||
/* | ||
@@ -1411,4 +1430,2 @@ * This method expects | ||
*/ | ||
function getAlphaByUv( image, uv ) { | ||
@@ -1446,3 +1463,2 @@ | ||
const group = geometry.groups[ groupIndex ]; | ||
if ( detectImageTransparency( imageData, geometry.attributes.uv.array, geometry.index.array.slice( group.start, group.start + group.count ) ) ) { | ||
@@ -1458,4 +1474,5 @@ | ||
} // | ||
} | ||
// | ||
@@ -1472,5 +1489,5 @@ class AnimationBuilder { | ||
// combine skeletal and morph animations | ||
const tracks = this.buildSkeletalAnimation( vmd, mesh ).tracks; | ||
const tracks2 = this.buildMorphAnimation( vmd, mesh ).tracks; | ||
for ( let i = 0, il = tracks2.length; i < il; i ++ ) { | ||
@@ -1485,2 +1502,3 @@ | ||
} | ||
/** | ||
@@ -1491,4 +1509,2 @@ * @param {Object} vmd - parsed VMD data | ||
*/ | ||
buildSkeletalAnimation( vmd, mesh ) { | ||
@@ -1499,7 +1515,4 @@ | ||
array.push( interpolation[ index + 0 ] / 127 ); // x1 | ||
array.push( interpolation[ index + 8 ] / 127 ); // x2 | ||
array.push( interpolation[ index + 4 ] / 127 ); // y1 | ||
array.push( interpolation[ index + 12 ] / 127 ); // y2 | ||
@@ -1513,3 +1526,2 @@ | ||
const boneNameDictionary = {}; | ||
for ( let i = 0, il = bones.length; i < il; i ++ ) { | ||
@@ -1545,3 +1557,2 @@ | ||
const basePosition = mesh.skeleton.getBoneByName( key ).position.toArray(); | ||
for ( let i = 0, il = array.length; i < il; i ++ ) { | ||
@@ -1554,9 +1565,5 @@ | ||
times.push( time ); | ||
for ( let j = 0; j < 3; j ++ ) positions.push( basePosition[ j ] + position[ j ] ); | ||
for ( let j = 0; j < 4; j ++ ) rotations.push( rotation[ j ] ); | ||
for ( let j = 0; j < 3; j ++ ) pushInterpolation( pInterpolations, interpolation, j ); | ||
pushInterpolation( rInterpolations, interpolation, 3 ); | ||
@@ -1575,2 +1582,3 @@ | ||
} | ||
/** | ||
@@ -1581,4 +1589,2 @@ * @param {Object} vmd - parsed VMD data | ||
*/ | ||
buildMorphAnimation( vmd, mesh ) { | ||
@@ -1589,3 +1595,2 @@ | ||
const morphTargetDictionary = mesh.morphTargetDictionary; | ||
for ( let i = 0; i < vmd.metadata.morphCount; i ++ ) { | ||
@@ -1611,3 +1616,2 @@ | ||
const values = []; | ||
for ( let i = 0, il = array.length; i < il; i ++ ) { | ||
@@ -1627,2 +1631,3 @@ | ||
} | ||
/** | ||
@@ -1632,4 +1637,2 @@ * @param {Object} vmd - parsed VMD data | ||
*/ | ||
buildCameraAnimation( vmd ) { | ||
@@ -1657,7 +1660,4 @@ | ||
array.push( interpolation[ index * 4 + 0 ] / 127 ); // x1 | ||
array.push( interpolation[ index * 4 + 1 ] / 127 ); // x2 | ||
array.push( interpolation[ index * 4 + 2 ] / 127 ); // y1 | ||
array.push( interpolation[ index * 4 + 3 ] / 127 ); // y2 | ||
@@ -1686,3 +1686,2 @@ | ||
const center = new THREE.Vector3(); | ||
for ( let i = 0, il = cameras.length; i < il; i ++ ) { | ||
@@ -1708,3 +1707,2 @@ | ||
fovs.push( fov ); | ||
for ( let j = 0; j < 3; j ++ ) { | ||
@@ -1716,4 +1714,5 @@ | ||
pushInterpolation( qInterpolations, interpolation, 3 ); // use the same parameter for x, y, z axis. | ||
pushInterpolation( qInterpolations, interpolation, 3 ); | ||
// use the same parameter for x, y, z axis. | ||
for ( let j = 0; j < 3; j ++ ) { | ||
@@ -1729,4 +1728,5 @@ | ||
const tracks = []; // I expect an object whose name 'target' exists under THREE.Camera | ||
const tracks = []; | ||
// I expect an object whose name 'target' exists under THREE.Camera | ||
tracks.push( this._createTrack( 'target.position', THREE.VectorKeyframeTrack, times, centers, cInterpolations ) ); | ||
@@ -1738,4 +1738,5 @@ tracks.push( this._createTrack( '.quaternion', THREE.QuaternionKeyframeTrack, times, quaternions, qInterpolations ) ); | ||
} // private method | ||
} | ||
// private method | ||
@@ -1757,3 +1758,2 @@ _createTrack( node, typedKeyframeTrack, times, values, interpolations ) { | ||
let index = 1; | ||
for ( let aheadIndex = 2, endIndex = times.length; aheadIndex < endIndex; aheadIndex ++ ) { | ||
@@ -1775,3 +1775,2 @@ | ||
times[ index ] = times[ aheadIndex ]; | ||
for ( let i = 0; i < stride; i ++ ) { | ||
@@ -1800,3 +1799,2 @@ | ||
const track = new typedKeyframeTrack( node, times, values ); | ||
track.createInterpolant = function InterpolantFactoryMethodCubicBezier( result ) { | ||
@@ -1812,4 +1810,5 @@ | ||
} // interpolation | ||
} | ||
// interpolation | ||
@@ -1824,3 +1823,2 @@ class CubicBezierInterpolation extends THREE.Interpolant { | ||
} | ||
interpolate_( i1, t0, t, t1 ) { | ||
@@ -1833,11 +1831,12 @@ | ||
const offset1 = i1 * stride; | ||
const offset0 = offset1 - stride; // No interpolation if next key frame is in one frame in 30fps. | ||
const offset0 = offset1 - stride; | ||
// No interpolation if next key frame is in one frame in 30fps. | ||
// This is from MMD animation spec. | ||
// '1.5' is for precision loss. times are Float32 in Three.js Animation system. | ||
const weight1 = t1 - t0 < 1 / 30 * 1.5 ? 0.0 : ( t - t0 ) / ( t1 - t0 ); | ||
if ( stride === 4 ) { | ||
// THREE.Quaternion | ||
const x1 = params[ i1 * 4 + 0 ]; | ||
@@ -1847,5 +1846,3 @@ const x2 = params[ i1 * 4 + 1 ]; | ||
const y2 = params[ i1 * 4 + 3 ]; | ||
const ratio = this._calculate( x1, x2, y1, y2, weight1 ); | ||
THREE.Quaternion.slerpFlat( result, 0, values, offset0, values, offset1, ratio ); | ||
@@ -1856,2 +1853,3 @@ | ||
// THREE.Vector3 | ||
for ( let i = 0; i !== stride; ++ i ) { | ||
@@ -1863,5 +1861,3 @@ | ||
const y2 = params[ i1 * 12 + i * 4 + 3 ]; | ||
const ratio = this._calculate( x1, x2, y1, y2, weight1 ); | ||
result[ i ] = values[ offset0 + i ] * ( 1 - ratio ) + values[ offset1 + i ] * ratio; | ||
@@ -1874,2 +1870,3 @@ | ||
// Number | ||
const x1 = params[ i1 * 4 + 0 ]; | ||
@@ -1879,5 +1876,3 @@ const x2 = params[ i1 * 4 + 1 ]; | ||
const y2 = params[ i1 * 4 + 3 ]; | ||
const ratio = this._calculate( x1, x2, y1, y2, weight1 ); | ||
result[ 0 ] = values[ offset0 ] * ( 1 - ratio ) + values[ offset1 ] * ratio; | ||
@@ -1890,3 +1885,2 @@ | ||
} | ||
_calculate( x1, x2, y1, y2, x ) { | ||
@@ -1930,2 +1924,3 @@ | ||
*/ | ||
let c = 0.5; | ||
@@ -1938,3 +1933,2 @@ let t = c; | ||
let sst3, stt3, ttt; | ||
for ( let i = 0; i < loop; i ++ ) { | ||
@@ -1958,3 +1952,2 @@ | ||
} | ||
class MMDToonMaterial extends THREE.ShaderMaterial { | ||
@@ -1986,3 +1979,2 @@ | ||
this._matcapCombine = value; | ||
switch ( value ) { | ||
@@ -1994,3 +1986,2 @@ | ||
break; | ||
default: | ||
@@ -2006,6 +1997,6 @@ case THREE.AddOperation: | ||
} ); | ||
this.uniforms = THREE.UniformsUtils.clone( THREE.MMDToonShader.uniforms ); // merged from MeshToon/Phong/MatcapMaterial | ||
this.uniforms = THREE.UniformsUtils.clone( THREE.MMDToonShader.uniforms ); | ||
// merged from MeshToon/Phong/MatcapMaterial | ||
const exposePropertyNames = [ 'specular', 'opacity', 'diffuse', 'map', 'matcap', 'gradientMap', 'lightMap', 'lightMapIntensity', 'aoMap', 'aoMapIntensity', 'emissive', 'emissiveMap', 'bumpMap', 'bumpScale', 'normalMap', 'normalScale', 'displacemantBias', 'displacemantMap', 'displacemantScale', 'specularMap', 'alphaMap', 'envMap', 'reflectivity', 'refractionRatio' ]; | ||
for ( const propertyName of exposePropertyNames ) { | ||
@@ -2026,5 +2017,5 @@ | ||
} // Special path for shininess to handle zero shininess properly | ||
} | ||
// Special path for shininess to handle zero shininess properly | ||
this._shininess = 30; | ||
@@ -2044,2 +2035,3 @@ Object.defineProperty( this, 'shininess', { | ||
} ); | ||
Object.defineProperty( this, 'color', Object.getOwnPropertyDescriptor( this, 'diffuse' ) ); | ||
@@ -2049,3 +2041,2 @@ this.setValues( parameters ); | ||
} | ||
copy( source ) { | ||
@@ -2052,0 +2043,0 @@ |
@@ -14,2 +14,3 @@ ( function () { | ||
} | ||
/** | ||
@@ -28,4 +29,2 @@ * Loads and parses a MTL asset from a URL. | ||
*/ | ||
load( url, onLoad, onProgress, onError ) { | ||
@@ -64,3 +63,2 @@ | ||
} | ||
setMaterialOptions( value ) { | ||
@@ -72,2 +70,3 @@ | ||
} | ||
/** | ||
@@ -84,4 +83,2 @@ * Parses a MTL file. | ||
*/ | ||
parse( text, path ) { | ||
@@ -93,3 +90,2 @@ | ||
const materialsInfo = {}; | ||
for ( let i = 0; i < lines.length; i ++ ) { | ||
@@ -99,3 +95,2 @@ | ||
line = line.trim(); | ||
if ( line.length === 0 || line.charAt( 0 ) === '#' ) { | ||
@@ -113,6 +108,6 @@ | ||
value = value.trim(); | ||
if ( key === 'newmtl' ) { | ||
// New material | ||
info = { | ||
@@ -149,2 +144,3 @@ name: value | ||
} | ||
/** | ||
@@ -165,3 +161,2 @@ * Create a new MTLLoader.MaterialCreator | ||
class MaterialCreator { | ||
@@ -182,3 +177,2 @@ | ||
} | ||
setCrossOrigin( value ) { | ||
@@ -190,3 +184,2 @@ | ||
} | ||
setManager( value ) { | ||
@@ -197,3 +190,2 @@ | ||
} | ||
setMaterials( materialsInfo ) { | ||
@@ -207,3 +199,2 @@ | ||
} | ||
convert( materialsInfo ) { | ||
@@ -213,10 +204,9 @@ | ||
const converted = {}; | ||
for ( const mn in materialsInfo ) { | ||
// Convert materials info into normalized form based on options | ||
const mat = materialsInfo[ mn ]; | ||
const covmat = {}; | ||
converted[ mn ] = covmat; | ||
for ( const prop in mat ) { | ||
@@ -227,3 +217,2 @@ | ||
const lprop = prop.toLowerCase(); | ||
switch ( lprop ) { | ||
@@ -235,2 +224,3 @@ | ||
// Diffuse color (color under white light) using RGB values | ||
if ( this.options && this.options.normalizeRGB ) { | ||
@@ -247,2 +237,3 @@ | ||
// ignore | ||
save = false; | ||
@@ -255,3 +246,2 @@ | ||
break; | ||
default: | ||
@@ -275,3 +265,2 @@ break; | ||
} | ||
preload() { | ||
@@ -286,3 +275,2 @@ | ||
} | ||
getIndex( materialName ) { | ||
@@ -293,7 +281,5 @@ | ||
} | ||
getAsArray() { | ||
let index = 0; | ||
for ( const mn in this.materialsInfo ) { | ||
@@ -310,3 +296,2 @@ | ||
} | ||
create( materialName ) { | ||
@@ -323,6 +308,6 @@ | ||
} | ||
createMaterial_( materialName ) { | ||
// Create material | ||
const scope = this; | ||
@@ -334,7 +319,7 @@ const mat = this.materialsInfo[ materialName ]; | ||
}; | ||
function resolveURL( baseUrl, url ) { | ||
if ( typeof url !== 'string' || url === '' ) return ''; // Absolute URL | ||
if ( typeof url !== 'string' || url === '' ) return ''; | ||
// Absolute URL | ||
if ( /^https?:\/\//i.test( url ) ) return url; | ||
@@ -355,3 +340,2 @@ return baseUrl + url; | ||
map.wrapT = scope.wrap; | ||
if ( mapType === 'map' || mapType === 'emissiveMap' ) { | ||
@@ -372,11 +356,11 @@ | ||
if ( value === '' ) continue; | ||
switch ( prop.toLowerCase() ) { | ||
// Ns is material specular exponent | ||
case 'kd': | ||
// Diffuse color (color under white light) using RGB values | ||
params.color = new THREE.Color().fromArray( value ).convertSRGBToLinear(); | ||
break; | ||
case 'ks': | ||
@@ -386,3 +370,2 @@ // Specular color (color when light is reflected from shiny surface) using RGB values | ||
break; | ||
case 'ke': | ||
@@ -392,43 +375,40 @@ // Emissive using RGB values | ||
break; | ||
case 'map_kd': | ||
// Diffuse texture map | ||
setMapForType( 'map', value ); | ||
break; | ||
case 'map_ks': | ||
// Specular map | ||
setMapForType( 'specularMap', value ); | ||
break; | ||
case 'map_ke': | ||
// Emissive map | ||
setMapForType( 'emissiveMap', value ); | ||
break; | ||
case 'norm': | ||
setMapForType( 'normalMap', value ); | ||
break; | ||
case 'map_bump': | ||
case 'bump': | ||
// Bump texture map | ||
setMapForType( 'bumpMap', value ); | ||
break; | ||
case 'map_d': | ||
// Alpha map | ||
setMapForType( 'alphaMap', value ); | ||
params.transparent = true; | ||
break; | ||
case 'ns': | ||
// The specular exponent (defines the focus of the specular highlight) | ||
// A high exponent results in a tight, concentrated highlight. Ns values normally range from 0 to 1000. | ||
params.shininess = parseFloat( value ); | ||
break; | ||
case 'd': | ||
n = parseFloat( value ); | ||
if ( n < 1 ) { | ||
@@ -442,7 +422,5 @@ | ||
break; | ||
case 'tr': | ||
n = parseFloat( value ); | ||
if ( this.options && this.options.invertTrProperty ) n = 1 - n; | ||
if ( n > 0 ) { | ||
@@ -456,3 +434,2 @@ | ||
break; | ||
default: | ||
@@ -469,3 +446,2 @@ break; | ||
} | ||
getTextureParams( value, matParams ) { | ||
@@ -480,3 +456,2 @@ | ||
pos = items.indexOf( '-bm' ); | ||
if ( pos >= 0 ) { | ||
@@ -490,3 +465,2 @@ | ||
pos = items.indexOf( '-s' ); | ||
if ( pos >= 0 ) { | ||
@@ -500,3 +474,2 @@ | ||
pos = items.indexOf( '-o' ); | ||
if ( pos >= 0 ) { | ||
@@ -513,3 +486,2 @@ | ||
} | ||
loadTexture( url, mapping, onLoad, onProgress, onError ) { | ||
@@ -519,3 +491,2 @@ | ||
let loader = manager.getHandler( url ); | ||
if ( loader === null ) { | ||
@@ -522,0 +493,0 @@ |
@@ -10,3 +10,2 @@ ( function () { | ||
} | ||
load( url, onLoad, onProgress, onError ) { | ||
@@ -45,14 +44,11 @@ | ||
} | ||
parse( data ) { | ||
// this parser is largely inspired from the XTK NRRD parser : https://github.com/xtk/X | ||
let _data = data; | ||
let _dataPointer = 0; | ||
const _nativeLittleEndian = new Int8Array( new Int16Array( [ 1 ] ).buffer )[ 0 ] > 0; | ||
const _littleEndian = true; | ||
const headerObject = {}; | ||
function scan( type, chunks ) { | ||
@@ -68,3 +64,2 @@ | ||
let _array_type = Uint8Array; | ||
switch ( type ) { | ||
@@ -75,3 +70,2 @@ | ||
break; | ||
case 'schar': | ||
@@ -81,3 +75,2 @@ _array_type = Int8Array; | ||
// 2 byte data types | ||
case 'ushort': | ||
@@ -87,3 +80,2 @@ _array_type = Uint16Array; | ||
break; | ||
case 'sshort': | ||
@@ -94,3 +86,2 @@ _array_type = Int16Array; | ||
// 4 byte data types | ||
case 'uint': | ||
@@ -100,3 +91,2 @@ _array_type = Uint32Array; | ||
break; | ||
case 'sint': | ||
@@ -106,3 +96,2 @@ _array_type = Int32Array; | ||
break; | ||
case 'float': | ||
@@ -112,3 +101,2 @@ _array_type = Float32Array; | ||
break; | ||
case 'complex': | ||
@@ -118,3 +106,2 @@ _array_type = Float64Array; | ||
break; | ||
case 'double': | ||
@@ -125,8 +112,8 @@ _array_type = Float64Array; | ||
} // increase the data pointer in-place | ||
} | ||
// increase the data pointer in-place | ||
let _bytes = new _array_type( _data.slice( _dataPointer, _dataPointer += chunks * _chunkSize ) ); | ||
let _bytes = new _array_type( _data.slice( _dataPointer, _dataPointer += chunks * _chunkSize ) ); // if required, flip the endianness of the bytes | ||
// if required, flip the endianness of the bytes | ||
if ( _nativeLittleEndian != _littleEndian ) { | ||
@@ -144,9 +131,10 @@ | ||
} // return the byte array | ||
} | ||
// return the byte array | ||
return _bytes; | ||
} //Flips typed array endianness in-place. Based on https://github.com/kig/DataStream.js/blob/master/DataStream.js. | ||
} | ||
//Flips typed array endianness in-place. Based on https://github.com/kig/DataStream.js/blob/master/DataStream.js. | ||
@@ -156,3 +144,2 @@ function flipEndianness( array, chunkSize ) { | ||
const u8 = new Uint8Array( array.buffer, array.byteOffset, array.byteLength ); | ||
for ( let i = 0; i < array.byteLength; i += chunkSize ) { | ||
@@ -172,15 +159,12 @@ | ||
} //parse the header | ||
} | ||
//parse the header | ||
function parseHeader( header ) { | ||
let data, field, fn, i, l, m, _i, _len; | ||
const lines = header.split( /\r?\n/ ); | ||
for ( _i = 0, _len = lines.length; _i < _len; _i ++ ) { | ||
l = lines[ _i ]; | ||
if ( l.match( /NRRD\d+/ ) ) { | ||
@@ -195,3 +179,2 @@ | ||
fn = _fieldFunctions[ field ]; | ||
if ( fn ) { | ||
@@ -229,4 +212,5 @@ | ||
headerObject.vectors.push( [ 0, 1, 0 ] ); | ||
headerObject.vectors.push( [ 0, 0, 1 ] ); //apply spacing if defined | ||
headerObject.vectors.push( [ 0, 0, 1 ] ); | ||
//apply spacing if defined | ||
if ( headerObject.spacings ) { | ||
@@ -252,5 +236,5 @@ | ||
} //parse the data when registred as one of this type : 'text', 'ascii', 'txt' | ||
} | ||
//parse the data when registred as one of this type : 'text', 'ascii', 'txt' | ||
function parseDataAsText( data, start, end ) { | ||
@@ -261,4 +245,4 @@ | ||
end = end || data.length; | ||
let value; //length of the result is the product of the sizes | ||
let value; | ||
//length of the result is the product of the sizes | ||
const lengthOfTheResult = headerObject.sizes.reduce( function ( previous, current ) { | ||
@@ -270,3 +254,2 @@ | ||
let base = 10; | ||
if ( headerObject.encoding === 'hex' ) { | ||
@@ -281,3 +264,2 @@ | ||
let parsingFunction = parseInt; | ||
if ( headerObject.__array === Float32Array || headerObject.__array === Float64Array ) { | ||
@@ -291,4 +273,4 @@ | ||
value = data[ i ]; //if value is not a space | ||
value = data[ i ]; | ||
//if value is not a space | ||
if ( ( value < 9 || value > 13 ) && value !== 32 ) { | ||
@@ -325,3 +307,2 @@ | ||
const _bytes = scan( 'uchar', data.byteLength ); | ||
const _length = _bytes.length; | ||
@@ -331,3 +312,2 @@ let _header = null; | ||
let i; | ||
for ( i = 1; i < _length; i ++ ) { | ||
@@ -339,4 +319,4 @@ | ||
// now we know what the header is | ||
_header = this.parseChars( _bytes, 0, i - 2 ); // this is were the data starts | ||
_header = this.parseChars( _bytes, 0, i - 2 ); | ||
// this is were the data starts | ||
_data_start = i + 1; | ||
@@ -347,8 +327,7 @@ break; | ||
} // parse the header | ||
} | ||
// parse the header | ||
parseHeader( _header ); | ||
_data = _bytes.subarray( _data_start ); // the data without header | ||
if ( headerObject.encoding.substring( 0, 2 ) === 'gz' ) { | ||
@@ -368,3 +347,2 @@ | ||
const _copy = new Uint8Array( _data.length ); | ||
for ( let i = 0; i < _data.length; i ++ ) { | ||
@@ -378,25 +356,27 @@ | ||
} // .. let's use the underlying array buffer | ||
} | ||
// .. let's use the underlying array buffer | ||
_data = _data.buffer; | ||
const volume = new THREE.Volume(); | ||
volume.header = headerObject; // | ||
volume.header = headerObject; | ||
// | ||
// parse the (unzipped) data to a datastream of the correct type | ||
// | ||
volume.data = new headerObject.__array( _data ); // get the min and max intensities | ||
volume.data = new headerObject.__array( _data ); | ||
// get the min and max intensities | ||
const min_max = volume.computeMinMax(); | ||
const min = min_max[ 0 ]; | ||
const max = min_max[ 1 ]; // attach the scalar range to the volume | ||
const max = min_max[ 1 ]; | ||
// attach the scalar range to the volume | ||
volume.windowLow = min; | ||
volume.windowHigh = max; // get the image dimensions | ||
volume.windowHigh = max; | ||
// get the image dimensions | ||
volume.dimensions = [ headerObject.sizes[ 0 ], headerObject.sizes[ 1 ], headerObject.sizes[ 2 ] ]; | ||
volume.xLength = volume.dimensions[ 0 ]; | ||
volume.yLength = volume.dimensions[ 1 ]; | ||
volume.zLength = volume.dimensions[ 2 ]; // Identify axis order in the space-directions matrix from the header if possible. | ||
volume.zLength = volume.dimensions[ 2 ]; | ||
// Identify axis order in the space-directions matrix from the header if possible. | ||
if ( headerObject.vectors ) { | ||
@@ -417,13 +397,13 @@ | ||
} // spacing | ||
} | ||
// spacing | ||
const spacingX = new THREE.Vector3().fromArray( headerObject.vectors[ 0 ] ).length(); | ||
const spacingY = new THREE.Vector3().fromArray( headerObject.vectors[ 1 ] ).length(); | ||
const spacingZ = new THREE.Vector3().fromArray( headerObject.vectors[ 2 ] ).length(); | ||
volume.spacing = [ spacingX, spacingY, spacingZ ]; // Create IJKtoRAS matrix | ||
volume.spacing = [ spacingX, spacingY, spacingZ ]; | ||
// Create IJKtoRAS matrix | ||
volume.matrix = new THREE.Matrix4(); | ||
const transitionMatrix = new THREE.Matrix4(); | ||
if ( headerObject.space === 'left-posterior-superior' ) { | ||
@@ -454,5 +434,6 @@ | ||
volume.inverseMatrix.copy( volume.matrix ).invert(); | ||
volume.RASDimensions = new THREE.Vector3( volume.xLength, volume.yLength, volume.zLength ).applyMatrix4( volume.matrix ).round().toArray().map( Math.abs ); // .. and set the default threshold | ||
volume.RASDimensions = new THREE.Vector3( volume.xLength, volume.yLength, volume.zLength ).applyMatrix4( volume.matrix ).round().toArray().map( Math.abs ); | ||
// .. and set the default threshold | ||
// only if the threshold was not already set | ||
if ( volume.lowerThreshold === - Infinity ) { | ||
@@ -473,3 +454,2 @@ | ||
} | ||
parseChars( array, start, end ) { | ||
@@ -490,6 +470,5 @@ | ||
let output = ''; // create and append the chars | ||
let output = ''; | ||
// create and append the chars | ||
let i = 0; | ||
for ( i = start; i < end; ++ i ) { | ||
@@ -506,3 +485,2 @@ | ||
} | ||
const _fieldFunctions = { | ||
@@ -519,3 +497,2 @@ type: function ( data ) { | ||
break; | ||
case 'signed char': | ||
@@ -526,3 +503,2 @@ case 'int8': | ||
break; | ||
case 'short': | ||
@@ -536,3 +512,2 @@ case 'short int': | ||
break; | ||
case 'ushort': | ||
@@ -545,3 +520,2 @@ case 'unsigned short': | ||
break; | ||
case 'int': | ||
@@ -553,3 +527,2 @@ case 'signed int': | ||
break; | ||
case 'uint': | ||
@@ -561,11 +534,8 @@ case 'unsigned int': | ||
break; | ||
case 'float': | ||
this.__array = Float32Array; | ||
break; | ||
case 'double': | ||
this.__array = Float64Array; | ||
break; | ||
default: | ||
@@ -600,9 +570,6 @@ throw new Error( 'Unsupported NRRD data type: ' + data ); | ||
const _ref = data.split( /\s+/ ); | ||
const _results = []; | ||
for ( let _i = 0, _len = _ref.length; _i < _len; _i ++ ) { | ||
i = _ref[ _i ]; | ||
_results.push( parseInt( i, 10 ) ); | ||
@@ -634,17 +601,12 @@ | ||
const _results = []; | ||
for ( let _i = 0, _len = parts.length; _i < _len; _i ++ ) { | ||
v = parts[ _i ]; | ||
_results.push( function () { | ||
const _ref = v.slice( 1, - 1 ).split( /,/ ); | ||
const _results2 = []; | ||
for ( let _j = 0, _len2 = _ref.length; _j < _len2; _j ++ ) { | ||
f = _ref[ _j ]; | ||
_results2.push( parseFloat( f ) ); | ||
@@ -672,7 +634,5 @@ | ||
const _results = []; | ||
for ( let _i = 0, _len = parts.length; _i < _len; _i ++ ) { | ||
f = parts[ _i ]; | ||
_results.push( parseFloat( f ) ); | ||
@@ -679,0 +639,0 @@ |
( function () { | ||
const _object_pattern = /^[og]\s*(.+)?/; // mtllib file_reference | ||
const _material_library_pattern = /^mtllib /; // usemtl material_name | ||
const _material_use_pattern = /^usemtl /; // usemap map_name | ||
// o object_name | g group_name | ||
const _object_pattern = /^[og]\s*(.+)?/; | ||
// mtllib file_reference | ||
const _material_library_pattern = /^mtllib /; | ||
// usemtl material_name | ||
const _material_use_pattern = /^usemtl /; | ||
// usemap map_name | ||
const _map_use_pattern = /^usemap /; | ||
const _face_vertex_data_separator_pattern = /\s+/; | ||
const _vA = new THREE.Vector3(); | ||
const _vB = new THREE.Vector3(); | ||
const _vC = new THREE.Vector3(); | ||
const _ab = new THREE.Vector3(); | ||
const _cb = new THREE.Vector3(); | ||
const _color = new THREE.Color(); | ||
function ParserState() { | ||
@@ -48,3 +42,2 @@ | ||
const previousMaterial = this.object && typeof this.object.currentMaterial === 'function' ? this.object.currentMaterial() : undefined; | ||
if ( this.object && typeof this.object._finalize === 'function' ) { | ||
@@ -70,6 +63,6 @@ | ||
const previous = this._finalize( false ); // New usemtl declaration overwrites an inherited material, except if faces were declared | ||
const previous = this._finalize( false ); | ||
// New usemtl declaration overwrites an inherited material, except if faces were declared | ||
// after the material, then it must be preserved for proper MultiMaterial continuation. | ||
if ( previous && ( previous.inherited || previous.groupCount <= 0 ) ) { | ||
@@ -125,3 +118,2 @@ | ||
const lastMultiMaterial = this.currentMaterial(); | ||
if ( lastMultiMaterial && lastMultiMaterial.groupEnd === - 1 ) { | ||
@@ -133,5 +125,5 @@ | ||
} // Ignore objects tail materials if no face declarations followed them before a new o/g started. | ||
} | ||
// Ignore objects tail materials if no face declarations followed them before a new o/g started. | ||
if ( end && this.materials.length > 1 ) { | ||
@@ -149,5 +141,5 @@ | ||
} // Guarantee at least one empty material, this makes the creation later more straight forward. | ||
} | ||
// Guarantee at least one empty material, this makes the creation later more straight forward. | ||
if ( end && this.materials.length === 0 ) { | ||
@@ -165,3 +157,5 @@ | ||
} | ||
}; // Inherit previous objects material. | ||
}; | ||
// Inherit previous objects material. | ||
// Spec tells us that a declared material must be set to all objects until a new material is declared. | ||
@@ -246,17 +240,9 @@ // If a usemtl declaration is encountered while this new object is being parsed, it will | ||
const dst = this.object.geometry.normals; | ||
_vA.fromArray( src, a ); | ||
_vB.fromArray( src, b ); | ||
_vC.fromArray( src, c ); | ||
_cb.subVectors( _vC, _vB ); | ||
_ab.subVectors( _vA, _vB ); | ||
_cb.cross( _ab ); | ||
_cb.normalize(); | ||
dst.push( _cb.x, _cb.y, _cb.z ); | ||
@@ -307,4 +293,6 @@ dst.push( _cb.x, _cb.y, _cb.z ); | ||
this.addVertex( ia, ib, ic ); | ||
this.addColor( ia, ib, ic ); // normals | ||
this.addColor( ia, ib, ic ); | ||
// normals | ||
if ( na !== undefined && na !== '' ) { | ||
@@ -322,4 +310,5 @@ | ||
} // uvs | ||
} | ||
// uvs | ||
@@ -338,2 +327,3 @@ if ( ua !== undefined && ua !== '' ) { | ||
// add placeholder values (for inconsistent face definitions) | ||
this.addDefaultUV(); | ||
@@ -348,3 +338,2 @@ | ||
const vLen = this.vertices.length; | ||
for ( let vi = 0, l = vertices.length; vi < l; vi ++ ) { | ||
@@ -364,3 +353,2 @@ | ||
const uvLen = this.uvs.length; | ||
for ( let vi = 0, l = vertices.length; vi < l; vi ++ ) { | ||
@@ -383,4 +371,5 @@ | ||
} // | ||
} | ||
// | ||
@@ -395,3 +384,2 @@ class OBJLoader extends THREE.Loader { | ||
} | ||
load( url, onLoad, onProgress, onError ) { | ||
@@ -429,3 +417,2 @@ | ||
} | ||
setMaterials( materials ) { | ||
@@ -437,7 +424,5 @@ | ||
} | ||
parse( text ) { | ||
const state = new ParserState(); | ||
if ( text.indexOf( '\r\n' ) !== - 1 ) { | ||
@@ -459,3 +444,2 @@ | ||
let result = []; | ||
for ( let i = 0, l = lines.length; i < l; i ++ ) { | ||
@@ -465,10 +449,9 @@ | ||
if ( line.length === 0 ) continue; | ||
const lineFirstChar = line.charAt( 0 ); // @todo invoke passed in handler if any | ||
const lineFirstChar = line.charAt( 0 ); | ||
// @todo invoke passed in handler if any | ||
if ( lineFirstChar === '#' ) continue; | ||
if ( lineFirstChar === 'v' ) { | ||
const data = line.split( _face_vertex_data_separator_pattern ); | ||
switch ( data[ 0 ] ) { | ||
@@ -478,7 +461,5 @@ | ||
state.vertices.push( parseFloat( data[ 1 ] ), parseFloat( data[ 2 ] ), parseFloat( data[ 3 ] ) ); | ||
if ( data.length >= 7 ) { | ||
_color.setRGB( parseFloat( data[ 4 ] ), parseFloat( data[ 5 ] ), parseFloat( data[ 6 ] ) ).convertSRGBToLinear(); | ||
state.colors.push( _color.r, _color.g, _color.b ); | ||
@@ -489,2 +470,3 @@ | ||
// if no colors are defined, add placeholders so color and vertex indices match | ||
state.colors.push( undefined, undefined, undefined ); | ||
@@ -495,7 +477,5 @@ | ||
break; | ||
case 'vn': | ||
state.normals.push( parseFloat( data[ 1 ] ), parseFloat( data[ 2 ] ), parseFloat( data[ 3 ] ) ); | ||
break; | ||
case 'vt': | ||
@@ -511,8 +491,9 @@ state.uvs.push( parseFloat( data[ 1 ] ), parseFloat( data[ 2 ] ) ); | ||
const vertexData = lineData.split( _face_vertex_data_separator_pattern ); | ||
const faceVertices = []; // Parse the face vertex data into an easy to work with format | ||
const faceVertices = []; | ||
// Parse the face vertex data into an easy to work with format | ||
for ( let j = 0, jl = vertexData.length; j < jl; j ++ ) { | ||
const vertex = vertexData[ j ]; | ||
if ( vertex.length > 0 ) { | ||
@@ -525,7 +506,7 @@ | ||
} // Draw an edge between the first vertex and all subsequent vertices to form an n-gon | ||
} | ||
// Draw an edge between the first vertex and all subsequent vertices to form an n-gon | ||
const v1 = faceVertices[ 0 ]; | ||
for ( let j = 1, jl = faceVertices.length - 1; j < jl; j ++ ) { | ||
@@ -544,3 +525,2 @@ | ||
const lineUVs = []; | ||
if ( line.indexOf( '/' ) === - 1 ) { | ||
@@ -575,2 +555,3 @@ | ||
// g group_name | ||
// WORKAROUND: https://bugs.chromium.org/p/v8/issues/detail?id=2869 | ||
@@ -584,2 +565,3 @@ // let name = result[ 0 ].slice( 1 ).trim(); | ||
// material | ||
state.object.startMaterial( line.substring( 7 ).trim(), state.materialLibraries ); | ||
@@ -590,2 +572,3 @@ | ||
// mtl file | ||
state.materialLibraries.push( line.substring( 7 ).trim() ); | ||
@@ -597,2 +580,3 @@ | ||
// (according to https://www.okino.com/conv/imp_wave.htm, 'usemap' is the old-style Wavefront texture reference method) | ||
console.warn( 'THREE.OBJLoader: Rendering identifier "usemap" not supported. Textures must be defined in MTL files.' ); | ||
@@ -602,3 +586,6 @@ | ||
result = line.split( ' ' ); // smooth shading | ||
result = line.split( ' ' ); | ||
// smooth shading | ||
// @todo Handle files that have varying smooth values for a set of faces inside one geometry, | ||
@@ -620,3 +607,2 @@ // but does not define a usemtl for each face set. | ||
*/ | ||
if ( result.length > 1 ) { | ||
@@ -651,3 +637,2 @@ | ||
const hasPrimitives = ! ( state.objects.length === 1 && state.objects[ 0 ].geometry.vertices.length === 0 ); | ||
if ( hasPrimitives === true ) { | ||
@@ -662,8 +647,8 @@ | ||
const isPoints = geometry.type === 'Points'; | ||
let hasVertexColors = false; // Skip o/g line declarations that did not follow with any faces | ||
let hasVertexColors = false; | ||
// Skip o/g line declarations that did not follow with any faces | ||
if ( geometry.vertices.length === 0 ) continue; | ||
const buffergeometry = new THREE.BufferGeometry(); | ||
buffergeometry.setAttribute( 'position', new THREE.Float32BufferAttribute( geometry.vertices, 3 ) ); | ||
if ( geometry.normals.length > 0 ) { | ||
@@ -686,7 +671,7 @@ | ||
} // Create materials | ||
} | ||
// Create materials | ||
const createdMaterials = []; | ||
for ( let mi = 0, miLen = materials.length; mi < miLen; mi ++ ) { | ||
@@ -697,7 +682,7 @@ | ||
let material = state.materials[ materialHash ]; | ||
if ( this.materials !== null ) { | ||
material = this.materials.create( sourceMaterial.name ); // mtl etc. loaders probably can't create line materials correctly, copy properties to a line material. | ||
material = this.materials.create( sourceMaterial.name ); | ||
// mtl etc. loaders probably can't create line materials correctly, copy properties to a line material. | ||
if ( isLine && material && ! ( material instanceof THREE.LineBasicMaterial ) ) { | ||
@@ -753,7 +738,7 @@ | ||
} // Create mesh | ||
} | ||
// Create mesh | ||
let mesh; | ||
if ( createdMaterials.length > 1 ) { | ||
@@ -808,2 +793,3 @@ | ||
// if there is only the default parser state object with no geometry data, interpret data as point cloud | ||
if ( state.vertices.length > 0 ) { | ||
@@ -817,3 +803,2 @@ | ||
buffergeometry.setAttribute( 'position', new THREE.Float32BufferAttribute( state.vertices, 3 ) ); | ||
if ( state.colors.length > 0 && state.colors[ 0 ] !== undefined ) { | ||
@@ -820,0 +805,0 @@ |
@@ -11,3 +11,2 @@ ( function () { | ||
} | ||
load( url, onLoad, onProgress, onError ) { | ||
@@ -46,6 +45,6 @@ | ||
} | ||
parse( data ) { | ||
// from https://gitlab.com/taketwo/three-pcd-loader/blob/master/decompress-lzf.js | ||
function decompressLZF( inData, outLength ) { | ||
@@ -60,7 +59,5 @@ | ||
let ref; | ||
do { | ||
ctrl = inData[ inPtr ++ ]; | ||
if ( ctrl < 1 << 5 ) { | ||
@@ -71,3 +68,2 @@ | ||
if ( inPtr + ctrl > inLength ) throw new Error( 'Invalid compressed data' ); | ||
do { | ||
@@ -84,3 +80,2 @@ | ||
if ( inPtr >= inLength ) throw new Error( 'Invalid compressed data' ); | ||
if ( len === 7 ) { | ||
@@ -97,3 +92,2 @@ | ||
if ( ref >= outPtr ) throw new Error( 'Invalid compressed data' ); | ||
do { | ||
@@ -120,6 +114,10 @@ | ||
PCDheader.headerLen = result2[ 0 ].length + result1; | ||
PCDheader.str = data.slice( 0, PCDheader.headerLen ); // remove comments | ||
PCDheader.str = data.slice( 0, PCDheader.headerLen ); | ||
PCDheader.str = PCDheader.str.replace( /\#.*/gi, '' ); // parse | ||
// remove comments | ||
PCDheader.str = PCDheader.str.replace( /\#.*/gi, '' ); | ||
// parse | ||
PCDheader.version = /VERSION (.*)/i.exec( PCDheader.str ); | ||
@@ -133,4 +131,6 @@ PCDheader.fields = /FIELDS (.*)/i.exec( PCDheader.str ); | ||
PCDheader.viewpoint = /VIEWPOINT (.*)/i.exec( PCDheader.str ); | ||
PCDheader.points = /POINTS (.*)/i.exec( PCDheader.str ); // evaluate | ||
PCDheader.points = /POINTS (.*)/i.exec( PCDheader.str ); | ||
// evaluate | ||
if ( PCDheader.version !== null ) PCDheader.version = parseFloat( PCDheader.version[ 1 ] ); | ||
@@ -144,3 +144,2 @@ PCDheader.fields = PCDheader.fields !== null ? PCDheader.fields[ 1 ].split( ' ' ) : []; | ||
if ( PCDheader.points === null ) PCDheader.points = PCDheader.width * PCDheader.height; | ||
if ( PCDheader.size !== null ) { | ||
@@ -167,3 +166,2 @@ | ||
PCDheader.count = []; | ||
for ( let i = 0, l = PCDheader.fields.length; i < l; i ++ ) { | ||
@@ -179,3 +177,2 @@ | ||
let sizeSum = 0; | ||
for ( let i = 0, l = PCDheader.fields.length; i < l; i ++ ) { | ||
@@ -194,4 +191,5 @@ | ||
} // for binary only | ||
} | ||
// for binary only | ||
@@ -203,6 +201,10 @@ PCDheader.rowSize = sizeSum; | ||
const textData = THREE.LoaderUtils.decodeText( new Uint8Array( data ) ); // parse header (always ascii format) | ||
const textData = THREE.LoaderUtils.decodeText( new Uint8Array( data ) ); | ||
const PCDheader = parseHeader( textData ); // parse data | ||
// parse header (always ascii format) | ||
const PCDheader = parseHeader( textData ); | ||
// parse data | ||
const position = []; | ||
@@ -212,4 +214,6 @@ const normal = []; | ||
const intensity = []; | ||
const label = []; // ascii | ||
const label = []; | ||
// ascii | ||
if ( PCDheader.data === 'ascii' ) { | ||
@@ -220,3 +224,2 @@ | ||
const lines = pcdData.split( '\n' ); | ||
for ( let i = 0, l = lines.length; i < l; i ++ ) { | ||
@@ -226,3 +229,2 @@ | ||
const line = lines[ i ].split( ' ' ); | ||
if ( offset.x !== undefined ) { | ||
@@ -242,3 +244,2 @@ | ||
let rgb = float; | ||
if ( rgb_type === 'F' ) { | ||
@@ -283,3 +284,6 @@ | ||
} // binary-compressed | ||
} | ||
// binary-compressed | ||
// normally data in PCD files are organized as array of structures: XYZRGBXYZRGB | ||
@@ -289,3 +293,2 @@ // binary compressed PCD files organize their data as structure of arrays: XXYYZZRGBRGB | ||
if ( PCDheader.data === 'binary_compressed' ) { | ||
@@ -299,3 +302,2 @@ | ||
const offset = PCDheader.offset; | ||
for ( let i = 0; i < PCDheader.points; i ++ ) { | ||
@@ -350,4 +352,5 @@ | ||
} // binary | ||
} | ||
// binary | ||
@@ -358,3 +361,2 @@ if ( PCDheader.data === 'binary' ) { | ||
const offset = PCDheader.offset; | ||
for ( let i = 0, row = 0; i < PCDheader.points; i ++, row += PCDheader.rowSize ) { | ||
@@ -400,4 +402,5 @@ | ||
} // build geometry | ||
} | ||
// build geometry | ||
@@ -410,8 +413,9 @@ const geometry = new THREE.BufferGeometry(); | ||
if ( label.length > 0 ) geometry.setAttribute( 'label', new THREE.Int32BufferAttribute( label, 1 ) ); | ||
geometry.computeBoundingSphere(); // build material | ||
geometry.computeBoundingSphere(); | ||
// build material | ||
const material = new THREE.PointsMaterial( { | ||
size: 0.005 | ||
} ); | ||
if ( color.length > 0 ) { | ||
@@ -421,4 +425,5 @@ | ||
} // build point cloud | ||
} | ||
// build point cloud | ||
@@ -425,0 +430,0 @@ return new THREE.Points( geometry, material ); |
@@ -10,3 +10,2 @@ ( function () { | ||
} | ||
load( url, onLoad, onProgress, onError ) { | ||
@@ -43,4 +42,5 @@ | ||
} // Based on CanvasMol PDB parser | ||
} | ||
// Based on CanvasMol PDB parser | ||
@@ -70,14 +70,13 @@ parse( text ) { | ||
const eatom = parseInt( lines[ i ].slice( start, start + length ) ); | ||
if ( eatom ) { | ||
const h = hash( satom, eatom ); | ||
if ( _bhash[ h ] === undefined ) { | ||
_bonds.push( [ satom - 1, eatom - 1, 1 ] ); | ||
_bhash[ h ] = _bonds.length - 1; | ||
} else { // doesn't really work as almost all PDBs | ||
} else { | ||
// doesn't really work as almost all PDBs | ||
// have just normal bonds appearing multiple | ||
@@ -105,4 +104,6 @@ // times instead of being double/triple bonds | ||
const colorsAtoms = []; | ||
const verticesBonds = []; // atoms | ||
const verticesBonds = []; | ||
// atoms | ||
for ( let i = 0, l = atoms.length; i < l; i ++ ) { | ||
@@ -120,4 +121,5 @@ | ||
} // bonds | ||
} | ||
// bonds | ||
@@ -140,4 +142,5 @@ for ( let i = 0, l = _bonds.length; i < l; i ++ ) { | ||
} // build geometry | ||
} | ||
// build geometry | ||
@@ -274,6 +277,7 @@ geometryAtoms.setAttribute( 'position', new THREE.Float32BufferAttribute( verticesAtoms, 3 ) ); | ||
const _bhash = {}; | ||
const _atomMap = {}; // parse | ||
const _atomMap = {}; | ||
// parse | ||
const lines = text.split( '\n' ); | ||
for ( let i = 0, l = lines.length; i < l; i ++ ) { | ||
@@ -288,3 +292,2 @@ | ||
let e = trim( lines[ i ].slice( 76, 78 ) ).toLowerCase(); | ||
if ( e === '' ) { | ||
@@ -310,4 +313,5 @@ | ||
} // build and return geometry | ||
} | ||
// build and return geometry | ||
@@ -314,0 +318,0 @@ return buildGeometry(); |
@@ -30,3 +30,2 @@ ( function () { | ||
const _color = new THREE.Color(); | ||
class PLYLoader extends THREE.Loader { | ||
@@ -40,3 +39,2 @@ | ||
} | ||
load( url, onLoad, onProgress, onError ) { | ||
@@ -75,3 +73,2 @@ | ||
} | ||
setPropertyNameMapping( mapping ) { | ||
@@ -82,3 +79,2 @@ | ||
} | ||
parse( data ) { | ||
@@ -92,3 +88,2 @@ | ||
const result = patternHeader.exec( data ); | ||
if ( result !== null ) { | ||
@@ -109,3 +104,2 @@ | ||
let currentElement; | ||
function make_ply_element_property( propertValues, propertyNameMapping ) { | ||
@@ -116,3 +110,2 @@ | ||
}; | ||
if ( property.type === 'list' ) { | ||
@@ -148,3 +141,2 @@ | ||
line = lineValues.join( ' ' ); | ||
switch ( lineType ) { | ||
@@ -156,7 +148,5 @@ | ||
break; | ||
case 'comment': | ||
header.comments.push( line ); | ||
break; | ||
case 'element': | ||
@@ -174,11 +164,8 @@ if ( currentElement !== undefined ) { | ||
break; | ||
case 'property': | ||
currentElement.properties.push( make_ply_element_property( lineValues, scope.propertyNameMapping ) ); | ||
break; | ||
case 'obj_info': | ||
header.objInfo = line; | ||
break; | ||
default: | ||
@@ -218,3 +205,2 @@ console.log( 'unhandled', lineType, lineValues ); | ||
return parseInt( n ); | ||
case 'float': | ||
@@ -234,3 +220,2 @@ case 'double': | ||
const element = {}; | ||
for ( let i = 0; i < properties.length; i ++ ) { | ||
@@ -242,3 +227,2 @@ | ||
const n = parseASCIINumber( values.shift(), properties[ i ].countType ); | ||
for ( let j = 0; j < n; j ++ ) { | ||
@@ -267,2 +251,3 @@ | ||
// PLY ascii format specification, as per http://en.wikipedia.org/wiki/PLY_(file_format) | ||
const buffer = { | ||
@@ -279,3 +264,2 @@ indices: [], | ||
let body = ''; | ||
if ( ( result = patternBody.exec( data ) ) !== null ) { | ||
@@ -290,3 +274,2 @@ | ||
let currentElementCount = 0; | ||
for ( let i = 0; i < lines.length; i ++ ) { | ||
@@ -296,3 +279,2 @@ | ||
line = line.trim(); | ||
if ( line === '' ) { | ||
@@ -323,4 +305,6 @@ | ||
let geometry = new THREE.BufferGeometry(); // mandatory buffer data | ||
let geometry = new THREE.BufferGeometry(); | ||
// mandatory buffer data | ||
if ( buffer.indices.length > 0 ) { | ||
@@ -332,4 +316,6 @@ | ||
geometry.setAttribute( 'position', new THREE.Float32BufferAttribute( buffer.vertices, 3 ) ); // optional buffer data | ||
geometry.setAttribute( 'position', new THREE.Float32BufferAttribute( buffer.vertices, 3 ) ); | ||
// optional buffer data | ||
if ( buffer.normals.length > 0 ) { | ||
@@ -391,7 +377,5 @@ | ||
const attrB = findAttrName( [ 'blue', 'diffuse_blue', 'b', 'diffuse_b' ] ); | ||
if ( elementName === 'vertex' ) { | ||
buffer.vertices.push( element[ attrX ], element[ attrY ], element[ attrZ ] ); | ||
if ( attrNX !== null && attrNY !== null && attrNZ !== null ) { | ||
@@ -412,3 +396,2 @@ | ||
_color.setRGB( element[ attrR ] / 255.0, element[ attrG ] / 255.0, element[ attrB ] / 255.0 ).convertSRGBToLinear(); | ||
buffer.colors.push( _color.r, _color.g, _color.b ); | ||
@@ -421,9 +404,6 @@ | ||
const vertex_indices = element.vertex_indices || element.vertex_index; // issue #9338 | ||
const texcoord = element.texcoord; | ||
if ( vertex_indices.length === 3 ) { | ||
buffer.indices.push( vertex_indices[ 0 ], vertex_indices[ 1 ], vertex_indices[ 2 ] ); | ||
if ( texcoord && texcoord.length === 6 ) { | ||
@@ -456,27 +436,20 @@ | ||
return [ dataview.getInt8( at ), 1 ]; | ||
case 'uint8': | ||
case 'uchar': | ||
return [ dataview.getUint8( at ), 1 ]; | ||
case 'int16': | ||
case 'short': | ||
return [ dataview.getInt16( at, little_endian ), 2 ]; | ||
case 'uint16': | ||
case 'ushort': | ||
return [ dataview.getUint16( at, little_endian ), 2 ]; | ||
case 'int32': | ||
case 'int': | ||
return [ dataview.getInt32( at, little_endian ), 4 ]; | ||
case 'uint32': | ||
case 'uint': | ||
return [ dataview.getUint32( at, little_endian ), 4 ]; | ||
case 'float32': | ||
case 'float': | ||
return [ dataview.getFloat32( at, little_endian ), 4 ]; | ||
case 'float64': | ||
@@ -495,3 +468,2 @@ case 'double': | ||
read = 0; | ||
for ( let i = 0; i < properties.length; i ++ ) { | ||
@@ -505,3 +477,2 @@ | ||
read += result[ 1 ]; | ||
for ( let j = 0; j < n; j ++ ) { | ||
@@ -545,3 +516,2 @@ | ||
loc = 0; | ||
for ( let currentElement = 0; currentElement < header.elements.length; currentElement ++ ) { | ||
@@ -562,8 +532,8 @@ | ||
} // | ||
} | ||
// | ||
let geometry; | ||
const scope = this; | ||
if ( data instanceof ArrayBuffer ) { | ||
@@ -570,0 +540,0 @@ |
@@ -8,2 +8,3 @@ ( function () { | ||
let bigEndianPlatform = null; | ||
/** | ||
@@ -13,3 +14,2 @@ * Check if the endianness of the platform is big-endian (most significant bit first) | ||
*/ | ||
function isBigEndianPlatform() { | ||
@@ -23,5 +23,3 @@ | ||
uint8Array[ 0 ] = 0xAA; // set first byte | ||
uint8Array[ 1 ] = 0xBB; // set second byte | ||
bigEndianPlatform = uint16Array[ 0 ] === 0xAABB; | ||
@@ -33,7 +31,8 @@ | ||
} // match the values defined in the spec to the TypedArray types | ||
} | ||
// match the values defined in the spec to the TypedArray types | ||
const InvertedEncodingTypes = [ null, Float32Array, null, Int8Array, Int16Array, null, Int32Array, Uint8Array, Uint16Array, null, Uint32Array ]; | ||
const InvertedEncodingTypes = [ null, Float32Array, null, Int8Array, Int16Array, null, Int32Array, Uint8Array, Uint16Array, null, Uint32Array ]; // define the method to use on a DataView, corresponding the TypedArray type | ||
// define the method to use on a DataView, corresponding the TypedArray type | ||
const getMethods = { | ||
@@ -47,3 +46,2 @@ Uint16Array: 'getUint16', | ||
}; | ||
function copyFromBuffer( sourceArrayBuffer, viewType, position, length, fromBigEndian ) { | ||
@@ -53,3 +51,2 @@ | ||
let result; | ||
if ( fromBigEndian === isBigEndianPlatform() || bytesPerElement === 1 ) { | ||
@@ -65,3 +62,2 @@ | ||
result = new viewType( length ); | ||
for ( let i = 0; i < length; i ++ ) { | ||
@@ -90,3 +86,2 @@ | ||
indicesNumber = 0; | ||
if ( bigEndian ) { | ||
@@ -103,5 +98,5 @@ | ||
} | ||
/** PRELIMINARY CHECKS **/ | ||
if ( version === 0 ) { | ||
@@ -130,12 +125,10 @@ | ||
} | ||
/** PARSING **/ | ||
let pos = 8; | ||
const attributes = {}; | ||
for ( let i = 0; i < attributesNumber; i ++ ) { | ||
let attributeName = ''; | ||
while ( pos < array.length ) { | ||
@@ -145,3 +138,2 @@ | ||
pos ++; | ||
if ( char === 0 ) { | ||
@@ -164,4 +156,5 @@ | ||
const arrayType = InvertedEncodingTypes[ encodingType ]; | ||
pos ++; // padding to next multiple of 4 | ||
pos ++; | ||
// padding to next multiple of 4 | ||
pos = Math.ceil( pos / 4 ) * 4; | ||
@@ -180,3 +173,2 @@ const values = copyFromBuffer( buffer, arrayType, pos, cardinality * valuesNumber, bigEndian ); | ||
let indices = null; | ||
if ( indexedGeometry ) { | ||
@@ -194,4 +186,5 @@ | ||
} // Define the public interface | ||
} | ||
// Define the public interface | ||
@@ -205,3 +198,2 @@ class PRWMLoader extends THREE.Loader { | ||
} | ||
load( url, onLoad, onProgress, onError ) { | ||
@@ -241,3 +233,2 @@ | ||
} | ||
parse( arrayBuffer ) { | ||
@@ -248,3 +239,2 @@ | ||
bufferGeometry = new THREE.BufferGeometry(); | ||
for ( let i = 0; i < attributesKey.length; i ++ ) { | ||
@@ -266,3 +256,2 @@ | ||
} | ||
static isBigEndianPlatform() { | ||
@@ -269,0 +258,0 @@ |
@@ -16,3 +16,2 @@ ( function () { | ||
} | ||
parse( buffer, loadMipmaps ) { | ||
@@ -27,6 +26,6 @@ | ||
}; | ||
if ( header[ 0 ] === 0x03525650 ) { | ||
// PVR v3 | ||
return _parseV3( pvrDatas ); | ||
@@ -37,2 +36,3 @@ | ||
// PVR v2 | ||
return _parseV2( pvrDatas ); | ||
@@ -49,3 +49,2 @@ | ||
} | ||
function _parseV3( pvrDatas ) { | ||
@@ -62,3 +61,2 @@ | ||
numMipmaps = header[ 11 ]; | ||
switch ( pixelFormat ) { | ||
@@ -71,3 +69,2 @@ | ||
break; | ||
case 1: | ||
@@ -78,3 +75,2 @@ // PVRTC 2bpp RGBA | ||
break; | ||
case 2: | ||
@@ -85,3 +81,2 @@ // PVRTC 4bpp RGB | ||
break; | ||
case 3: | ||
@@ -92,3 +87,2 @@ // PVRTC 4bpp RGBA | ||
break; | ||
default: | ||
@@ -132,5 +126,3 @@ console.error( 'THREE.PVRLoader: Unsupported PVR format:', pixelFormat ); | ||
let bpp, format; | ||
const _hasAlpha = bitmaskAlpha > 0; | ||
if ( formatFlags === PVRTC_4 ) { | ||
@@ -158,5 +150,6 @@ | ||
pvrDatas.numSurfaces = numSurfs; | ||
pvrDatas.numMipmaps = numMipmaps + 1; // guess cubemap type seems tricky in v2 | ||
pvrDatas.numMipmaps = numMipmaps + 1; | ||
// guess cubemap type seems tricky in v2 | ||
// it juste a pvr containing 6 surface (no explicit cubemap type) | ||
pvrDatas.isCubemap = numSurfs === 6; | ||
@@ -187,3 +180,2 @@ return _extract( pvrDatas ); | ||
numSurfs = pvrDatas.numSurfaces; | ||
if ( bpp === 2 ) { | ||
@@ -204,3 +196,2 @@ | ||
let mipLevel = 0; | ||
while ( mipLevel < pvrDatas.numMipmaps ) { | ||
@@ -211,8 +202,8 @@ | ||
widthBlocks = sWidth / blockWidth; | ||
heightBlocks = sHeight / blockHeight; // Clamp to minimum number of blocks | ||
heightBlocks = sHeight / blockHeight; | ||
// Clamp to minimum number of blocks | ||
if ( widthBlocks < 2 ) widthBlocks = 2; | ||
if ( heightBlocks < 2 ) heightBlocks = 2; | ||
dataSize = widthBlocks * heightBlocks * blockSize; | ||
for ( let surfIndex = 0; surfIndex < numSurfs; surfIndex ++ ) { | ||
@@ -219,0 +210,0 @@ |
( function () { | ||
// https://github.com/mrdoob/three.js/issues/5552 | ||
// http://en.wikipedia.org/wiki/RGBE_image_format | ||
@@ -12,12 +13,11 @@ | ||
} // adapted from http://www.graphics.cornell.edu/~bjw/rgbe.html | ||
} | ||
// adapted from http://www.graphics.cornell.edu/~bjw/rgbe.html | ||
parse( buffer ) { | ||
const | ||
/* return codes for rgbe routines */ | ||
const /* return codes for rgbe routines */ | ||
//RGBE_RETURN_SUCCESS = 0, | ||
RGBE_RETURN_FAILURE = - 1, | ||
/* default error routine. change this to change error handling */ | ||
@@ -35,11 +35,8 @@ rgbe_read_error = 1, | ||
break; | ||
case rgbe_write_error: | ||
console.error( 'THREE.RGBELoader Write Error: ' + ( msg || '' ) ); | ||
break; | ||
case rgbe_format_error: | ||
console.error( 'THREE.RGBELoader Bad File Format: ' + ( msg || '' ) ); | ||
break; | ||
default: | ||
@@ -54,3 +51,2 @@ case rgbe_memory_error: | ||
}, | ||
/* offsets to red, green, and blue components in a data (float) pixel */ | ||
@@ -78,3 +74,2 @@ //RGBE_DATA_RED = 0, | ||
chunk = String.fromCharCode.apply( null, new Uint16Array( buffer.subarray( p, p + chunkSize ) ) ); | ||
while ( 0 > ( i = chunk.indexOf( NEWLINE ) ) && len < lineLimit && p < buffer.byteLength ) { | ||
@@ -92,7 +87,7 @@ | ||
/*for (i=l-1; i>=0; i--) { | ||
byteCode = m.charCodeAt(i); | ||
if (byteCode > 0x7f && byteCode <= 0x7ff) byteLen++; | ||
else if (byteCode > 0x7ff && byteCode <= 0xffff) byteLen += 2; | ||
if (byteCode >= 0xDC00 && byteCode <= 0xDFFF) i--; //trail surrogate | ||
}*/ | ||
byteCode = m.charCodeAt(i); | ||
if (byteCode > 0x7f && byteCode <= 0x7ff) byteLen++; | ||
else if (byteCode > 0x7ff && byteCode <= 0xffff) byteLen += 2; | ||
if (byteCode >= 0xDC00 && byteCode <= 0xDFFF) i--; //trail surrogate | ||
}*/ | ||
if ( false !== consume ) buffer.pos += len + i + 1; | ||
@@ -106,3 +101,2 @@ return s + chunk.slice( 0, i ); | ||
}, | ||
/* minimal header reading. modify if you want to parse more information */ | ||
@@ -120,29 +114,27 @@ RGBE_ReadHeader = function ( buffer ) { | ||
valid: 0, | ||
/* indicate which fields are valid */ | ||
/* indicate which fields are valid */ | ||
string: '', | ||
/* the actual header string */ | ||
/* the actual header string */ | ||
comments: '', | ||
/* comments found in header */ | ||
/* comments found in header */ | ||
programtype: 'RGBE', | ||
/* listed at beginning of file to identify it after "#?". defaults to "RGBE" */ | ||
/* listed at beginning of file to identify it after "#?". defaults to "RGBE" */ | ||
format: '', | ||
/* RGBE format, default 32-bit_rle_rgbe */ | ||
/* RGBE format, default 32-bit_rle_rgbe */ | ||
gamma: 1.0, | ||
/* image has already been gamma corrected with given gamma. defaults to 1.0 (no correction) */ | ||
/* image has already been gamma corrected with given gamma. defaults to 1.0 (no correction) */ | ||
exposure: 1.0, | ||
/* a value of 1.0 in an image corresponds to <exposure> watts/steradian/m^2. defaults to 1.0 */ | ||
/* a value of 1.0 in an image corresponds to <exposure> watts/steradian/m^2. defaults to 1.0 */ | ||
width: 0, | ||
height: 0 | ||
/* image dimensions, width/height */ | ||
height: 0 /* image dimensions, width/height */ | ||
}; | ||
}; | ||
let line, match; | ||
if ( buffer.pos >= buffer.byteLength || ! ( line = fgets( buffer ) ) ) { | ||
@@ -153,5 +145,4 @@ | ||
} | ||
/* if you want to require the magic token then uncomment the next line */ | ||
if ( ! ( match = line.match( magic_token_re ) ) ) { | ||
@@ -166,3 +157,2 @@ | ||
header.string += line + '\n'; | ||
while ( true ) { | ||
@@ -173,3 +163,2 @@ | ||
header.string += line + '\n'; | ||
if ( '#' === line.charAt( 0 ) ) { | ||
@@ -231,7 +220,8 @@ | ||
const scanline_width = w; | ||
if ( | ||
// run length encoding is not allowed so read flat | ||
scanline_width < 8 || scanline_width > 0x7fff || | ||
// this file is not run length encoded | ||
2 !== buffer[ 0 ] || 2 !== buffer[ 1 ] || buffer[ 2 ] & 0x80 ) { | ||
if ( // run length encoding is not allowed so read flat | ||
scanline_width < 8 || scanline_width > 0x7fff || // this file is not run length encoded | ||
2 !== buffer[ 0 ] || 2 !== buffer[ 1 ] || buffer[ 2 ] & 0x80 ) { | ||
// return the flat buffer | ||
@@ -249,3 +239,2 @@ return new Uint8Array( buffer ); | ||
const data_rgba = new Uint8Array( 4 * w * h ); | ||
if ( ! data_rgba.length ) { | ||
@@ -262,4 +251,5 @@ | ||
const scanline_buffer = new Uint8Array( ptr_end ); | ||
let num_scanlines = h; // read in each successive scanline | ||
let num_scanlines = h; | ||
// read in each successive scanline | ||
while ( num_scanlines > 0 && pos < buffer.byteLength ) { | ||
@@ -277,3 +267,2 @@ | ||
rgbeStart[ 3 ] = buffer[ pos ++ ]; | ||
if ( 2 != rgbeStart[ 0 ] || 2 != rgbeStart[ 1 ] || ( rgbeStart[ 2 ] << 8 | rgbeStart[ 3 ] ) != scanline_width ) { | ||
@@ -283,9 +272,8 @@ | ||
} // read each of the four channels for the scanline into the buffer | ||
} | ||
// read each of the four channels for the scanline into the buffer | ||
// first red, then green, then blue, then exponent | ||
let ptr = 0, | ||
count; | ||
while ( ptr < ptr_end && pos < buffer.byteLength ) { | ||
@@ -296,3 +284,2 @@ | ||
if ( isEncodedRun ) count -= 128; | ||
if ( 0 === count || ptr + count > ptr_end ) { | ||
@@ -308,3 +295,2 @@ | ||
const byteValue = buffer[ pos ++ ]; | ||
for ( let i = 0; i < count; i ++ ) { | ||
@@ -314,3 +300,4 @@ | ||
} //ptr += count; | ||
} | ||
//ptr += count; | ||
@@ -326,8 +313,7 @@ } else { | ||
} // now convert data from buffer into rgba | ||
} | ||
// now convert data from buffer into rgba | ||
// first red, then green, then blue, then exponent (alpha) | ||
const l = scanline_width; //scanline_buffer.byteLength; | ||
for ( let i = 0; i < l; i ++ ) { | ||
@@ -338,9 +324,6 @@ | ||
off += scanline_width; //1; | ||
data_rgba[ offset + 1 ] = scanline_buffer[ i + off ]; | ||
off += scanline_width; //1; | ||
data_rgba[ offset + 2 ] = scanline_buffer[ i + off ]; | ||
off += scanline_width; //1; | ||
data_rgba[ offset + 3 ] = scanline_buffer[ i + off ]; | ||
@@ -373,4 +356,5 @@ offset += 4; | ||
const e = sourceArray[ sourceOffset + 3 ]; | ||
const scale = Math.pow( 2.0, e - 128.0 ) / 255.0; // clamping to 65504, the maximum representable value in float16 | ||
const scale = Math.pow( 2.0, e - 128.0 ) / 255.0; | ||
// clamping to 65504, the maximum representable value in float16 | ||
destArray[ destOffset + 0 ] = THREE.DataUtils.toHalfFloat( Math.min( sourceArray[ sourceOffset + 0 ] * scale, 65504 ) ); | ||
@@ -386,3 +370,2 @@ destArray[ destOffset + 1 ] = THREE.DataUtils.toHalfFloat( Math.min( sourceArray[ sourceOffset + 1 ] * scale, 65504 ) ); | ||
const rgbe_header_info = RGBE_ReadHeader( byteArray ); | ||
if ( RGBE_RETURN_FAILURE !== rgbe_header_info ) { | ||
@@ -393,3 +376,2 @@ | ||
image_rgba_data = RGBE_ReadPixels_RLE( byteArray.subarray( byteArray.pos ), w, h ); | ||
if ( RGBE_RETURN_FAILURE !== image_rgba_data ) { | ||
@@ -399,3 +381,2 @@ | ||
let numElements; | ||
switch ( this.type ) { | ||
@@ -406,3 +387,2 @@ | ||
const floatArray = new Float32Array( numElements * 4 ); | ||
for ( let j = 0; j < numElements; j ++ ) { | ||
@@ -417,7 +397,5 @@ | ||
break; | ||
case THREE.HalfFloatType: | ||
numElements = image_rgba_data.length / 4; | ||
const halfArray = new Uint16Array( numElements * 4 ); | ||
for ( let j = 0; j < numElements; j ++ ) { | ||
@@ -432,3 +410,2 @@ | ||
break; | ||
default: | ||
@@ -457,3 +434,2 @@ console.error( 'THREE.RGBELoader: unsupported type: ', this.type ); | ||
} | ||
setDataType( value ) { | ||
@@ -465,3 +441,2 @@ | ||
} | ||
load( url, onLoad, onProgress, onError ) { | ||
@@ -468,0 +443,0 @@ |
@@ -19,3 +19,2 @@ ( function () { | ||
} | ||
setMaxRange( value ) { | ||
@@ -27,3 +26,2 @@ | ||
} | ||
loadCubemap( urls, onLoad, onProgress, onError ) { | ||
@@ -34,3 +32,2 @@ | ||
const scope = this; | ||
function loadTexture( i ) { | ||
@@ -42,3 +39,2 @@ | ||
loaded ++; | ||
if ( loaded === 6 ) { | ||
@@ -68,3 +64,2 @@ | ||
} | ||
parse( buffer ) { | ||
@@ -76,4 +71,6 @@ | ||
const size = img.width * img.height * 4; | ||
const output = this.type === THREE.HalfFloatType ? new Uint16Array( size ) : new Float32Array( size ); // decode RGBM | ||
const output = this.type === THREE.HalfFloatType ? new Uint16Array( size ) : new Float32Array( size ); | ||
// decode RGBM | ||
for ( let i = 0; i < data.length; i += 4 ) { | ||
@@ -85,3 +82,2 @@ | ||
const a = data[ i + 3 ] / 255; | ||
if ( this.type === THREE.HalfFloatType ) { | ||
@@ -116,7 +112,7 @@ | ||
} // from https://github.com/photopea/UPNG.js (MIT License) | ||
} | ||
// from https://github.com/photopea/UPNG.js (MIT License) | ||
var UPNG = {}; | ||
UPNG.toRGBA8 = function ( out ) { | ||
@@ -133,3 +129,2 @@ | ||
prev = new Uint8Array( len ); | ||
for ( var i = 0; i < out.frames.length; i ++ ) { | ||
@@ -158,3 +153,2 @@ | ||
bpp = UPNG.decode._getBPP( out ); | ||
var bpl = Math.ceil( w * bpp / 8 ); // bytes per line | ||
@@ -167,6 +161,6 @@ | ||
var rs = UPNG._bin.readUshort; | ||
if ( ctype == 6 ) { | ||
// RGB + alpha | ||
var qarea = area << 2; | ||
@@ -191,4 +185,4 @@ if ( depth == 8 ) for ( var i = 0; i < qarea; i += 4 ) { | ||
// RGB | ||
var ts = out.tabs[ 'tRNS' ]; | ||
if ( ts == null ) { | ||
@@ -238,6 +232,7 @@ | ||
// palette | ||
var p = out.tabs[ 'PLTE' ], | ||
ap = out.tabs[ 'tRNS' ], | ||
tl = ap ? ap.length : 0; //console.log(p, ap); | ||
tl = ap ? ap.length : 0; | ||
//console.log(p, ap); | ||
if ( depth == 1 ) for ( var y = 0; y < h; y ++ ) { | ||
@@ -247,3 +242,2 @@ | ||
t0 = y * w; | ||
for ( var i = 0; i < w; i ++ ) { | ||
@@ -267,3 +261,2 @@ | ||
t0 = y * w; | ||
for ( var i = 0; i < w; i ++ ) { | ||
@@ -287,3 +280,2 @@ | ||
t0 = y * w; | ||
for ( var i = 0; i < w; i ++ ) { | ||
@@ -318,2 +310,3 @@ | ||
// gray + alpha | ||
if ( depth == 8 ) for ( var i = 0; i < area; i ++ ) { | ||
@@ -346,4 +339,4 @@ | ||
// gray | ||
var tr = out.tabs[ 'tRNS' ] ? out.tabs[ 'tRNS' ] : - 1; | ||
for ( var y = 0; y < h; y ++ ) { | ||
@@ -387,5 +380,5 @@ | ||
} //console.log(Date.now()-time); | ||
} | ||
//console.log(Date.now()-time); | ||
return bf; | ||
@@ -408,11 +401,7 @@ | ||
doff = 0; // put all IDAT data into it | ||
var fd, | ||
foff = 0; // frames | ||
var text, keyw, bfr; | ||
var mgck = [ 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a ]; | ||
for ( var i = 0; i < 8; i ++ ) if ( data[ i ] != mgck[ i ] ) throw new Error( 'The input is not a PNG file!' ); | ||
while ( offset < data.length ) { | ||
@@ -423,3 +412,4 @@ | ||
var type = bin.readASCII( data, offset, 4 ); | ||
offset += 4; //console.log(type,len); | ||
offset += 4; | ||
//console.log(type,len); | ||
@@ -437,3 +427,2 @@ if ( type == 'IHDR' ) { | ||
for ( var i = 0; i < len; i ++ ) dd[ doff + i ] = data[ offset + i ]; | ||
doff += len; | ||
@@ -472,4 +461,4 @@ | ||
blend: data[ offset + 25 ] | ||
}; //console.log(frm); | ||
}; | ||
//console.log(frm); | ||
out.frames.push( frm ); | ||
@@ -480,3 +469,2 @@ | ||
for ( var i = 0; i < len - 4; i ++ ) fd[ foff + i ] = data[ offset + i + 4 ]; | ||
foff += len - 4; | ||
@@ -491,3 +479,2 @@ | ||
out.tabs[ type ] = []; | ||
for ( var i = 0; i < 8; i ++ ) out.tabs[ type ].push( bin.readUint( data, offset + i * 4 ) ); | ||
@@ -544,3 +531,2 @@ | ||
out.tabs[ type ] = []; | ||
for ( var i = 0; i < pl; i ++ ) out.tabs[ type ].push( rUs( data, offset + i * 2 ) ); | ||
@@ -550,3 +536,4 @@ | ||
if ( out.ctype == 3 ) out.tabs[ type ] = bin.readBytes( data, offset, len ); else if ( out.ctype == 0 ) out.tabs[ type ] = rUs( data, offset ); else if ( out.ctype == 2 ) out.tabs[ type ] = [ rUs( data, offset ), rUs( data, offset + 2 ), rUs( data, offset + 4 ) ]; //else console.log("tRNS for unsupported color type",out.ctype, len); | ||
if ( out.ctype == 3 ) out.tabs[ type ] = bin.readBytes( data, offset, len ); else if ( out.ctype == 0 ) out.tabs[ type ] = rUs( data, offset ); else if ( out.ctype == 2 ) out.tabs[ type ] = [ rUs( data, offset ), rUs( data, offset + 2 ), rUs( data, offset + 4 ) ]; | ||
//else console.log("tRNS for unsupported color type",out.ctype, len); | ||
@@ -561,5 +548,5 @@ } else if ( type == 'gAMA' ) out.tabs[ type ] = bin.readUint( data, offset ) / 100000; else if ( type == 'sRGB' ) out.tabs[ type ] = data[ offset ]; else if ( type == 'bKGD' ) { | ||
} //else { console.log("unknown chunk type", type, len); out.tabs[type]=data.slice(offset,offset+len); } | ||
} | ||
//else { console.log("unknown chunk type", type, len); out.tabs[type]=data.slice(offset,offset+len); } | ||
offset += len; | ||
@@ -591,3 +578,2 @@ bin.readUint( data, offset ); | ||
buff = new Uint8Array( ( bpl + 1 + out.interlace ) * h ); | ||
if ( out.tabs[ 'CgBI' ] ) dd = UPNG.inflateRaw( dd, buff ); else dd = UPNG.decode._inflate( dd, buff ); | ||
@@ -610,3 +596,2 @@ if ( out.interlace == 0 ) dd = UPNG.decode._filterZero( dd, out, 0, w, h ); else if ( out.interlace == 1 ) dd = UPNG.decode._readInterlace( dd, out ); | ||
H.H = {}; | ||
H.H.N = function ( N, W ) { | ||
@@ -637,3 +622,2 @@ | ||
if ( Z ) W = new R( N.length >>> 2 << 5 ); | ||
while ( i == 0 ) { | ||
@@ -644,3 +628,2 @@ | ||
d += 3; | ||
if ( m == 0 ) { | ||
@@ -660,3 +643,2 @@ | ||
if ( Z ) W = H.H.W( W, w + ( 1 << 17 ) ); | ||
if ( m == 1 ) { | ||
@@ -678,3 +660,2 @@ | ||
var j = 1; | ||
for ( var c = 0; c < 38; c += 2 ) { | ||
@@ -717,3 +698,2 @@ | ||
var p = T >>> 4; | ||
if ( p >>> 8 == 0 ) { | ||
@@ -730,3 +710,2 @@ | ||
var z = w + p - 254; | ||
if ( p > 264 ) { | ||
@@ -746,3 +725,2 @@ | ||
d += Y & 15; | ||
while ( w < z ) { | ||
@@ -784,3 +762,2 @@ | ||
I = 0; | ||
while ( I < R ) { | ||
@@ -791,3 +768,2 @@ | ||
var b = e >>> 4; | ||
if ( b <= 15 ) { | ||
@@ -802,3 +778,2 @@ | ||
m = 0; | ||
if ( b == 16 ) { | ||
@@ -823,3 +798,2 @@ | ||
var J = I + m; | ||
while ( I < J ) { | ||
@@ -845,3 +819,2 @@ | ||
l = V.length >>> 1; | ||
while ( A < R ) { | ||
@@ -879,11 +852,7 @@ | ||
e = R.j; | ||
for ( var M = 0; M <= W; M ++ ) e[ M ] = 0; | ||
for ( M = 1; M < V; M += 2 ) e[ N[ M ] ] ++; | ||
var b = R.K; | ||
n = 0; | ||
e[ 0 ] = 0; | ||
for ( A = 1; A <= W; A ++ ) { | ||
@@ -899,3 +868,2 @@ | ||
I = N[ l + 1 ]; | ||
if ( I != 0 ) { | ||
@@ -917,3 +885,2 @@ | ||
A = n.r; | ||
for ( var l = 0; l < V; l += 2 ) if ( N[ l + 1 ] != 0 ) { | ||
@@ -927,3 +894,2 @@ | ||
m = Z + ( 1 << b ); | ||
while ( Z != m ) { | ||
@@ -945,3 +911,2 @@ | ||
V = 15 - W; | ||
for ( var n = 0; n < N.length; n += 2 ) { | ||
@@ -1034,3 +999,2 @@ | ||
}(); | ||
( function () { | ||
@@ -1040,3 +1004,2 @@ | ||
W = 1 << 15; | ||
for ( var R = 0; R < W; R ++ ) { | ||
@@ -1087,3 +1050,2 @@ | ||
}(); | ||
UPNG.decode._readInterlace = function ( data, out ) { | ||
@@ -1093,7 +1055,5 @@ | ||
h = out.height; | ||
var bpp = UPNG.decode._getBPP( out ), | ||
cbpp = bpp >> 3, | ||
bpl = Math.ceil( w * bpp / 8 ); | ||
var img = new Uint8Array( h * bpl ); | ||
@@ -1106,3 +1066,2 @@ var di = 0; | ||
var pass = 0; | ||
while ( pass < 7 ) { | ||
@@ -1115,3 +1074,2 @@ | ||
var cr = starting_row[ pass ]; | ||
while ( cr < h ) { | ||
@@ -1125,3 +1083,2 @@ | ||
var cc = starting_col[ pass ]; | ||
while ( cc < w ) { | ||
@@ -1135,9 +1092,6 @@ | ||
var bpll = Math.ceil( sw * bpp / 8 ); | ||
UPNG.decode._filterZero( data, out, di, sw, sh ); | ||
var y = 0, | ||
row = starting_row[ pass ]; | ||
var val; | ||
while ( row < h ) { | ||
@@ -1147,3 +1101,2 @@ | ||
var cdi = di + y * bpll << 3; | ||
while ( col < w ) { | ||
@@ -1178,3 +1131,2 @@ | ||
var ii = row * bpl + col * cbpp; | ||
for ( var j = 0; j < cbpp; j ++ ) img[ ii + j ] = data[ ( cdi >> 3 ) + j ]; | ||
@@ -1215,3 +1167,2 @@ | ||
paeth = UPNG.decode._paeth; | ||
bpp = Math.ceil( bpp / 8 ); | ||
@@ -1224,3 +1175,2 @@ var i, | ||
if ( type == 3 ) for ( x = bpp; x < bpl; x ++ ) data[ x + 1 ] = data[ x + 1 ] + ( data[ x + 1 - bpp ] >>> 1 ) & 255; | ||
for ( var y = 0; y < h; y ++ ) { | ||
@@ -1235,3 +1185,2 @@ | ||
for ( ; x < bpp; x ++ ) data[ i + x ] = data[ di + x ]; | ||
for ( ; x < bpl; x ++ ) data[ i + x ] = data[ di + x ] + data[ i + x - bpp ]; | ||
@@ -1246,3 +1195,2 @@ | ||
for ( ; x < bpp; x ++ ) data[ i + x ] = data[ di + x ] + ( data[ i + x - bpl ] >>> 1 ); | ||
for ( ; x < bpl; x ++ ) data[ i + x ] = data[ di + x ] + ( data[ i + x - bpl ] + data[ i + x - bpp ] >>> 1 ); | ||
@@ -1253,3 +1201,2 @@ | ||
for ( ; x < bpp; x ++ ) data[ i + x ] = data[ di + x ] + paeth( 0, data[ i + x - bpl ], 0 ); | ||
for ( ; x < bpl; x ++ ) data[ i + x ] = data[ di + x ] + paeth( data[ i + x - bpp ], data[ i + x - bpl ], data[ i + x - bpp - bpl ] ); | ||
@@ -1300,3 +1247,2 @@ | ||
while ( data[ p ] != 0 ) p ++; | ||
return p; | ||
@@ -1332,5 +1278,3 @@ | ||
var s = ''; | ||
for ( var i = 0; i < l; i ++ ) s += String.fromCharCode( buff[ p + i ] ); | ||
return s; | ||
@@ -1347,5 +1291,3 @@ | ||
var arr = []; | ||
for ( var i = 0; i < l; i ++ ) arr.push( buff[ p + i ] ); | ||
return arr; | ||
@@ -1363,5 +1305,3 @@ | ||
ns; | ||
for ( var i = 0; i < l; i ++ ) s += '%' + UPNG._bin.pad( buff[ p + i ].toString( 16 ) ); | ||
try { | ||
@@ -1381,3 +1321,2 @@ | ||
}; | ||
UPNG._copyTile = function ( sb, sw, sh, tb, tw, th, xoff, yoff, mode ) { | ||
@@ -1389,3 +1328,2 @@ | ||
ti = 0; | ||
for ( var y = 0; y < h; y ++ ) for ( var x = 0; x < w; x ++ ) { | ||
@@ -1433,2 +1371,3 @@ | ||
// copy only differences, otherwise zero | ||
var fa = sb[ si + 3 ], | ||
@@ -1442,3 +1381,2 @@ fr = sb[ si ], | ||
bb = tb[ ti + 2 ]; | ||
if ( fa == ba && fr == br && fg == bg && fb == bb ) { | ||
@@ -1463,2 +1401,3 @@ | ||
// check if can be blended | ||
var fa = sb[ si + 3 ], | ||
@@ -1472,4 +1411,4 @@ fr = sb[ si ], | ||
bb = tb[ ti + 2 ]; | ||
if ( fa == ba && fr == br && fg == bg && fb == bb ) continue; //if(fa!=255 && ba!=0) return false; | ||
if ( fa == ba && fr == br && fg == bg && fb == bb ) continue; | ||
//if(fa!=255 && ba!=0) return false; | ||
if ( fa < 220 && ba > 20 ) return false; | ||
@@ -1476,0 +1415,0 @@ |
@@ -61,3 +61,2 @@ ( function () { | ||
} | ||
load( url, onLoad, onProgress, onError ) { | ||
@@ -96,3 +95,2 @@ | ||
} | ||
parse( data ) { | ||
@@ -106,3 +104,2 @@ | ||
const expect = 80 + 32 / 8 + n_faces * face_size; | ||
if ( expect === reader.byteLength ) { | ||
@@ -112,20 +109,24 @@ | ||
} // An ASCII STL data must begin with 'solid ' as the first six bytes. | ||
} | ||
// An ASCII STL data must begin with 'solid ' as the first six bytes. | ||
// However, ASCII STLs lacking the SPACE after the 'd' are known to be | ||
// plentiful. So, check the first 5 bytes for 'solid'. | ||
// Several encodings, such as UTF-8, precede the text with up to 5 bytes: | ||
// https://en.wikipedia.org/wiki/Byte_order_mark#Byte_order_marks_by_encoding | ||
// Search for "solid" to start anywhere after those prefixes. | ||
// US-ASCII ordinal values for 's', 'o', 'l', 'i', 'd' | ||
const solid = [ 115, 111, 108, 105, 100 ]; | ||
for ( let off = 0; off < 5; off ++ ) { | ||
// If "solid" text is matched to the current offset, declare it to be an ASCII STL. | ||
if ( matchDataViewAt( solid, reader, off ) ) return false; | ||
} // Couldn't find "solid" text at the beginning; it is binary STL. | ||
} | ||
// Couldn't find "solid" text at the beginning; it is binary STL. | ||
@@ -139,2 +140,3 @@ return true; | ||
// Check if each byte in query matches the corresponding byte from the current offset | ||
for ( let i = 0, il = query.length; i < il; i ++ ) { | ||
@@ -159,3 +161,5 @@ | ||
colors; | ||
let defaultR, defaultG, defaultB, alpha; // process STL header | ||
let defaultR, defaultG, defaultB, alpha; | ||
// process STL header | ||
// check for default color in header ("COLOR=rgba" sequence). | ||
@@ -165,9 +169,3 @@ | ||
if ( reader.getUint32( index, false ) == 0x434F4C4F | ||
/*COLO*/ | ||
&& reader.getUint8( index + 4 ) == 0x52 | ||
/*'R'*/ | ||
&& reader.getUint8( index + 5 ) == 0x3D | ||
/*'='*/ | ||
) { | ||
if ( reader.getUint32( index, false ) == 0x434F4C4F /*COLO*/ && reader.getUint8( index + 4 ) == 0x52 /*'R'*/ && reader.getUint8( index + 5 ) == 0x3D /*'='*/ ) { | ||
@@ -190,3 +188,2 @@ hasColors = true; | ||
const normals = new Float32Array( faces * 3 * 3 ); | ||
for ( let face = 0; face < faces; face ++ ) { | ||
@@ -198,10 +195,9 @@ | ||
const normalZ = reader.getFloat32( start + 8, true ); | ||
if ( hasColors ) { | ||
const packedColor = reader.getUint16( start + 48, true ); | ||
if ( ( packedColor & 0x8000 ) === 0 ) { | ||
// facet has its own unique color | ||
r = ( packedColor & 0x1F ) / 31; | ||
@@ -231,3 +227,2 @@ g = ( packedColor >> 5 & 0x1F ) / 31; | ||
normals[ componentIdx + 2 ] = normalZ; | ||
if ( hasColors ) { | ||
@@ -247,3 +242,2 @@ | ||
geometry.setAttribute( 'normal', new THREE.BufferAttribute( normals, 3 ) ); | ||
if ( hasColors ) { | ||
@@ -277,3 +271,2 @@ | ||
let endVertex = 0; | ||
while ( ( result = patternSolid.exec( data ) ) !== null ) { | ||
@@ -283,3 +276,2 @@ | ||
const solid = result[ 0 ]; | ||
while ( ( result = patternFace.exec( solid ) ) !== null ) { | ||
@@ -290,3 +282,2 @@ | ||
const text = result[ 0 ]; | ||
while ( ( result = patternNormal.exec( text ) ) !== null ) { | ||
@@ -308,4 +299,5 @@ | ||
} // every face have to own ONE valid normal | ||
} | ||
// every face have to own ONE valid normal | ||
@@ -316,4 +308,5 @@ if ( normalCountPerFace !== 1 ) { | ||
} // each face have to own THREE valid vertices | ||
} | ||
// each face have to own THREE valid vertices | ||
@@ -360,3 +353,2 @@ if ( vertexCountPerFace !== 3 ) { | ||
const array_buffer = new Uint8Array( buffer.length ); | ||
for ( let i = 0; i < buffer.length; i ++ ) { | ||
@@ -376,4 +368,5 @@ | ||
} // start | ||
} | ||
// start | ||
@@ -380,0 +373,0 @@ const binData = ensureBinary( data ); |
@@ -23,2 +23,3 @@ ( function () { | ||
} | ||
/** | ||
@@ -33,4 +34,2 @@ * Load 3ds file from url. | ||
*/ | ||
load( url, onLoad, onProgress, onError ) { | ||
@@ -70,2 +69,3 @@ | ||
} | ||
/** | ||
@@ -79,4 +79,2 @@ * Parse arraybuffer data and load 3ds file. | ||
*/ | ||
parse( arraybuffer, path ) { | ||
@@ -88,3 +86,2 @@ | ||
this.readFile( arraybuffer, path ); | ||
for ( let i = 0; i < this.meshes.length; i ++ ) { | ||
@@ -99,2 +96,3 @@ | ||
} | ||
/** | ||
@@ -107,4 +105,2 @@ * Decode file content to read 3ds data. | ||
*/ | ||
readFile( arraybuffer, path ) { | ||
@@ -114,7 +110,5 @@ | ||
const chunk = new Chunk( data, 0, this.debugMessage ); | ||
if ( chunk.id === MLIBMAGIC || chunk.id === CMAGIC || chunk.id === M3DMAGIC ) { | ||
let next = chunk.readChunk(); | ||
while ( next ) { | ||
@@ -146,2 +140,3 @@ | ||
} | ||
/** | ||
@@ -154,8 +149,5 @@ * Read mesh data chunk. | ||
*/ | ||
readMeshData( chunk, path ) { | ||
let next = chunk.readChunk(); | ||
while ( next ) { | ||
@@ -195,2 +187,3 @@ | ||
} | ||
/** | ||
@@ -202,4 +195,2 @@ * Read named object chunk. | ||
*/ | ||
readNamedObject( chunk ) { | ||
@@ -209,3 +200,2 @@ | ||
let next = chunk.readChunk(); | ||
while ( next ) { | ||
@@ -230,2 +220,3 @@ | ||
} | ||
/** | ||
@@ -238,4 +229,2 @@ * Read material data chunk and add it to the material list. | ||
*/ | ||
readMaterialEntry( chunk, path ) { | ||
@@ -245,3 +234,2 @@ | ||
const material = new THREE.MeshPhongMaterial(); | ||
while ( next ) { | ||
@@ -336,2 +324,3 @@ | ||
} | ||
/** | ||
@@ -344,4 +333,2 @@ * Read mesh data chunk. | ||
*/ | ||
readMesh( chunk ) { | ||
@@ -354,3 +341,2 @@ | ||
mesh.name = 'mesh'; | ||
while ( next ) { | ||
@@ -361,6 +347,7 @@ | ||
const points = next.readWord(); | ||
this.debugMessage( ' Vertex: ' + points ); //BufferGeometry | ||
this.debugMessage( ' Vertex: ' + points ); | ||
//BufferGeometry | ||
const vertices = []; | ||
for ( let i = 0; i < points; i ++ ) { | ||
@@ -383,6 +370,7 @@ | ||
const texels = next.readWord(); | ||
this.debugMessage( ' UV: ' + texels ); //BufferGeometry | ||
this.debugMessage( ' UV: ' + texels ); | ||
//BufferGeometry | ||
const uvs = []; | ||
for ( let i = 0; i < texels; i ++ ) { | ||
@@ -401,3 +389,2 @@ | ||
const values = []; | ||
for ( let i = 0; i < 12; i ++ ) { | ||
@@ -409,19 +396,23 @@ | ||
const matrix = new THREE.Matrix4(); //X Line | ||
const matrix = new THREE.Matrix4(); | ||
//X Line | ||
matrix.elements[ 0 ] = values[ 0 ]; | ||
matrix.elements[ 1 ] = values[ 6 ]; | ||
matrix.elements[ 2 ] = values[ 3 ]; | ||
matrix.elements[ 3 ] = values[ 9 ]; //Y Line | ||
matrix.elements[ 3 ] = values[ 9 ]; | ||
//Y Line | ||
matrix.elements[ 4 ] = values[ 2 ]; | ||
matrix.elements[ 5 ] = values[ 8 ]; | ||
matrix.elements[ 6 ] = values[ 5 ]; | ||
matrix.elements[ 7 ] = values[ 11 ]; //Z Line | ||
matrix.elements[ 7 ] = values[ 11 ]; | ||
//Z Line | ||
matrix.elements[ 8 ] = values[ 1 ]; | ||
matrix.elements[ 9 ] = values[ 7 ]; | ||
matrix.elements[ 10 ] = values[ 4 ]; | ||
matrix.elements[ 11 ] = values[ 10 ]; //W Line | ||
matrix.elements[ 11 ] = values[ 10 ]; | ||
//W Line | ||
matrix.elements[ 12 ] = 0; | ||
@@ -451,2 +442,3 @@ matrix.elements[ 13 ] = 0; | ||
} | ||
/** | ||
@@ -459,4 +451,2 @@ * Read face array data chunk. | ||
*/ | ||
readFaceArray( chunk, mesh ) { | ||
@@ -467,3 +457,2 @@ | ||
const index = []; | ||
for ( let i = 0; i < faces; ++ i ) { | ||
@@ -476,11 +465,11 @@ | ||
mesh.geometry.setIndex( index ); //The rest of the FACE_ARRAY chunk is subchunks | ||
mesh.geometry.setIndex( index ); | ||
//The rest of the FACE_ARRAY chunk is subchunks | ||
let materialIndex = 0; | ||
let start = 0; | ||
while ( ! chunk.endOfChunk ) { | ||
const subchunk = chunk.readChunk(); | ||
if ( subchunk.id === MSH_MAT_GROUP ) { | ||
@@ -497,3 +486,2 @@ | ||
if ( Array.isArray( mesh.material ) === false ) mesh.material = []; | ||
if ( material !== undefined ) { | ||
@@ -516,2 +504,3 @@ | ||
} | ||
/** | ||
@@ -525,4 +514,2 @@ * Read texture map data chunk. | ||
*/ | ||
readMap( chunk, path ) { | ||
@@ -534,3 +521,2 @@ | ||
loader.setPath( this.resourcePath || path ).setCrossOrigin( this.crossOrigin ); | ||
while ( next ) { | ||
@@ -577,2 +563,3 @@ | ||
} | ||
/** | ||
@@ -585,4 +572,2 @@ * Read material group data chunk. | ||
*/ | ||
readMaterialGroup( chunk ) { | ||
@@ -595,3 +580,2 @@ | ||
const index = []; | ||
for ( let i = 0; i < numFaces; ++ i ) { | ||
@@ -609,2 +593,3 @@ | ||
} | ||
/** | ||
@@ -617,4 +602,2 @@ * Read a color value. | ||
*/ | ||
readColor( chunk ) { | ||
@@ -624,3 +607,2 @@ | ||
const color = new THREE.Color(); | ||
if ( subChunk.id === COLOR_24 || subChunk.id === LIN_COLOR_24 ) { | ||
@@ -651,2 +633,3 @@ | ||
} | ||
/** | ||
@@ -659,8 +642,5 @@ * Read percentage value. | ||
*/ | ||
readPercentage( chunk ) { | ||
const subChunk = chunk.readChunk(); | ||
switch ( subChunk.id ) { | ||
@@ -671,7 +651,5 @@ | ||
break; | ||
case FLOAT_PERCENTAGE: | ||
return subChunk.readFloat(); | ||
break; | ||
default: | ||
@@ -684,2 +662,3 @@ this.debugMessage( ' Unknown percentage chunk: ' + subChunk.hexId ); | ||
} | ||
/** | ||
@@ -693,4 +672,2 @@ * Print debug message to the console. | ||
*/ | ||
debugMessage( message ) { | ||
@@ -707,5 +684,4 @@ | ||
} | ||
/** Read data/sub-chunks from chunk */ | ||
class Chunk { | ||
@@ -723,9 +699,8 @@ | ||
this.data = data; // the offset to the begin of this chunk | ||
this.offset = position; // the current reading position | ||
this.data = data; | ||
// the offset to the begin of this chunk | ||
this.offset = position; | ||
// the current reading position | ||
this.position = position; | ||
this.debugMessage = debugMessage; | ||
if ( this.debugMessage instanceof Function ) { | ||
@@ -740,3 +715,2 @@ | ||
this.end = this.offset + this.size; | ||
if ( this.end > data.byteLength ) { | ||
@@ -749,2 +723,3 @@ | ||
} | ||
/** | ||
@@ -756,4 +731,2 @@ * read a sub cchunk. | ||
*/ | ||
readChunk() { | ||
@@ -781,2 +754,3 @@ | ||
} | ||
/** | ||
@@ -788,4 +762,2 @@ * return the ID of this chunk as Hex | ||
*/ | ||
get hexId() { | ||
@@ -796,3 +768,2 @@ | ||
} | ||
get endOfChunk() { | ||
@@ -803,2 +774,3 @@ | ||
} | ||
/** | ||
@@ -810,4 +782,2 @@ * Read byte value. | ||
*/ | ||
readByte() { | ||
@@ -820,2 +790,3 @@ | ||
} | ||
/** | ||
@@ -827,4 +798,2 @@ * Read 32 bit float value. | ||
*/ | ||
readFloat() { | ||
@@ -846,2 +815,3 @@ | ||
} | ||
/** | ||
@@ -853,4 +823,2 @@ * Read 32 bit signed integer value. | ||
*/ | ||
readInt() { | ||
@@ -863,2 +831,3 @@ | ||
} | ||
/** | ||
@@ -870,4 +839,2 @@ * Read 16 bit signed integer value. | ||
*/ | ||
readShort() { | ||
@@ -880,2 +847,3 @@ | ||
} | ||
/** | ||
@@ -887,4 +855,2 @@ * Read 64 bit unsigned integer value. | ||
*/ | ||
readDWord() { | ||
@@ -897,2 +863,3 @@ | ||
} | ||
/** | ||
@@ -904,4 +871,2 @@ * Read 32 bit unsigned integer value. | ||
*/ | ||
readWord() { | ||
@@ -914,2 +879,3 @@ | ||
} | ||
/** | ||
@@ -921,4 +887,2 @@ * Read NULL terminated ASCII string value from chunk-pos. | ||
*/ | ||
readString() { | ||
@@ -928,3 +892,2 @@ | ||
let c = this.readByte(); | ||
while ( c ) { | ||
@@ -941,13 +904,13 @@ | ||
} // const NULL_CHUNK = 0x0000; | ||
} | ||
const M3DMAGIC = 0x4D4D; // const SMAGIC = 0x2D2D; | ||
// const NULL_CHUNK = 0x0000; | ||
const M3DMAGIC = 0x4D4D; | ||
// const SMAGIC = 0x2D2D; | ||
// const LMAGIC = 0x2D3D; | ||
const MLIBMAGIC = 0x3DAA; // const MATMAGIC = 0x3DFF; | ||
const MLIBMAGIC = 0x3DAA; | ||
// const MATMAGIC = 0x3DFF; | ||
const CMAGIC = 0xC23D; | ||
const M3D_VERSION = 0x0002; // const M3D_KFVERSION = 0x0005; | ||
const M3D_VERSION = 0x0002; | ||
// const M3D_KFVERSION = 0x0005; | ||
const COLOR_F = 0x0010; | ||
@@ -961,3 +924,4 @@ const COLOR_24 = 0x0011; | ||
const MESH_VERSION = 0x3D3E; | ||
const MASTER_SCALE = 0x0100; // const LO_SHADOW_BIAS = 0x1400; | ||
const MASTER_SCALE = 0x0100; | ||
// const LO_SHADOW_BIAS = 0x1400; | ||
// const HI_SHADOW_BIAS = 0x1410; | ||
@@ -985,3 +949,2 @@ // const SHADOW_MAP_SIZE = 0x1420; | ||
// const USE_DISTANCE_CUE = 0x2301; | ||
const MAT_ENTRY = 0xAFFF; | ||
@@ -992,5 +955,6 @@ const MAT_NAME = 0xA000; | ||
const MAT_SPECULAR = 0xA030; | ||
const MAT_SHININESS = 0xA040; // const MAT_SHIN2PCT = 0xA041; | ||
const MAT_TRANSPARENCY = 0xA050; // const MAT_XPFALL = 0xA052; | ||
const MAT_SHININESS = 0xA040; | ||
// const MAT_SHIN2PCT = 0xA041; | ||
const MAT_TRANSPARENCY = 0xA050; | ||
// const MAT_XPFALL = 0xA052; | ||
// const MAT_USE_XPFALL = 0xA240; | ||
@@ -1001,13 +965,13 @@ // const MAT_REFBLUR = 0xA053; | ||
// const MAT_SELF_ILLUM = 0xA084; | ||
const MAT_TWO_SIDE = 0xA081; // const MAT_DECAL = 0xA082; | ||
const MAT_TWO_SIDE = 0xA081; | ||
// const MAT_DECAL = 0xA082; | ||
const MAT_ADDITIVE = 0xA083; | ||
const MAT_WIRE = 0xA085; // const MAT_FACEMAP = 0xA088; | ||
const MAT_WIRE = 0xA085; | ||
// const MAT_FACEMAP = 0xA088; | ||
// const MAT_TRANSFALLOFF_IN = 0xA08A; | ||
// const MAT_PHONGSOFT = 0xA08C; | ||
// const MAT_WIREABS = 0xA08E; | ||
const MAT_WIRE_SIZE = 0xA087; | ||
const MAT_TEXMAP = 0xA200; // const MAT_SXP_TEXT_DATA = 0xA320; | ||
const MAT_TEXMAP = 0xA200; | ||
// const MAT_SXP_TEXT_DATA = 0xA320; | ||
// const MAT_TEXMASK = 0xA33E; | ||
@@ -1019,12 +983,12 @@ // const MAT_SXP_TEXTMASK_DATA = 0xA32A; | ||
// const MAT_SXP_TEXT2MASK_DATA = 0xA32C; | ||
const MAT_OPACMAP = 0xA210; // const MAT_SXP_OPAC_DATA = 0xA322; | ||
const MAT_OPACMAP = 0xA210; | ||
// const MAT_SXP_OPAC_DATA = 0xA322; | ||
// const MAT_OPACMASK = 0xA342; | ||
// const MAT_SXP_OPACMASK_DATA = 0xA32E; | ||
const MAT_BUMPMAP = 0xA230; // const MAT_SXP_BUMP_DATA = 0xA324; | ||
const MAT_BUMPMAP = 0xA230; | ||
// const MAT_SXP_BUMP_DATA = 0xA324; | ||
// const MAT_BUMPMASK = 0xA344; | ||
// const MAT_SXP_BUMPMASK_DATA = 0xA330; | ||
const MAT_SPECMAP = 0xA204; // const MAT_SXP_SPEC_DATA = 0xA325; | ||
const MAT_SPECMAP = 0xA204; | ||
// const MAT_SXP_SPEC_DATA = 0xA325; | ||
// const MAT_SPECMASK = 0xA348; | ||
@@ -1044,10 +1008,10 @@ // const MAT_SXP_SPECMASK_DATA = 0xA332; | ||
// const MAT_ACUBIC = 0xA310; | ||
const MAT_MAPNAME = 0xA300; // const MAT_MAP_TILING = 0xA351; | ||
const MAT_MAPNAME = 0xA300; | ||
// const MAT_MAP_TILING = 0xA351; | ||
// const MAT_MAP_TEXBLUR = 0xA353; | ||
const MAT_MAP_USCALE = 0xA354; | ||
const MAT_MAP_VSCALE = 0xA356; | ||
const MAT_MAP_UOFFSET = 0xA358; | ||
const MAT_MAP_VOFFSET = 0xA35A; // const MAT_MAP_ANG = 0xA35C; | ||
const MAT_MAP_VOFFSET = 0xA35A; | ||
// const MAT_MAP_ANG = 0xA35C; | ||
// const MAT_MAP_COL1 = 0xA360; | ||
@@ -1058,4 +1022,4 @@ // const MAT_MAP_COL2 = 0xA362; | ||
// const MAT_MAP_BCOL = 0xA368; | ||
const NAMED_OBJECT = 0x4000; // const N_DIRECT_LIGHT = 0x4600; | ||
const NAMED_OBJECT = 0x4000; | ||
// const N_DIRECT_LIGHT = 0x4600; | ||
// const DL_OFF = 0x4620; | ||
@@ -1089,12 +1053,11 @@ // const DL_OUTER_RANGE = 0x465A; | ||
// const OBJ_FROZEN = 0x4016; | ||
const N_TRI_OBJECT = 0x4100; | ||
const POINT_ARRAY = 0x4110; // const POINT_FLAG_ARRAY = 0x4111; | ||
const POINT_ARRAY = 0x4110; | ||
// const POINT_FLAG_ARRAY = 0x4111; | ||
const FACE_ARRAY = 0x4120; | ||
const MSH_MAT_GROUP = 0x4130; // const SMOOTH_GROUP = 0x4150; | ||
const MSH_MAT_GROUP = 0x4130; | ||
// const SMOOTH_GROUP = 0x4150; | ||
// const MSH_BOXMAP = 0x4190; | ||
const TEX_VERTS = 0x4140; | ||
const MESH_MATRIX = 0x4160; // const MESH_COLOR = 0x4165; | ||
const MESH_MATRIX = 0x4160; | ||
@@ -1101,0 +1064,0 @@ THREE.TDSLoader = TDSLoader; |
@@ -10,6 +10,6 @@ ( function () { | ||
} | ||
parse( buffer ) { | ||
// reference from vthibault, https://github.com/vthibault/roBrowser/blob/master/src/Loaders/Targa.js | ||
function tgaCheckHeader( header ) { | ||
@@ -20,2 +20,3 @@ | ||
// check indexed type | ||
case TGA_TYPE_INDEXED: | ||
@@ -30,2 +31,3 @@ case TGA_TYPE_RLE_INDEXED: | ||
break; | ||
// check colormap type | ||
@@ -44,2 +46,3 @@ | ||
break; | ||
// What the need of a file without data ? | ||
@@ -49,2 +52,3 @@ | ||
console.error( 'THREE.TGALoader: No data.' ); | ||
// Invalid type ? | ||
@@ -55,4 +59,5 @@ | ||
} // check image width and height | ||
} | ||
// check image width and height | ||
@@ -63,4 +68,5 @@ if ( header.width <= 0 || header.height <= 0 ) { | ||
} // check image pixel size | ||
} | ||
// check image pixel size | ||
@@ -73,4 +79,5 @@ if ( header.pixel_size !== 8 && header.pixel_size !== 16 && header.pixel_size !== 24 && header.pixel_size !== 32 ) { | ||
} // parse tga image buffer | ||
} | ||
// parse tga image buffer | ||
@@ -81,4 +88,6 @@ function tgaParse( use_rle, use_pal, header, offset, data ) { | ||
const pixel_size = header.pixel_size >> 3; | ||
const pixel_total = header.width * header.height * pixel_size; // read palettes | ||
const pixel_total = header.width * header.height * pixel_size; | ||
// read palettes | ||
if ( use_pal ) { | ||
@@ -88,4 +97,5 @@ | ||
} // read RLE | ||
} | ||
// read RLE | ||
@@ -98,11 +108,13 @@ if ( use_rle ) { | ||
const pixels = new Uint8Array( pixel_size ); | ||
while ( shift < pixel_total ) { | ||
c = data[ offset ++ ]; | ||
count = ( c & 0x7f ) + 1; // RLE pixels | ||
count = ( c & 0x7f ) + 1; | ||
// RLE pixels | ||
if ( c & 0x80 ) { | ||
// bind pixel tmp array | ||
for ( i = 0; i < pixel_size; ++ i ) { | ||
@@ -112,4 +124,5 @@ | ||
} // copy pixel array | ||
} | ||
// copy pixel array | ||
@@ -127,4 +140,4 @@ for ( i = 0; i < count; ++ i ) { | ||
// raw pixels | ||
count *= pixel_size; | ||
for ( i = 0; i < count; ++ i ) { | ||
@@ -145,2 +158,3 @@ | ||
// raw pixels | ||
pixel_data = data.subarray( offset, offset += use_pal ? header.width * header.height : pixel_total ); | ||
@@ -165,3 +179,2 @@ | ||
const width = header.width; | ||
for ( y = y_start; y !== y_end; y += y_step ) { | ||
@@ -192,3 +205,2 @@ | ||
const width = header.width; | ||
for ( y = y_start; y !== y_end; y += y_step ) { | ||
@@ -218,3 +230,2 @@ | ||
const width = header.width; | ||
for ( y = y_start; y !== y_end; y += y_step ) { | ||
@@ -243,3 +254,2 @@ | ||
const width = header.width; | ||
for ( y = y_start; y !== y_end; y += y_step ) { | ||
@@ -269,3 +279,2 @@ | ||
const width = header.width; | ||
for ( y = y_start; y !== y_end; y += y_step ) { | ||
@@ -295,3 +304,2 @@ | ||
const width = header.width; | ||
for ( y = y_start; y !== y_end; y += y_step ) { | ||
@@ -317,3 +325,2 @@ | ||
let x_start, y_start, x_step, y_step, x_end, y_end; | ||
switch ( ( header.flags & TGA_ORIGIN_MASK ) >> TGA_ORIGIN_SHIFT ) { | ||
@@ -330,3 +337,2 @@ | ||
break; | ||
case TGA_ORIGIN_BL: | ||
@@ -340,3 +346,2 @@ x_start = 0; | ||
break; | ||
case TGA_ORIGIN_UR: | ||
@@ -350,3 +355,2 @@ x_start = width - 1; | ||
break; | ||
case TGA_ORIGIN_BR: | ||
@@ -370,7 +374,5 @@ x_start = width - 1; | ||
break; | ||
case 16: | ||
tgaGetImageDataGrey16bits( data, y_start, y_step, y_end, x_start, x_step, x_end, image ); | ||
break; | ||
default: | ||
@@ -389,15 +391,11 @@ console.error( 'THREE.TGALoader: Format not supported.' ); | ||
break; | ||
case 16: | ||
tgaGetImageData16bits( data, y_start, y_step, y_end, x_start, x_step, x_end, image ); | ||
break; | ||
case 24: | ||
tgaGetImageData24bits( data, y_start, y_step, y_end, x_start, x_step, x_end, image ); | ||
break; | ||
case 32: | ||
tgaGetImageData32bits( data, y_start, y_step, y_end, x_start, x_step, x_end, image ); | ||
break; | ||
default: | ||
@@ -409,11 +407,12 @@ console.error( 'THREE.TGALoader: Format not supported.' ); | ||
} // Load image data according to specific method | ||
} | ||
// Load image data according to specific method | ||
// let func = 'tgaGetImageData' + (use_grey ? 'Grey' : '') + (header.pixel_size) + 'bits'; | ||
// func(data, y_start, y_step, y_end, x_start, x_step, x_end, width, image, palette ); | ||
return data; | ||
} // TGA constants | ||
} | ||
// TGA constants | ||
@@ -448,6 +447,7 @@ const TGA_TYPE_NO_DATA = 0, | ||
flags: content[ offset ++ ] | ||
}; // check tga if it is valid format | ||
}; | ||
// check tga if it is valid format | ||
tgaCheckHeader( header ); | ||
if ( header.id_length + offset > buffer.length ) { | ||
@@ -457,11 +457,13 @@ | ||
} // skip the needn't data | ||
} | ||
// skip the needn't data | ||
offset += header.id_length; // get targa information about RLE compression and palette | ||
offset += header.id_length; | ||
// get targa information about RLE compression and palette | ||
let use_rle = false, | ||
use_pal = false, | ||
use_grey = false; | ||
switch ( header.image_type ) { | ||
@@ -473,14 +475,10 @@ | ||
break; | ||
case TGA_TYPE_INDEXED: | ||
use_pal = true; | ||
break; | ||
case TGA_TYPE_RLE_RGB: | ||
use_rle = true; | ||
break; | ||
case TGA_TYPE_RGB: | ||
break; | ||
case TGA_TYPE_RLE_GREY: | ||
@@ -490,3 +488,2 @@ use_rle = true; | ||
break; | ||
case TGA_TYPE_GREY: | ||
@@ -496,4 +493,5 @@ use_grey = true; | ||
} // | ||
} | ||
// | ||
@@ -500,0 +498,0 @@ const imageData = new Uint8Array( header.width * header.height * 4 ); |
@@ -10,3 +10,2 @@ ( function () { | ||
} | ||
parse( buffer ) { | ||
@@ -13,0 +12,0 @@ |
@@ -37,8 +37,9 @@ ( function () { | ||
} | ||
parse( buffer ) { | ||
const group = new THREE.Group(); // https://docs.google.com/document/d/11ZsHozYn9FnWG7y3s3WAyKIACfbfwb4PbaS8cZ_xjvo/edit# | ||
const group = new THREE.Group(); | ||
// https://docs.google.com/document/d/11ZsHozYn9FnWG7y3s3WAyKIACfbfwb4PbaS8cZ_xjvo/edit# | ||
const zip = fflate.unzipSync( new Uint8Array( buffer.slice( 16 ) ) ); | ||
/* | ||
@@ -52,2 +53,3 @@ const thumbnail = zip[ 'thumbnail.png' ].buffer; | ||
const metadata = JSON.parse( fflate.strFromU8( zip[ 'metadata.json' ] ) ); | ||
/* | ||
@@ -62,3 +64,2 @@ const blob = new Blob( [ zip[ 'data.sketch' ].buffer ], { type: 'application/octet-stream' } ); | ||
let offset = 20; | ||
for ( let i = 0; i < num_strokes; i ++ ) { | ||
@@ -73,6 +74,6 @@ | ||
let offset_controlpoint_mask = 0; | ||
for ( let j = 0; j < 4; j ++ ) { | ||
// TOFIX: I don't understand these masks yet | ||
const byte = 1 << j; | ||
@@ -82,14 +83,16 @@ if ( ( stroke_mask & byte ) > 0 ) offset_stroke_mask += 4; | ||
} // console.log( { brush_index, brush_color, brush_size, stroke_mask, controlpoint_mask } ); | ||
} | ||
// console.log( { brush_index, brush_color, brush_size, stroke_mask, controlpoint_mask } ); | ||
// console.log( offset_stroke_mask, offset_controlpoint_mask ); | ||
offset = offset + 28 + offset_stroke_mask + 4; // TOFIX: This is wrong | ||
const num_control_points = data.getInt32( offset, true ); // console.log( { num_control_points } ); | ||
const num_control_points = data.getInt32( offset, true ); | ||
// console.log( { num_control_points } ); | ||
const positions = new Float32Array( num_control_points * 3 ); | ||
const quaternions = new Float32Array( num_control_points * 4 ); | ||
offset = offset + 4; | ||
for ( let j = 0, k = 0; j < positions.length; j += 3, k += 4 ) { | ||
@@ -131,3 +134,2 @@ | ||
} | ||
class StrokeGeometry extends THREE.BufferGeometry { | ||
@@ -148,4 +150,6 @@ | ||
const vector3 = new THREE.Vector3(); | ||
const vector4 = new THREE.Vector3(); // size = size / 2; | ||
const vector4 = new THREE.Vector3(); | ||
// size = size / 2; | ||
for ( const k in strokes ) { | ||
@@ -160,3 +164,2 @@ | ||
prevQuaternion.fromArray( quaternions, 0 ); | ||
for ( let i = 3, j = 4, l = positions.length; i < l; i += 3, j += 4 ) { | ||
@@ -212,3 +215,2 @@ | ||
} | ||
const BRUSH_LIST_ARRAY = { | ||
@@ -347,3 +349,2 @@ '89d104cd-d012-426b-b5b3-bbaee63ac43c': 'Bubbles', | ||
let shaders = null; | ||
function getShaders() { | ||
@@ -452,3 +453,2 @@ | ||
const name = BRUSH_LIST_ARRAY[ GUID ]; | ||
switch ( name ) { | ||
@@ -458,3 +458,2 @@ | ||
return new THREE.RawShaderMaterial( getShaders().Light ); | ||
default: | ||
@@ -461,0 +460,0 @@ return new THREE.MeshBasicMaterial( { |
@@ -17,3 +17,2 @@ ( function () { | ||
} | ||
load( url, onLoad, onProgress, onError ) { | ||
@@ -52,3 +51,2 @@ | ||
} | ||
parse( arraybuffer ) { | ||
@@ -63,3 +61,2 @@ | ||
const unicodes = Object.keys( glyphIndexMap ); | ||
for ( let i = 0; i < unicodes.length; i ++ ) { | ||
@@ -69,3 +66,2 @@ | ||
const glyph = font.glyphs.glyphs[ glyphIndexMap[ unicode ] ]; | ||
if ( unicode !== undefined ) { | ||
@@ -79,3 +75,2 @@ | ||
}; | ||
if ( reversed ) { | ||
@@ -96,3 +91,2 @@ | ||
token.o += command.type.toLowerCase() + ' '; | ||
if ( command.x !== undefined && command.y !== undefined ) { | ||
@@ -169,3 +163,2 @@ | ||
reversed.push( result ); | ||
for ( let i = p.length - 1; i > 0; i -- ) { | ||
@@ -177,3 +170,2 @@ | ||
}; | ||
if ( command.x2 !== undefined && command.y2 !== undefined ) { | ||
@@ -180,0 +172,0 @@ |
@@ -37,3 +37,2 @@ ( function () { | ||
} | ||
parse( buffer ) { | ||
@@ -44,3 +43,2 @@ | ||
const version = data.getUint32( 4, true ); | ||
if ( id !== 542658390 || version !== 150 ) { | ||
@@ -57,7 +55,5 @@ | ||
const chunks = []; | ||
while ( i < data.byteLength ) { | ||
let id = ''; | ||
for ( let j = 0; j < 4; j ++ ) { | ||
@@ -102,3 +98,2 @@ | ||
const palette = [ 0 ]; | ||
for ( let j = 0; j < 256; j ++ ) { | ||
@@ -116,2 +111,3 @@ | ||
// console.log( id, chunkSize, childChunks ); | ||
i += chunkSize; | ||
@@ -128,3 +124,2 @@ | ||
} | ||
class VOXMesh extends THREE.Mesh { | ||
@@ -136,4 +131,6 @@ | ||
const size = chunk.size; | ||
const palette = chunk.palette; // | ||
const palette = chunk.palette; | ||
// | ||
const vertices = []; | ||
@@ -147,3 +144,2 @@ const colors = []; | ||
const pz = [ 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 1, 1 ]; | ||
function add( tile, x, y, z, r, g, b ) { | ||
@@ -154,3 +150,2 @@ | ||
z += size.y / 2; | ||
for ( let i = 0; i < 18; i += 3 ) { | ||
@@ -163,4 +158,5 @@ | ||
} // Store data in a volume for sampling | ||
} | ||
// Store data in a volume for sampling | ||
@@ -170,3 +166,2 @@ const offsety = size.x; | ||
const array = new Uint8Array( size.x * size.y * size.z ); | ||
for ( let j = 0; j < data.length; j += 4 ) { | ||
@@ -180,7 +175,7 @@ | ||
} // Construct geometry | ||
} | ||
// Construct geometry | ||
let hasColors = false; | ||
for ( let j = 0; j < data.length; j += 4 ) { | ||
@@ -211,3 +206,2 @@ | ||
const material = new THREE.MeshStandardMaterial(); | ||
if ( hasColors ) { | ||
@@ -225,3 +219,2 @@ | ||
} | ||
class VOXData3DTexture extends THREE.Data3DTexture { | ||
@@ -236,3 +229,2 @@ | ||
const array = new Uint8Array( size.x * size.y * size.z ); | ||
for ( let j = 0; j < data.length; j += 4 ) { | ||
@@ -239,0 +231,0 @@ |
@@ -10,3 +10,2 @@ ( function () { | ||
} | ||
load( url, onLoad, onProgress, onError ) { | ||
@@ -45,3 +44,2 @@ | ||
} | ||
parse( data ) { | ||
@@ -52,30 +50,43 @@ | ||
// connectivity of the triangles | ||
const indices = []; // triangles vertices | ||
const indices = []; | ||
const positions = []; // red, green, blue colors in the range 0 to 1 | ||
// triangles vertices | ||
const positions = []; | ||
const colors = []; // normal vector, one per vertex | ||
// red, green, blue colors in the range 0 to 1 | ||
const colors = []; | ||
// normal vector, one per vertex | ||
const normals = []; | ||
let result; // pattern for detecting the end of a number sequence | ||
let result; | ||
const patWord = /^[^\d.\s-]+/; // pattern for reading vertices, 3 floats or integers | ||
// pattern for detecting the end of a number sequence | ||
const patWord = /^[^\d.\s-]+/; | ||
const pat3Floats = /(\-?\d+\.?[\d\-\+e]*)\s+(\-?\d+\.?[\d\-\+e]*)\s+(\-?\d+\.?[\d\-\+e]*)/g; // pattern for connectivity, an integer followed by any number of ints | ||
// pattern for reading vertices, 3 floats or integers | ||
const pat3Floats = /(\-?\d+\.?[\d\-\+e]*)\s+(\-?\d+\.?[\d\-\+e]*)\s+(\-?\d+\.?[\d\-\+e]*)/g; | ||
// pattern for connectivity, an integer followed by any number of ints | ||
// the first integer is the number of polygon nodes | ||
const patConnectivity = /^(\d+)\s+([\s\d]*)/; | ||
const patConnectivity = /^(\d+)\s+([\s\d]*)/; // indicates start of vertex data section | ||
// indicates start of vertex data section | ||
const patPOINTS = /^POINTS /; | ||
const patPOINTS = /^POINTS /; // indicates start of polygon connectivity section | ||
// indicates start of polygon connectivity section | ||
const patPOLYGONS = /^POLYGONS /; | ||
const patPOLYGONS = /^POLYGONS /; // indicates start of triangle strips section | ||
// indicates start of triangle strips section | ||
const patTRIANGLE_STRIPS = /^TRIANGLE_STRIPS /; | ||
const patTRIANGLE_STRIPS = /^TRIANGLE_STRIPS /; // POINT_DATA number_of_values | ||
// POINT_DATA number_of_values | ||
const patPOINT_DATA = /^POINT_DATA[ ]+(\d+)/; | ||
const patPOINT_DATA = /^POINT_DATA[ ]+(\d+)/; // CELL_DATA number_of_polys | ||
// CELL_DATA number_of_polys | ||
const patCELL_DATA = /^CELL_DATA[ ]+(\d+)/; | ||
const patCELL_DATA = /^CELL_DATA[ ]+(\d+)/; // Start of color section | ||
// Start of color section | ||
const patCOLOR_SCALARS = /^COLOR_SCALARS[ ]+(\w+)[ ]+3/; | ||
const patCOLOR_SCALARS = /^COLOR_SCALARS[ ]+(\w+)[ ]+3/; // NORMALS Normals float | ||
// NORMALS Normals float | ||
const patNORMALS = /^NORMALS[ ]+(\w+)[ ]+(\w+)/; | ||
@@ -90,7 +101,5 @@ let inPointsSection = false; | ||
const lines = data.split( '\n' ); | ||
for ( const i in lines ) { | ||
const line = lines[ i ].trim(); | ||
if ( line.indexOf( 'DATASET' ) === 0 ) { | ||
@@ -121,8 +130,7 @@ | ||
const inds = result[ 2 ].split( /\s+/ ); | ||
if ( numVertices >= 3 ) { | ||
const i0 = parseInt( inds[ 0 ] ); | ||
let k = 1; // split the polygon in numVertices - 2 triangles | ||
let k = 1; | ||
// split the polygon in numVertices - 2 triangles | ||
for ( let j = 0; j < numVertices - 2; ++ j ) { | ||
@@ -148,3 +156,2 @@ | ||
const inds = result[ 2 ].split( /\s+/ ); | ||
if ( numVertices >= 3 ) { | ||
@@ -182,2 +189,3 @@ | ||
// Get the colors | ||
while ( ( result = pat3Floats.exec( line ) ) !== null ) { | ||
@@ -196,2 +204,3 @@ | ||
// Get the normal vectors | ||
while ( ( result = pat3Floats.exec( line ) ) !== null ) { | ||
@@ -266,3 +275,2 @@ | ||
geometry.setAttribute( 'position', new THREE.Float32BufferAttribute( positions, 3 ) ); | ||
if ( normals.length === positions.length ) { | ||
@@ -277,2 +285,3 @@ | ||
// stagger | ||
if ( colors.length === positions.length ) { | ||
@@ -287,9 +296,8 @@ | ||
// cell | ||
geometry = geometry.toNonIndexed(); | ||
const numTriangles = geometry.attributes.position.count / 3; | ||
if ( colors.length === numTriangles * 3 ) { | ||
const newColors = []; | ||
for ( let i = 0; i < numTriangles; i ++ ) { | ||
@@ -319,4 +327,5 @@ | ||
const buffer = new Uint8Array( data ); | ||
const dataView = new DataView( data ); // Points and normals, by default, are empty | ||
const dataView = new DataView( data ); | ||
// Points and normals, by default, are empty | ||
let points = []; | ||
@@ -326,3 +335,2 @@ let normals = []; | ||
let index = 0; | ||
function findString( buffer, start ) { | ||
@@ -333,3 +341,2 @@ | ||
const s = []; | ||
while ( c !== 10 ) { | ||
@@ -353,3 +360,2 @@ | ||
let state, line; | ||
while ( true ) { | ||
@@ -360,3 +366,2 @@ | ||
line = state.parsedString; | ||
if ( line.indexOf( 'DATASET' ) === 0 ) { | ||
@@ -370,8 +375,8 @@ | ||
// Add the points | ||
const numberOfPoints = parseInt( line.split( ' ' )[ 1 ], 10 ); // Each point is 3 4-byte floats | ||
const numberOfPoints = parseInt( line.split( ' ' )[ 1 ], 10 ); | ||
// Each point is 3 4-byte floats | ||
const count = numberOfPoints * 4 * 3; | ||
points = new Float32Array( numberOfPoints * 3 ); | ||
let pointIndex = state.next; | ||
for ( let i = 0; i < numberOfPoints; i ++ ) { | ||
@@ -384,5 +389,5 @@ | ||
} // increment our next pointer | ||
} | ||
// increment our next pointer | ||
state.next = state.next + count + 1; | ||
@@ -393,4 +398,4 @@ | ||
const numberOfStrips = parseInt( line.split( ' ' )[ 1 ], 10 ); | ||
const size = parseInt( line.split( ' ' )[ 2 ], 10 ); // 4 byte integers | ||
const size = parseInt( line.split( ' ' )[ 2 ], 10 ); | ||
// 4 byte integers | ||
const count = size * 4; | ||
@@ -400,3 +405,2 @@ indices = new Uint32Array( 3 * size - 9 * numberOfStrips ); | ||
let pointIndex = state.next; | ||
for ( let i = 0; i < numberOfStrips; i ++ ) { | ||
@@ -408,3 +412,2 @@ | ||
pointIndex += 4; | ||
for ( let s = 0; s < indexCount; s ++ ) { | ||
@@ -415,5 +418,5 @@ | ||
} // retrieves the n-2 triangles from the triangle strip | ||
} | ||
// retrieves the n-2 triangles from the triangle strip | ||
for ( let j = 0; j < indexCount - 2; j ++ ) { | ||
@@ -437,5 +440,5 @@ | ||
} // increment our next pointer | ||
} | ||
// increment our next pointer | ||
state.next = state.next + count + 1; | ||
@@ -446,4 +449,4 @@ | ||
const numberOfStrips = parseInt( line.split( ' ' )[ 1 ], 10 ); | ||
const size = parseInt( line.split( ' ' )[ 2 ], 10 ); // 4 byte integers | ||
const size = parseInt( line.split( ' ' )[ 2 ], 10 ); | ||
// 4 byte integers | ||
const count = size * 4; | ||
@@ -453,3 +456,2 @@ indices = new Uint32Array( 3 * size - 9 * numberOfStrips ); | ||
let pointIndex = state.next; | ||
for ( let i = 0; i < numberOfStrips; i ++ ) { | ||
@@ -461,3 +463,2 @@ | ||
pointIndex += 4; | ||
for ( let s = 0; s < indexCount; s ++ ) { | ||
@@ -468,5 +469,5 @@ | ||
} // divide the polygon in n-2 triangle | ||
} | ||
// divide the polygon in n-2 triangle | ||
for ( let j = 1; j < indexCount - 1; j ++ ) { | ||
@@ -480,5 +481,5 @@ | ||
} // increment our next pointer | ||
} | ||
// increment our next pointer | ||
state.next = state.next + count + 1; | ||
@@ -488,10 +489,11 @@ | ||
const numberOfPoints = parseInt( line.split( ' ' )[ 1 ], 10 ); // Grab the next line | ||
const numberOfPoints = parseInt( line.split( ' ' )[ 1 ], 10 ); | ||
state = findString( buffer, state.next ); // Now grab the binary data | ||
// Grab the next line | ||
state = findString( buffer, state.next ); | ||
// Now grab the binary data | ||
const count = numberOfPoints * 4 * 3; | ||
normals = new Float32Array( numberOfPoints * 3 ); | ||
let pointIndex = state.next; | ||
for ( let i = 0; i < numberOfPoints; i ++ ) { | ||
@@ -504,12 +506,11 @@ | ||
} // Increment past our data | ||
} | ||
// Increment past our data | ||
state.next = state.next + count; | ||
} // Increment index | ||
} | ||
// Increment index | ||
index = state.next; | ||
if ( index >= buffer.byteLength ) { | ||
@@ -526,3 +527,2 @@ | ||
geometry.setAttribute( 'position', new THREE.BufferAttribute( points, 3 ) ); | ||
if ( normals.length === points.length ) { | ||
@@ -561,2 +561,3 @@ | ||
// Changes XML to JSON, based on https://davidwalsh.name/convert-xml-json | ||
function xmlToJson( xml ) { | ||
@@ -566,7 +567,8 @@ | ||
let obj = {}; | ||
if ( xml.nodeType === 1 ) { | ||
// element | ||
// do attributes | ||
if ( xml.attributes ) { | ||
@@ -577,3 +579,2 @@ | ||
obj[ 'attributes' ] = {}; | ||
for ( let j = 0; j < xml.attributes.length; j ++ ) { | ||
@@ -593,7 +594,8 @@ | ||
// text | ||
obj = xml.nodeValue.trim(); | ||
} // do children | ||
} | ||
// do children | ||
if ( xml.hasChildNodes() ) { | ||
@@ -605,3 +607,2 @@ | ||
const nodeName = item.nodeName; | ||
if ( typeof obj[ nodeName ] === 'undefined' ) { | ||
@@ -632,5 +633,5 @@ | ||
} // Taken from Base64-js | ||
} | ||
// Taken from Base64-js | ||
function Base64toByteArray( b64 ) { | ||
@@ -641,3 +642,2 @@ | ||
const code = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; | ||
for ( let i = 0, l = code.length; i < l; ++ i ) { | ||
@@ -652,3 +652,2 @@ | ||
const len = b64.length; | ||
if ( len % 4 > 0 ) { | ||
@@ -665,3 +664,2 @@ | ||
let i, j; | ||
for ( i = 0, j = 0; i < l; i += 4, j += 3 ) { | ||
@@ -696,3 +694,2 @@ | ||
let numBytes = 0; | ||
if ( json.attributes.header_type === 'UInt64' ) { | ||
@@ -708,4 +705,5 @@ | ||
let txt, content; // Check the format | ||
let txt, content; | ||
// Check the format | ||
if ( ele.attributes.format === 'binary' && compressed ) { | ||
@@ -721,3 +719,5 @@ | ||
} // VTP data with the header has the following structure: | ||
} | ||
// VTP data with the header has the following structure: | ||
// [#blocks][#u-size][#p-size][#c-size-1][#c-size-2]...[#c-size-#blocks][DATA] | ||
@@ -734,10 +734,9 @@ // | ||
const textNode = ele[ '#text' ]; | ||
const rawData = Array.isArray( textNode ) ? textNode[ 0 ] : textNode; | ||
const byteData = Base64toByteArray( rawData ); // Each data point consists of 8 bits regardless of the header type | ||
const byteData = Base64toByteArray( rawData ); | ||
// Each data point consists of 8 bits regardless of the header type | ||
const dataPointSize = 8; | ||
let blocks = byteData[ 0 ]; | ||
for ( let i = 1; i < numBytes - 1; i ++ ) { | ||
@@ -754,11 +753,10 @@ | ||
let currentOffset = headerSize; | ||
dataOffsets.push( currentOffset ); // Get the blocks sizes after the compression. | ||
dataOffsets.push( currentOffset ); | ||
// Get the blocks sizes after the compression. | ||
// There are three blocks before c-size-i, so we skip 3*numBytes | ||
const cSizeStart = 3 * numBytes; | ||
for ( let i = 0; i < blocks; i ++ ) { | ||
let currentBlockSize = byteData[ i * numBytes + cSizeStart ]; | ||
for ( let j = 1; j < numBytes - 1; j ++ ) { | ||
@@ -778,5 +776,3 @@ | ||
const data = fflate.unzlibSync( byteData.slice( dataOffsets[ i ], dataOffsets[ i + 1 ] ) ); // eslint-disable-line no-undef | ||
content = data.buffer; | ||
if ( ele.attributes.type === 'Float32' ) { | ||
@@ -797,3 +793,2 @@ | ||
delete ele[ '#text' ]; | ||
if ( ele.attributes.type === 'Int64' ) { | ||
@@ -817,6 +812,7 @@ | ||
content = Base64toByteArray( ele[ '#text' ] ); // VTP data for the uncompressed case has the following structure: | ||
content = Base64toByteArray( ele[ '#text' ] ); | ||
// VTP data for the uncompressed case has the following structure: | ||
// [#bytes][DATA] | ||
// where "[#bytes]" is an integer value specifying the number of bytes in the block of data following it. | ||
content = content.slice( numBytes ).buffer; | ||
@@ -842,4 +838,5 @@ | ||
delete ele[ '#text' ]; // Get the content and optimize it | ||
delete ele[ '#text' ]; | ||
// Get the content and optimize it | ||
if ( ele.attributes.type === 'Float32' ) { | ||
@@ -856,3 +853,2 @@ | ||
txt = new Int32Array( content ); | ||
if ( ele.attributes.format === 'binary' ) { | ||
@@ -872,13 +868,13 @@ | ||
return txt; | ||
} // Main part | ||
} | ||
// Main part | ||
// Get Dom | ||
const dom = new DOMParser().parseFromString( stringFile, 'application/xml' ); | ||
const dom = new DOMParser().parseFromString( stringFile, 'application/xml' ); // Get the doc | ||
const doc = dom.documentElement; // Convert to json | ||
// Get the doc | ||
const doc = dom.documentElement; | ||
// Convert to json | ||
const json = xmlToJson( doc ); | ||
@@ -888,23 +884,23 @@ let points = []; | ||
let indices = []; | ||
if ( json.PolyData ) { | ||
const piece = json.PolyData.Piece; | ||
const compressed = json.attributes.hasOwnProperty( 'compressor' ); // Can be optimized | ||
const compressed = json.attributes.hasOwnProperty( 'compressor' ); | ||
// Can be optimized | ||
// Loop through the sections | ||
const sections = [ 'PointData', 'Points', 'Strips', 'Polys' ]; // +['CellData', 'Verts', 'Lines']; | ||
let sectionIndex = 0; | ||
const numberOfSections = sections.length; | ||
while ( sectionIndex < numberOfSections ) { | ||
const section = piece[ sections[ sectionIndex ] ]; // If it has a DataArray in it | ||
const section = piece[ sections[ sectionIndex ] ]; | ||
// If it has a DataArray in it | ||
if ( section && section.DataArray ) { | ||
// Depending on the number of DataArrays | ||
let arr; | ||
if ( Array.isArray( section.DataArray ) ) { | ||
@@ -922,3 +918,2 @@ | ||
const numberOfDataArrays = arr.length; | ||
while ( dataArrayIndex < numberOfDataArrays ) { | ||
@@ -945,3 +940,2 @@ | ||
const normalsName = section.attributes.Normals; | ||
if ( numberOfPoints > 0 ) { | ||
@@ -966,4 +960,4 @@ | ||
break; | ||
// if it is points | ||
case 'Points': | ||
@@ -973,3 +967,2 @@ { | ||
const numberOfPoints = parseInt( piece.attributes.NumberOfPoints ); | ||
if ( numberOfPoints > 0 ) { | ||
@@ -986,4 +979,4 @@ | ||
break; | ||
// if it is strips | ||
case 'Strips': | ||
@@ -993,3 +986,2 @@ { | ||
const numberOfStrips = parseInt( piece.attributes.NumberOfStrips ); | ||
if ( numberOfStrips > 0 ) { | ||
@@ -1004,7 +996,5 @@ | ||
let indicesIndex = 0; | ||
for ( let i = 0, len = numberOfStrips; i < len; i ++ ) { | ||
const strip = []; | ||
for ( let s = 0, len1 = offset[ i ], len0 = 0; s < len1 - len0; s ++ ) { | ||
@@ -1044,4 +1034,4 @@ | ||
break; | ||
// if it is polys | ||
case 'Polys': | ||
@@ -1051,3 +1041,2 @@ { | ||
const numberOfPolys = parseInt( piece.attributes.NumberOfPolys ); | ||
if ( numberOfPolys > 0 ) { | ||
@@ -1066,3 +1055,2 @@ | ||
const len = numberOfPolys; | ||
while ( i < len ) { | ||
@@ -1073,3 +1061,2 @@ | ||
const len1 = offset[ i ]; | ||
while ( s < len1 - len0 ) { | ||
@@ -1083,3 +1070,2 @@ | ||
let j = 1; | ||
while ( j < len1 - len0 - 1 ) { | ||
@@ -1104,3 +1090,2 @@ | ||
break; | ||
default: | ||
@@ -1120,3 +1105,2 @@ break; | ||
geometry.setAttribute( 'position', new THREE.BufferAttribute( points, 3 ) ); | ||
if ( normals.length === points.length ) { | ||
@@ -1136,7 +1120,6 @@ | ||
} // get the 5 first lines of the files to check if there is the key word binary | ||
} | ||
// get the 5 first lines of the files to check if there is the key word binary | ||
const meta = THREE.LoaderUtils.decodeText( new Uint8Array( data, 0, 250 ) ).split( '\n' ); | ||
if ( meta[ 0 ].indexOf( 'xml' ) !== - 1 ) { | ||
@@ -1143,0 +1126,0 @@ |
@@ -37,3 +37,2 @@ ( function () { | ||
} | ||
parse( text ) { | ||
@@ -44,3 +43,2 @@ | ||
const colors = []; | ||
for ( let line of lines ) { | ||
@@ -52,6 +50,6 @@ | ||
const lineValues = line.split( /\s+/ ); | ||
if ( lineValues.length === 3 ) { | ||
// XYZ | ||
vertices.push( parseFloat( lineValues[ 0 ] ) ); | ||
@@ -66,2 +64,3 @@ vertices.push( parseFloat( lineValues[ 1 ] ) ); | ||
// XYZRGB | ||
vertices.push( parseFloat( lineValues[ 0 ] ) ); | ||
@@ -80,3 +79,2 @@ vertices.push( parseFloat( lineValues[ 1 ] ) ); | ||
geometry.setAttribute( 'position', new THREE.Float32BufferAttribute( vertices, 3 ) ); | ||
if ( colors.length > 0 ) { | ||
@@ -83,0 +81,0 @@ |
@@ -15,5 +15,3 @@ ( function () { | ||
} ] ), | ||
vertexShader: | ||
/* glsl */ | ||
` | ||
vertexShader: /* glsl */` | ||
@@ -194,5 +192,3 @@ #define GOURAUD | ||
}`, | ||
fragmentShader: | ||
/* glsl */ | ||
` | ||
fragmentShader: /* glsl */` | ||
@@ -296,4 +292,6 @@ #define GOURAUD | ||
}` | ||
}; // | ||
}; | ||
// | ||
class MeshGouraudMaterial extends THREE.ShaderMaterial { | ||
@@ -305,15 +303,23 @@ | ||
this.isMeshGouraudMaterial = true; | ||
this.type = 'MeshGouraudMaterial'; //this.color = new THREE.Color( 0xffffff ); // diffuse | ||
this.type = 'MeshGouraudMaterial'; | ||
//this.color = new THREE.Color( 0xffffff ); // diffuse | ||
//this.map = null; | ||
//this.lightMap = null; | ||
//this.lightMapIntensity = 1.0; | ||
//this.aoMap = null; | ||
//this.aoMapIntensity = 1.0; | ||
//this.emissive = new THREE.Color( 0x000000 ); | ||
//this.emissiveIntensity = 1.0; | ||
//this.emissiveMap = null; | ||
//this.specularMap = null; | ||
//this.alphaMap = null; | ||
//this.envMap = null; | ||
this.combine = THREE.MultiplyOperation; // combine has no uniform | ||
@@ -324,5 +330,3 @@ //this.reflectivity = 1; | ||
this.fog = false; // set to use scene fog | ||
this.lights = true; // set to use scene lights | ||
this.clipping = false; // set to use user-defined clipping planes | ||
@@ -336,3 +340,2 @@ | ||
const exposePropertyNames = [ 'map', 'lightMap', 'lightMapIntensity', 'aoMap', 'aoMapIntensity', 'emissive', 'emissiveIntensity', 'emissiveMap', 'specularMap', 'alphaMap', 'envMap', 'reflectivity', 'refractionRatio', 'opacity', 'diffuse' ]; | ||
for ( const propertyName of exposePropertyNames ) { | ||
@@ -359,3 +362,2 @@ | ||
} | ||
copy( source ) { | ||
@@ -362,0 +364,0 @@ |
( function () { | ||
const _v1 = new THREE.Vector3(); | ||
const _v2 = new THREE.Vector3(); | ||
const _v3 = new THREE.Vector3(); | ||
const EPS = 1e-10; | ||
class Capsule { | ||
@@ -20,3 +16,2 @@ | ||
} | ||
clone() { | ||
@@ -27,3 +22,2 @@ | ||
} | ||
set( start, end, radius ) { | ||
@@ -36,3 +30,2 @@ | ||
} | ||
copy( capsule ) { | ||
@@ -45,3 +38,2 @@ | ||
} | ||
getCenter( target ) { | ||
@@ -52,3 +44,2 @@ | ||
} | ||
translate( v ) { | ||
@@ -60,3 +51,2 @@ | ||
} | ||
checkAABBAxis( p1x, p1y, p2x, p2y, minx, maxx, miny, maxy, radius ) { | ||
@@ -67,3 +57,2 @@ | ||
} | ||
intersectsBox( box ) { | ||
@@ -74,11 +63,7 @@ | ||
} | ||
lineLineMinimumPoints( line1, line2 ) { | ||
const r = _v1.copy( line1.end ).sub( line1.start ); | ||
const s = _v2.copy( line2.end ).sub( line2.start ); | ||
const w = _v3.copy( line2.start ).sub( line1.start ); | ||
const a = r.dot( s ), | ||
@@ -91,3 +76,2 @@ b = r.dot( r ), | ||
const divisor = b * c - a * a; | ||
if ( Math.abs( divisor ) < EPS ) { | ||
@@ -97,3 +81,2 @@ | ||
const d2 = ( a - d ) / c; | ||
if ( Math.abs( d1 - 0.5 ) < Math.abs( d2 - 0.5 ) ) { | ||
@@ -100,0 +83,0 @@ |
( function () { | ||
const _hsl = {}; | ||
class ColorConverter { | ||
@@ -10,2 +9,3 @@ | ||
// https://gist.github.com/xpansive/1337890#file-index-js | ||
h = THREE.MathUtils.euclideanModulo( h, 1 ); | ||
@@ -17,7 +17,7 @@ s = THREE.MathUtils.clamp( s, 0, 1 ); | ||
} | ||
static getHSV( color, target ) { | ||
color.getHSL( _hsl ); // based on https://gist.github.com/xpansive/1337890#file-index-js | ||
color.getHSL( _hsl ); | ||
// based on https://gist.github.com/xpansive/1337890#file-index-js | ||
_hsl.s *= _hsl.l < 0.5 ? _hsl.l : 1 - _hsl.l; | ||
@@ -24,0 +24,0 @@ target.h = _hsl.h; |
@@ -9,13 +9,7 @@ ( function () { | ||
const Deleted = 1; | ||
const _v1 = new THREE.Vector3(); | ||
const _line3 = new THREE.Line3(); | ||
const _plane = new THREE.Plane(); | ||
const _closestPoint = new THREE.Vector3(); | ||
const _triangle = new THREE.Triangle(); | ||
class ConvexHull { | ||
@@ -27,4 +21,4 @@ | ||
this.faces = []; // the generated faces of the convex hull | ||
this.newFaces = []; // this array holds the faces that are generated within a single iteration | ||
this.newFaces = []; // this array holds the faces that are generated within a single iteration | ||
// the vertex lists work as follows: | ||
@@ -40,3 +34,2 @@ // | ||
// | ||
this.assigned = new VertexList(); | ||
@@ -51,6 +44,6 @@ this.unassigned = new VertexList(); | ||
// The algorithm needs at least four points. | ||
if ( points.length >= 4 ) { | ||
this.makeEmpty(); | ||
for ( let i = 0, l = points.length; i < l; i ++ ) { | ||
@@ -69,3 +62,2 @@ | ||
} | ||
setFromObject( object ) { | ||
@@ -78,7 +70,5 @@ | ||
const geometry = node.geometry; | ||
if ( geometry !== undefined ) { | ||
const attribute = geometry.attributes.position; | ||
if ( attribute !== undefined ) { | ||
@@ -102,11 +92,11 @@ | ||
} | ||
containsPoint( point ) { | ||
const faces = this.faces; | ||
for ( let i = 0, l = faces.length; i < l; i ++ ) { | ||
const face = faces[ i ]; // compute signed distance and check on what half space the point lies | ||
const face = faces[ i ]; | ||
// compute signed distance and check on what half space the point lies | ||
if ( face.distanceToPoint( point ) > this.tolerance ) return false; | ||
@@ -119,28 +109,38 @@ | ||
} | ||
intersectRay( ray, target ) { | ||
// based on "Fast Ray-Convex Polyhedron Intersection" by Eric Haines, GRAPHICS GEMS II | ||
const faces = this.faces; | ||
let tNear = - Infinity; | ||
let tFar = Infinity; | ||
for ( let i = 0, l = faces.length; i < l; i ++ ) { | ||
const face = faces[ i ]; // interpret faces as planes for the further computation | ||
const face = faces[ i ]; | ||
// interpret faces as planes for the further computation | ||
const vN = face.distanceToPoint( ray.origin ); | ||
const vD = face.normal.dot( ray.direction ); // if the origin is on the positive side of a plane (so the plane can "see" the origin) and | ||
const vD = face.normal.dot( ray.direction ); | ||
// if the origin is on the positive side of a plane (so the plane can "see" the origin) and | ||
// the ray is turned away or parallel to the plane, there is no intersection | ||
if ( vN > 0 && vD >= 0 ) return null; // compute the distance from the ray’s origin to the intersection with the plane | ||
if ( vN > 0 && vD >= 0 ) return null; | ||
const t = vD !== 0 ? - vN / vD : 0; // only proceed if the distance is positive. a negative distance means the intersection point | ||
// compute the distance from the ray’s origin to the intersection with the plane | ||
const t = vD !== 0 ? - vN / vD : 0; | ||
// only proceed if the distance is positive. a negative distance means the intersection point | ||
// lies "behind" the origin | ||
if ( t <= 0 ) continue; // now categorized plane as front-facing or back-facing | ||
if ( t <= 0 ) continue; | ||
// now categorized plane as front-facing or back-facing | ||
if ( vD > 0 ) { | ||
// plane faces away from the ray, so this plane is a back-face | ||
tFar = Math.min( t, tFar ); | ||
@@ -151,2 +151,3 @@ | ||
// front-face | ||
tNear = Math.max( t, tNear ); | ||
@@ -159,2 +160,3 @@ | ||
// if tNear ever is greater than tFar, the ray must miss the convex hull | ||
return null; | ||
@@ -164,6 +166,8 @@ | ||
} // evaluate intersection point | ||
} | ||
// evaluate intersection point | ||
// always try tNear first since its the closer intersection point | ||
if ( tNear !== - Infinity ) { | ||
@@ -182,3 +186,2 @@ | ||
} | ||
intersectsRay( ray ) { | ||
@@ -189,3 +192,2 @@ | ||
} | ||
makeEmpty() { | ||
@@ -197,4 +199,5 @@ | ||
} // Adds a vertex to the 'assigned' list of vertices and assigns it to the given face | ||
} | ||
// Adds a vertex to the 'assigned' list of vertices and assigns it to the given face | ||
@@ -204,3 +207,2 @@ addVertexToFace( vertex, face ) { | ||
vertex.face = face; | ||
if ( face.outside === null ) { | ||
@@ -219,4 +221,5 @@ | ||
} // Removes a vertex from the 'assigned' list of vertices and from the given face | ||
} | ||
// Removes a vertex from the 'assigned' list of vertices and from the given face | ||
@@ -228,5 +231,7 @@ removeVertexFromFace( vertex, face ) { | ||
// fix face.outside link | ||
if ( vertex.next !== null && vertex.next.face === face ) { | ||
// face has at least 2 outside vertices, move the 'outside' reference | ||
face.outside = vertex.next; | ||
@@ -237,2 +242,3 @@ | ||
// vertex was the only outside vertex that face had | ||
face.outside = null; | ||
@@ -247,4 +253,5 @@ | ||
} // Removes all the visible vertices that a given face is able to see which are stored in the 'assigned' vertext list | ||
} | ||
// Removes all the visible vertices that a given face is able to see which are stored in the 'assigned' vertext list | ||
@@ -256,5 +263,5 @@ removeAllVerticesFromFace( face ) { | ||
// reference to the first and last vertex of this face | ||
const start = face.outside; | ||
let end = face.outside; | ||
while ( end.next !== null && end.next.face === face ) { | ||
@@ -266,4 +273,6 @@ | ||
this.assigned.removeSubList( start, end ); // fix references | ||
this.assigned.removeSubList( start, end ); | ||
// fix references | ||
start.prev = end.next = null; | ||
@@ -275,4 +284,5 @@ face.outside = null; | ||
} // Removes all the visible vertices that 'face' is able to see | ||
} | ||
// Removes all the visible vertices that 'face' is able to see | ||
@@ -282,3 +292,2 @@ deleteFaceVertices( face, absorbingFace ) { | ||
const faceVertices = this.removeAllVerticesFromFace( face ); | ||
if ( faceVertices !== undefined ) { | ||
@@ -289,2 +298,3 @@ | ||
// mark the vertices to be reassigned to some other face | ||
this.unassigned.appendChain( faceVertices ); | ||
@@ -295,4 +305,4 @@ | ||
// if there's an absorbing face try to assign as many vertices as possible to it | ||
let vertex = faceVertices; | ||
do { | ||
@@ -302,5 +312,8 @@ | ||
// will be changed by upcoming method calls | ||
const nextVertex = vertex.next; | ||
const distance = absorbingFace.distanceToPoint( vertex.point ); // check if 'vertex' is able to see 'absorbingFace' | ||
const distance = absorbingFace.distanceToPoint( vertex.point ); | ||
// check if 'vertex' is able to see 'absorbingFace' | ||
if ( distance > this.tolerance ) { | ||
@@ -314,4 +327,5 @@ | ||
} // now assign next vertex | ||
} | ||
// now assign next vertex | ||
@@ -328,4 +342,5 @@ vertex = nextVertex; | ||
} // Reassigns as many vertices as possible from the unassigned list to the new faces | ||
} | ||
// Reassigns as many vertices as possible from the unassigned list to the new faces | ||
@@ -337,18 +352,15 @@ resolveUnassignedPoints( newFaces ) { | ||
let vertex = this.unassigned.first(); | ||
do { | ||
// buffer 'next' reference, see .deleteFaceVertices() | ||
const nextVertex = vertex.next; | ||
let maxDistance = this.tolerance; | ||
let maxFace = null; | ||
for ( let i = 0; i < newFaces.length; i ++ ) { | ||
const face = newFaces[ i ]; | ||
if ( face.mark === Visible ) { | ||
const distance = face.distanceToPoint( vertex.point ); | ||
if ( distance > maxDistance ) { | ||
@@ -365,4 +377,5 @@ | ||
} // 'maxFace' can be null e.g. if there are identical vertices | ||
} | ||
// 'maxFace' can be null e.g. if there are identical vertices | ||
@@ -383,4 +396,5 @@ if ( maxFace !== null ) { | ||
} // Computes the extremes of a simplex which will be the initial hull | ||
} | ||
// Computes the extremes of a simplex which will be the initial hull | ||
@@ -392,4 +406,6 @@ computeExtremes() { | ||
const minVertices = []; | ||
const maxVertices = []; // initially assume that the first vertex is the min/max | ||
const maxVertices = []; | ||
// initially assume that the first vertex is the min/max | ||
for ( let i = 0; i < 3; i ++ ) { | ||
@@ -402,9 +418,13 @@ | ||
min.copy( this.vertices[ 0 ].point ); | ||
max.copy( this.vertices[ 0 ].point ); // compute the min/max vertex on all six directions | ||
max.copy( this.vertices[ 0 ].point ); | ||
// compute the min/max vertex on all six directions | ||
for ( let i = 0, l = this.vertices.length; i < l; i ++ ) { | ||
const vertex = this.vertices[ i ]; | ||
const point = vertex.point; // update the min coordinates | ||
const point = vertex.point; | ||
// update the min coordinates | ||
for ( let j = 0; j < 3; j ++ ) { | ||
@@ -419,4 +439,5 @@ | ||
} // update the max coordinates | ||
} | ||
// update the max coordinates | ||
@@ -434,4 +455,5 @@ for ( let j = 0; j < 3; j ++ ) { | ||
} // use min/max vectors to compute an optimal epsilon | ||
} | ||
// use min/max vectors to compute an optimal epsilon | ||
@@ -444,6 +466,7 @@ this.tolerance = 3 * Number.EPSILON * ( Math.max( Math.abs( min.x ), Math.abs( max.x ) ) + Math.max( Math.abs( min.y ), Math.abs( max.y ) ) + Math.max( Math.abs( min.z ), Math.abs( max.z ) ) ); | ||
} // Computes the initial simplex assigning to its faces all the points | ||
} | ||
// Computes the initial simplex assigning to its faces all the points | ||
// that are candidates to form part of the hull | ||
computeInitialHull() { | ||
@@ -454,3 +477,5 @@ | ||
const min = extremes.min; | ||
const max = extremes.max; // 1. Find the two vertices 'v0' and 'v1' with the greatest 1d separation | ||
const max = extremes.max; | ||
// 1. Find the two vertices 'v0' and 'v1' with the greatest 1d separation | ||
// (max.x - min.x) | ||
@@ -462,7 +487,5 @@ // (max.y - min.y) | ||
let index = 0; | ||
for ( let i = 0; i < 3; i ++ ) { | ||
const distance = max[ i ].point.getComponent( i ) - min[ i ].point.getComponent( i ); | ||
if ( distance > maxDistance ) { | ||
@@ -480,18 +503,15 @@ | ||
let v2; | ||
let v3; // 2. The next vertex 'v2' is the one farthest to the line formed by 'v0' and 'v1' | ||
let v3; | ||
// 2. The next vertex 'v2' is the one farthest to the line formed by 'v0' and 'v1' | ||
maxDistance = 0; | ||
_line3.set( v0.point, v1.point ); | ||
for ( let i = 0, l = this.vertices.length; i < l; i ++ ) { | ||
const vertex = vertices[ i ]; | ||
if ( vertex !== v0 && vertex !== v1 ) { | ||
_line3.closestPointToPoint( vertex.point, true, _closestPoint ); | ||
const distance = _closestPoint.distanceToSquared( vertex.point ); | ||
if ( distance > maxDistance ) { | ||
@@ -506,17 +526,14 @@ | ||
} // 3. The next vertex 'v3' is the one farthest to the plane 'v0', 'v1', 'v2' | ||
} | ||
// 3. The next vertex 'v3' is the one farthest to the plane 'v0', 'v1', 'v2' | ||
maxDistance = - 1; | ||
_plane.setFromCoplanarPoints( v0.point, v1.point, v2.point ); | ||
for ( let i = 0, l = this.vertices.length; i < l; i ++ ) { | ||
const vertex = vertices[ i ]; | ||
if ( vertex !== v0 && vertex !== v1 && vertex !== v2 ) { | ||
const distance = Math.abs( _plane.distanceToPoint( vertex.point ) ); | ||
if ( distance > maxDistance ) { | ||
@@ -534,14 +551,20 @@ | ||
const faces = []; | ||
if ( _plane.distanceToPoint( v3.point ) < 0 ) { | ||
// the face is not able to see the point so 'plane.normal' is pointing outside the tetrahedron | ||
faces.push( Face.create( v0, v1, v2 ), Face.create( v3, v1, v0 ), Face.create( v3, v2, v1 ), Face.create( v3, v0, v2 ) ); // set the twin edge | ||
faces.push( Face.create( v0, v1, v2 ), Face.create( v3, v1, v0 ), Face.create( v3, v2, v1 ), Face.create( v3, v0, v2 ) ); | ||
// set the twin edge | ||
for ( let i = 0; i < 3; i ++ ) { | ||
const j = ( i + 1 ) % 3; // join face[ i ] i > 0, with the first face | ||
const j = ( i + 1 ) % 3; | ||
faces[ i + 1 ].getEdge( 2 ).setTwin( faces[ 0 ].getEdge( j ) ); // join face[ i ] with face[ i + 1 ], 1 <= i <= 3 | ||
// join face[ i ] i > 0, with the first face | ||
faces[ i + 1 ].getEdge( 2 ).setTwin( faces[ 0 ].getEdge( j ) ); | ||
// join face[ i ] with face[ i + 1 ], 1 <= i <= 3 | ||
faces[ i + 1 ].getEdge( 1 ).setTwin( faces[ j + 1 ].getEdge( 0 ) ); | ||
@@ -554,10 +577,17 @@ | ||
// the face is able to see the point so 'plane.normal' is pointing inside the tetrahedron | ||
faces.push( Face.create( v0, v2, v1 ), Face.create( v3, v0, v1 ), Face.create( v3, v1, v2 ), Face.create( v3, v2, v0 ) ); // set the twin edge | ||
faces.push( Face.create( v0, v2, v1 ), Face.create( v3, v0, v1 ), Face.create( v3, v1, v2 ), Face.create( v3, v2, v0 ) ); | ||
// set the twin edge | ||
for ( let i = 0; i < 3; i ++ ) { | ||
const j = ( i + 1 ) % 3; // join face[ i ] i > 0, with the first face | ||
const j = ( i + 1 ) % 3; | ||
faces[ i + 1 ].getEdge( 2 ).setTwin( faces[ 0 ].getEdge( ( 3 - i ) % 3 ) ); // join face[ i ] with face[ i + 1 ] | ||
// join face[ i ] i > 0, with the first face | ||
faces[ i + 1 ].getEdge( 2 ).setTwin( faces[ 0 ].getEdge( ( 3 - i ) % 3 ) ); | ||
// join face[ i ] with face[ i + 1 ] | ||
faces[ i + 1 ].getEdge( 0 ).setTwin( faces[ j + 1 ].getEdge( 1 ) ); | ||
@@ -567,4 +597,5 @@ | ||
} // the initial hull is the tetrahedron | ||
} | ||
// the initial hull is the tetrahedron | ||
@@ -575,4 +606,5 @@ for ( let i = 0; i < 4; i ++ ) { | ||
} // initial assignment of vertices to the faces of the tetrahedron | ||
} | ||
// initial assignment of vertices to the faces of the tetrahedron | ||
@@ -582,3 +614,2 @@ for ( let i = 0, l = vertices.length; i < l; i ++ ) { | ||
const vertex = vertices[ i ]; | ||
if ( vertex !== v0 && vertex !== v1 && vertex !== v2 && vertex !== v3 ) { | ||
@@ -588,7 +619,5 @@ | ||
let maxFace = null; | ||
for ( let j = 0; j < 4; j ++ ) { | ||
const distance = this.faces[ j ].distanceToPoint( vertex.point ); | ||
if ( distance > maxDistance ) { | ||
@@ -615,4 +644,5 @@ | ||
} // Removes inactive faces | ||
} | ||
// Removes inactive faces | ||
@@ -622,7 +652,5 @@ reindexFaces() { | ||
const activeFaces = []; | ||
for ( let i = 0; i < this.faces.length; i ++ ) { | ||
const face = this.faces[ i ]; | ||
if ( face.mark === Visible ) { | ||
@@ -639,4 +667,5 @@ | ||
} // Finds the next vertex to create faces with the current hull | ||
} | ||
// Finds the next vertex to create faces with the current hull | ||
@@ -646,14 +675,18 @@ nextVertexToAdd() { | ||
// if the 'assigned' list of vertices is empty, no vertices are left. return with 'undefined' | ||
if ( this.assigned.isEmpty() === false ) { | ||
let eyeVertex, | ||
maxDistance = 0; // grap the first available face and start with the first visible vertex of that face | ||
maxDistance = 0; | ||
// grap the first available face and start with the first visible vertex of that face | ||
const eyeFace = this.assigned.first().face; | ||
let vertex = eyeFace.outside; // now calculate the farthest vertex that face can see | ||
let vertex = eyeFace.outside; | ||
// now calculate the farthest vertex that face can see | ||
do { | ||
const distance = eyeFace.distanceToPoint( vertex.point ); | ||
if ( distance > maxDistance ) { | ||
@@ -674,14 +707,15 @@ | ||
} // Computes a chain of half edges in CCW order called the 'horizon'. | ||
} | ||
// Computes a chain of half edges in CCW order called the 'horizon'. | ||
// For an edge to be part of the horizon it must join a face that can see | ||
// 'eyePoint' and a face that cannot see 'eyePoint'. | ||
computeHorizon( eyePoint, crossEdge, face, horizon ) { | ||
// moves face's vertices to the 'unassigned' vertex list | ||
this.deleteFaceVertices( face ); | ||
face.mark = Deleted; | ||
let edge; | ||
if ( crossEdge === null ) { | ||
@@ -695,2 +729,3 @@ | ||
// (actually 'crossEdge.twin' was the edge who called this method recursively) | ||
edge = crossEdge.next; | ||
@@ -704,3 +739,2 @@ | ||
const oppositeFace = twinEdge.face; | ||
if ( oppositeFace.mark === Visible ) { | ||
@@ -711,2 +745,3 @@ | ||
// the opposite face can see the vertex, so proceed with next edge | ||
this.computeHorizon( eyePoint, twinEdge, oppositeFace, horizon ); | ||
@@ -717,2 +752,3 @@ | ||
// the opposite face can't see the vertex, so this edge is part of the horizon | ||
horizon.push( edge ); | ||
@@ -730,4 +766,5 @@ | ||
} // Creates a face with the vertices 'eyeVertex.point', 'horizonEdge.tail' and 'horizonEdge.head' in CCW order | ||
} | ||
// Creates a face with the vertices 'eyeVertex.point', 'horizonEdge.tail' and 'horizonEdge.head' in CCW order | ||
@@ -737,12 +774,16 @@ addAdjoiningFace( eyeVertex, horizonEdge ) { | ||
// all the half edges are created in ccw order thus the face is always pointing outside the hull | ||
const face = Face.create( eyeVertex, horizonEdge.tail(), horizonEdge.head() ); | ||
this.faces.push( face ); // join face.getEdge( - 1 ) with the horizon's opposite edge face.getEdge( - 1 ) = face.getEdge( 2 ) | ||
this.faces.push( face ); | ||
// join face.getEdge( - 1 ) with the horizon's opposite edge face.getEdge( - 1 ) = face.getEdge( 2 ) | ||
face.getEdge( - 1 ).setTwin( horizonEdge.twin ); | ||
return face.getEdge( 0 ); // the half edge whose vertex is the eyeVertex | ||
} // Adds 'horizon.length' faces to the hull, each face will be linked with the | ||
} | ||
// Adds 'horizon.length' faces to the hull, each face will be linked with the | ||
// horizon opposite face and the face on the left/right | ||
addNewFaces( eyeVertex, horizon ) { | ||
@@ -753,9 +794,9 @@ | ||
let previousSideEdge = null; | ||
for ( let i = 0; i < horizon.length; i ++ ) { | ||
const horizonEdge = horizon[ i ]; // returns the right side edge | ||
const horizonEdge = horizon[ i ]; | ||
// returns the right side edge | ||
const sideEdge = this.addAdjoiningFace( eyeVertex, horizonEdge ); | ||
if ( firstSideEdge === null ) { | ||
@@ -768,2 +809,3 @@ | ||
// joins face.getEdge( 1 ) with previousFace.getEdge( 0 ) | ||
sideEdge.next.setTwin( previousSideEdge ); | ||
@@ -776,4 +818,5 @@ | ||
} // perform final join of new faces | ||
} | ||
// perform final join of new faces | ||
@@ -783,4 +826,5 @@ firstSideEdge.next.setTwin( previousSideEdge ); | ||
} // Adds a vertex to the hull | ||
} | ||
// Adds a vertex to the hull | ||
@@ -790,8 +834,12 @@ addVertexToHull( eyeVertex ) { | ||
const horizon = []; | ||
this.unassigned.clear(); // remove 'eyeVertex' from 'eyeVertex.face' so that it can't be added to the 'unassigned' vertex list | ||
this.unassigned.clear(); | ||
// remove 'eyeVertex' from 'eyeVertex.face' so that it can't be added to the 'unassigned' vertex list | ||
this.removeVertexFromFace( eyeVertex, eyeVertex.face ); | ||
this.computeHorizon( eyeVertex.point, null, eyeVertex.face, horizon ); | ||
this.addNewFaces( eyeVertex, horizon ); // reassign 'unassigned' vertices to the new faces | ||
this.addNewFaces( eyeVertex, horizon ); | ||
// reassign 'unassigned' vertices to the new faces | ||
this.resolveUnassignedPoints( this.newFaces ); | ||
@@ -801,3 +849,2 @@ return this; | ||
} | ||
cleanup() { | ||
@@ -811,8 +858,9 @@ | ||
} | ||
compute() { | ||
let vertex; | ||
this.computeInitialHull(); // add all available vertices gradually to the hull | ||
this.computeInitialHull(); | ||
// add all available vertices gradually to the hull | ||
while ( ( vertex = this.nextVertexToAdd() ) !== undefined ) { | ||
@@ -830,4 +878,5 @@ | ||
} // | ||
} | ||
// | ||
@@ -842,5 +891,3 @@ class Face { | ||
this.constant = 0; // signed distance from face to the origin | ||
this.outside = null; // reference to a vertex in a vertex list this face can see | ||
this.mark = Visible; | ||
@@ -850,3 +897,2 @@ this.edge = null; | ||
} | ||
static create( a, b, c ) { | ||
@@ -857,8 +903,12 @@ | ||
const e1 = new HalfEdge( b, face ); | ||
const e2 = new HalfEdge( c, face ); // join edges | ||
const e2 = new HalfEdge( c, face ); | ||
// join edges | ||
e0.next = e2.prev = e1; | ||
e1.next = e0.prev = e2; | ||
e2.next = e1.prev = e0; // main half edge reference | ||
e2.next = e1.prev = e0; | ||
// main half edge reference | ||
face.edge = e0; | ||
@@ -868,7 +918,5 @@ return face.compute(); | ||
} | ||
getEdge( i ) { | ||
let edge = this.edge; | ||
while ( i > 0 ) { | ||
@@ -891,3 +939,2 @@ | ||
} | ||
compute() { | ||
@@ -898,9 +945,5 @@ | ||
const c = this.edge.next.head(); | ||
_triangle.set( a.point, b.point, c.point ); | ||
_triangle.getNormal( this.normal ); | ||
_triangle.getMidpoint( this.midpoint ); | ||
this.area = _triangle.getArea(); | ||
@@ -911,3 +954,2 @@ this.constant = this.normal.dot( this.midpoint ); | ||
} | ||
distanceToPoint( point ) { | ||
@@ -919,4 +961,5 @@ | ||
} // Entity for a Doubly-Connected Edge List (DCEL). | ||
} | ||
// Entity for a Doubly-Connected Edge List (DCEL). | ||
@@ -934,3 +977,2 @@ class HalfEdge { | ||
} | ||
head() { | ||
@@ -941,3 +983,2 @@ | ||
} | ||
tail() { | ||
@@ -948,3 +989,2 @@ | ||
} | ||
length() { | ||
@@ -954,3 +994,2 @@ | ||
const tail = this.tail(); | ||
if ( tail !== null ) { | ||
@@ -965,3 +1004,2 @@ | ||
} | ||
lengthSquared() { | ||
@@ -971,3 +1009,2 @@ | ||
const tail = this.tail(); | ||
if ( tail !== null ) { | ||
@@ -982,3 +1019,2 @@ | ||
} | ||
setTwin( edge ) { | ||
@@ -992,4 +1028,5 @@ | ||
} // A vertex as a double linked list node. | ||
} | ||
// A vertex as a double linked list node. | ||
@@ -1007,4 +1044,5 @@ class VertexNode { | ||
} // A double linked list that contains vertex nodes. | ||
} | ||
// A double linked list that contains vertex nodes. | ||
@@ -1019,3 +1057,2 @@ class VertexList { | ||
} | ||
first() { | ||
@@ -1026,3 +1063,2 @@ | ||
} | ||
last() { | ||
@@ -1033,3 +1069,2 @@ | ||
} | ||
clear() { | ||
@@ -1040,4 +1075,5 @@ | ||
} // Inserts a vertex before the target vertex | ||
} | ||
// Inserts a vertex before the target vertex | ||
@@ -1048,3 +1084,2 @@ insertBefore( target, vertex ) { | ||
vertex.next = target; | ||
if ( vertex.prev === null ) { | ||
@@ -1063,4 +1098,5 @@ | ||
} // Inserts a vertex after the target vertex | ||
} | ||
// Inserts a vertex after the target vertex | ||
@@ -1071,3 +1107,2 @@ insertAfter( target, vertex ) { | ||
vertex.next = target.next; | ||
if ( vertex.next === null ) { | ||
@@ -1086,4 +1121,5 @@ | ||
} // Appends a vertex to the end of the linked list | ||
} | ||
// Appends a vertex to the end of the linked list | ||
@@ -1108,4 +1144,5 @@ append( vertex ) { | ||
} // Appends a chain of vertices where 'vertex' is the head. | ||
} | ||
// Appends a chain of vertices where 'vertex' is the head. | ||
@@ -1124,4 +1161,6 @@ appendChain( vertex ) { | ||
vertex.prev = this.tail; // ensure that the 'tail' reference points to the last vertex of the chain | ||
vertex.prev = this.tail; | ||
// ensure that the 'tail' reference points to the last vertex of the chain | ||
while ( vertex.next !== null ) { | ||
@@ -1136,4 +1175,5 @@ | ||
} // Removes a vertex from the linked list | ||
} | ||
// Removes a vertex from the linked list | ||
@@ -1164,4 +1204,5 @@ remove( vertex ) { | ||
} // Removes a list of vertices whose 'head' is 'a' and whose 'tail' is b | ||
} | ||
// Removes a list of vertices whose 'head' is 'a' and whose 'tail' is b | ||
@@ -1193,3 +1234,2 @@ removeSubList( a, b ) { | ||
} | ||
isEmpty() { | ||
@@ -1204,3 +1244,7 @@ | ||
THREE.ConvexHull = ConvexHull; | ||
THREE.Face = Face; | ||
THREE.HalfEdge = HalfEdge; | ||
THREE.VertexList = VertexList; | ||
THREE.VertexNode = VertexNode; | ||
} )(); |
( function () { | ||
// https://cs.nyu.edu/~perlin/noise/ | ||
const _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 ( let i = 0; i < 256; i ++ ) { | ||
@@ -7,0 +7,0 @@ |
@@ -16,3 +16,2 @@ ( function () { | ||
} | ||
set( value ) { | ||
@@ -29,3 +28,2 @@ | ||
} | ||
setMin( min ) { | ||
@@ -37,3 +35,2 @@ | ||
} | ||
setMax( max ) { | ||
@@ -45,3 +42,2 @@ | ||
} | ||
setColorMap( colormap, count = 32 ) { | ||
@@ -54,10 +50,13 @@ | ||
const maxColor = new THREE.Color(); | ||
this.lut.length = 0; // sample at 0 | ||
this.lut.length = 0; | ||
this.lut.push( new THREE.Color( this.map[ 0 ][ 1 ] ) ); // sample at 1/n, ..., (n-1)/n | ||
// sample at 0 | ||
this.lut.push( new THREE.Color( this.map[ 0 ][ 1 ] ) ); | ||
// sample at 1/n, ..., (n-1)/n | ||
for ( let i = 1; i < count; i ++ ) { | ||
const alpha = i * step; | ||
for ( let j = 0; j < this.map.length - 1; j ++ ) { | ||
@@ -78,4 +77,5 @@ | ||
} // sample at 1 | ||
} | ||
// sample at 1 | ||
@@ -86,3 +86,2 @@ this.lut.push( new THREE.Color( this.map[ this.map.length - 1 ][ 1 ] ) ); | ||
} | ||
copy( lut ) { | ||
@@ -98,3 +97,2 @@ | ||
} | ||
getColor( alpha ) { | ||
@@ -108,3 +106,2 @@ | ||
} | ||
addColorMap( name, arrayOfColors ) { | ||
@@ -116,3 +113,2 @@ | ||
} | ||
createCanvas() { | ||
@@ -127,3 +123,2 @@ | ||
} | ||
updateCanvas( canvas ) { | ||
@@ -141,3 +136,2 @@ | ||
const finalColor = new THREE.Color(); | ||
for ( let i = 1; i >= 0; i -= step ) { | ||
@@ -172,3 +166,2 @@ | ||
} | ||
const ColorMapKeywords = { | ||
@@ -175,0 +168,0 @@ 'rainbow': [[ 0.0, 0x0000FF ], [ 0.2, 0x00FFFF ], [ 0.5, 0x00FF00 ], [ 0.8, 0xFFFF00 ], [ 1.0, 0xFF0000 ]], |
@@ -15,5 +15,3 @@ ( function () { | ||
const _face = new THREE.Triangle(); | ||
const _color = new THREE.Vector3(); | ||
class MeshSurfaceSampler { | ||
@@ -24,3 +22,2 @@ | ||
let geometry = mesh.geometry; | ||
if ( ! geometry.isBufferGeometry || geometry.attributes.position.itemSize !== 3 ) { | ||
@@ -47,3 +44,2 @@ | ||
} | ||
setWeightAttribute( name ) { | ||
@@ -55,3 +51,2 @@ | ||
} | ||
build() { | ||
@@ -61,8 +56,9 @@ | ||
const weightAttribute = this.weightAttribute; | ||
const faceWeights = new Float32Array( positionAttribute.count / 3 ); // Accumulate weights for each mesh face. | ||
const faceWeights = new Float32Array( positionAttribute.count / 3 ); | ||
// Accumulate weights for each mesh face. | ||
for ( let i = 0; i < positionAttribute.count; i += 3 ) { | ||
let faceWeight = 1; | ||
if ( weightAttribute ) { | ||
@@ -75,17 +71,14 @@ | ||
_face.a.fromBufferAttribute( positionAttribute, i ); | ||
_face.b.fromBufferAttribute( positionAttribute, i + 1 ); | ||
_face.c.fromBufferAttribute( positionAttribute, i + 2 ); | ||
faceWeight *= _face.getArea(); | ||
faceWeights[ i / 3 ] = faceWeight; | ||
} // Store cumulative total face weights in an array, where weight index | ||
} | ||
// Store cumulative total face weights in an array, where weight index | ||
// corresponds to face index. | ||
this.distribution = new Float32Array( positionAttribute.count / 3 ); | ||
let cumulativeTotal = 0; | ||
for ( let i = 0; i < faceWeights.length; i ++ ) { | ||
@@ -101,3 +94,2 @@ | ||
} | ||
setRandomGenerator( randomFunction ) { | ||
@@ -109,3 +101,2 @@ | ||
} | ||
sample( targetPosition, targetNormal, targetColor ) { | ||
@@ -118,3 +109,2 @@ | ||
} | ||
binarySearch( x ) { | ||
@@ -126,7 +116,5 @@ | ||
let index = - 1; | ||
while ( start <= end ) { | ||
const mid = Math.ceil( ( start + end ) / 2 ); | ||
if ( mid === 0 || dist[ mid - 1 ] <= x && dist[ mid ] > x ) { | ||
@@ -152,3 +140,2 @@ | ||
} | ||
sampleFace( faceIndex, targetPosition, targetNormal, targetColor ) { | ||
@@ -158,3 +145,2 @@ | ||
let v = this.randomFunction(); | ||
if ( u + v > 1 ) { | ||
@@ -168,9 +154,5 @@ | ||
_face.a.fromBufferAttribute( this.positionAttribute, faceIndex * 3 ); | ||
_face.b.fromBufferAttribute( this.positionAttribute, faceIndex * 3 + 1 ); | ||
_face.c.fromBufferAttribute( this.positionAttribute, faceIndex * 3 + 2 ); | ||
targetPosition.set( 0, 0, 0 ).addScaledVector( _face.a, u ).addScaledVector( _face.b, v ).addScaledVector( _face.c, 1 - ( u + v ) ); | ||
if ( targetNormal !== undefined ) { | ||
@@ -185,9 +167,5 @@ | ||
_face.a.fromBufferAttribute( this.colorAttribute, faceIndex * 3 ); | ||
_face.b.fromBufferAttribute( this.colorAttribute, faceIndex * 3 + 1 ); | ||
_face.c.fromBufferAttribute( this.colorAttribute, faceIndex * 3 + 2 ); | ||
_color.set( 0, 0, 0 ).addScaledVector( _face.a, u ).addScaledVector( _face.b, v ).addScaledVector( _face.c, 1 - ( u + v ) ); | ||
targetColor.r = _color.x; | ||
@@ -194,0 +172,0 @@ targetColor.g = _color.y; |
( function () { | ||
// module scope helper variables | ||
const a = { | ||
@@ -9,4 +11,4 @@ c: null, | ||
e: [] // half width | ||
}; | ||
}; | ||
const b = { | ||
@@ -18,4 +20,4 @@ c: null, | ||
e: [] // half width | ||
}; | ||
}; | ||
const R = [[], [], []]; | ||
@@ -34,4 +36,6 @@ const AbsR = [[], [], []]; | ||
const inverse = new THREE.Matrix4(); | ||
const localRay = new THREE.Ray(); // OBB | ||
const localRay = new THREE.Ray(); | ||
// OBB | ||
class OBB { | ||
@@ -46,3 +50,2 @@ | ||
} | ||
set( center, halfSize, rotation ) { | ||
@@ -56,3 +59,2 @@ | ||
} | ||
copy( obb ) { | ||
@@ -66,3 +68,2 @@ | ||
} | ||
clone() { | ||
@@ -73,3 +74,2 @@ | ||
} | ||
getSize( result ) { | ||
@@ -80,2 +80,3 @@ | ||
} | ||
/** | ||
@@ -85,4 +86,2 @@ * Reference: Closest Point on OBB to Point in Real-Time Collision Detection | ||
*/ | ||
clampPoint( point, result ) { | ||
@@ -92,6 +91,10 @@ | ||
v1.subVectors( point, this.center ); | ||
this.rotation.extractBasis( xAxis, yAxis, zAxis ); // start at the center position of the OBB | ||
this.rotation.extractBasis( xAxis, yAxis, zAxis ); | ||
result.copy( this.center ); // project the target onto the OBB axes and walk towards that point | ||
// start at the center position of the OBB | ||
result.copy( this.center ); | ||
// project the target onto the OBB axes and walk towards that point | ||
const x = THREE.MathUtils.clamp( v1.dot( xAxis ), - halfSize.x, halfSize.x ); | ||
@@ -106,12 +109,12 @@ result.add( xAxis.multiplyScalar( x ) ); | ||
} | ||
containsPoint( point ) { | ||
v1.subVectors( point, this.center ); | ||
this.rotation.extractBasis( xAxis, yAxis, zAxis ); // project v1 onto each axis and check if these points lie inside the OBB | ||
this.rotation.extractBasis( xAxis, yAxis, zAxis ); | ||
// project v1 onto each axis and check if these points lie inside the OBB | ||
return Math.abs( v1.dot( xAxis ) ) <= this.halfSize.x && Math.abs( v1.dot( yAxis ) ) <= this.halfSize.y && Math.abs( v1.dot( zAxis ) ) <= this.halfSize.z; | ||
} | ||
intersectsBox3( box3 ) { | ||
@@ -122,11 +125,14 @@ | ||
} | ||
intersectsSphere( sphere ) { | ||
// find the point on the OBB closest to the sphere center | ||
this.clampPoint( sphere.center, closestPoint ); // if that point is inside the sphere, the OBB and sphere intersect | ||
this.clampPoint( sphere.center, closestPoint ); | ||
// if that point is inside the sphere, the OBB and sphere intersect | ||
return closestPoint.distanceToSquared( sphere.center ) <= sphere.radius * sphere.radius; | ||
} | ||
/** | ||
@@ -137,7 +143,6 @@ * Reference: OBB-OBB Intersection in Real-Time Collision Detection | ||
*/ | ||
intersectsOBB( obb, epsilon = Number.EPSILON ) { | ||
// prepare data structures (the code uses the same nomenclature like the reference) | ||
a.c = this.center; | ||
@@ -152,4 +157,6 @@ a.e[ 0 ] = this.halfSize.x; | ||
b.e[ 2 ] = obb.halfSize.z; | ||
obb.rotation.extractBasis( b.u[ 0 ], b.u[ 1 ], b.u[ 2 ] ); // compute rotation matrix expressing b in a's coordinate frame | ||
obb.rotation.extractBasis( b.u[ 0 ], b.u[ 1 ], b.u[ 2 ] ); | ||
// compute rotation matrix expressing b in a's coordinate frame | ||
for ( let i = 0; i < 3; i ++ ) { | ||
@@ -163,10 +170,15 @@ | ||
} // compute translation vector | ||
} | ||
// compute translation vector | ||
v1.subVectors( b.c, a.c ); // bring translation into a's coordinate frame | ||
v1.subVectors( b.c, a.c ); | ||
// bring translation into a's coordinate frame | ||
t[ 0 ] = v1.dot( a.u[ 0 ] ); | ||
t[ 1 ] = v1.dot( a.u[ 1 ] ); | ||
t[ 2 ] = v1.dot( a.u[ 2 ] ); // compute common subexpressions. Add in an epsilon term to | ||
t[ 2 ] = v1.dot( a.u[ 2 ] ); | ||
// compute common subexpressions. Add in an epsilon term to | ||
// counteract arithmetic errors when two edges are parallel and | ||
@@ -185,4 +197,6 @@ // their cross product is (near) null | ||
let ra, rb; // test axes L = A0, L = A1, L = A2 | ||
let ra, rb; | ||
// test axes L = A0, L = A1, L = A2 | ||
for ( let i = 0; i < 3; i ++ ) { | ||
@@ -194,4 +208,5 @@ | ||
} // test axes L = B0, L = B1, L = B2 | ||
} | ||
// test axes L = B0, L = B1, L = B2 | ||
@@ -204,44 +219,64 @@ for ( let i = 0; i < 3; i ++ ) { | ||
} // test axis L = A0 x B0 | ||
} | ||
// test axis L = A0 x B0 | ||
ra = a.e[ 1 ] * AbsR[ 2 ][ 0 ] + a.e[ 2 ] * AbsR[ 1 ][ 0 ]; | ||
rb = b.e[ 1 ] * AbsR[ 0 ][ 2 ] + b.e[ 2 ] * AbsR[ 0 ][ 1 ]; | ||
if ( Math.abs( t[ 2 ] * R[ 1 ][ 0 ] - t[ 1 ] * R[ 2 ][ 0 ] ) > ra + rb ) return false; // test axis L = A0 x B1 | ||
if ( Math.abs( t[ 2 ] * R[ 1 ][ 0 ] - t[ 1 ] * R[ 2 ][ 0 ] ) > ra + rb ) return false; | ||
// test axis L = A0 x B1 | ||
ra = a.e[ 1 ] * AbsR[ 2 ][ 1 ] + a.e[ 2 ] * AbsR[ 1 ][ 1 ]; | ||
rb = b.e[ 0 ] * AbsR[ 0 ][ 2 ] + b.e[ 2 ] * AbsR[ 0 ][ 0 ]; | ||
if ( Math.abs( t[ 2 ] * R[ 1 ][ 1 ] - t[ 1 ] * R[ 2 ][ 1 ] ) > ra + rb ) return false; // test axis L = A0 x B2 | ||
if ( Math.abs( t[ 2 ] * R[ 1 ][ 1 ] - t[ 1 ] * R[ 2 ][ 1 ] ) > ra + rb ) return false; | ||
// test axis L = A0 x B2 | ||
ra = a.e[ 1 ] * AbsR[ 2 ][ 2 ] + a.e[ 2 ] * AbsR[ 1 ][ 2 ]; | ||
rb = b.e[ 0 ] * AbsR[ 0 ][ 1 ] + b.e[ 1 ] * AbsR[ 0 ][ 0 ]; | ||
if ( Math.abs( t[ 2 ] * R[ 1 ][ 2 ] - t[ 1 ] * R[ 2 ][ 2 ] ) > ra + rb ) return false; // test axis L = A1 x B0 | ||
if ( Math.abs( t[ 2 ] * R[ 1 ][ 2 ] - t[ 1 ] * R[ 2 ][ 2 ] ) > ra + rb ) return false; | ||
// test axis L = A1 x B0 | ||
ra = a.e[ 0 ] * AbsR[ 2 ][ 0 ] + a.e[ 2 ] * AbsR[ 0 ][ 0 ]; | ||
rb = b.e[ 1 ] * AbsR[ 1 ][ 2 ] + b.e[ 2 ] * AbsR[ 1 ][ 1 ]; | ||
if ( Math.abs( t[ 0 ] * R[ 2 ][ 0 ] - t[ 2 ] * R[ 0 ][ 0 ] ) > ra + rb ) return false; // test axis L = A1 x B1 | ||
if ( Math.abs( t[ 0 ] * R[ 2 ][ 0 ] - t[ 2 ] * R[ 0 ][ 0 ] ) > ra + rb ) return false; | ||
// test axis L = A1 x B1 | ||
ra = a.e[ 0 ] * AbsR[ 2 ][ 1 ] + a.e[ 2 ] * AbsR[ 0 ][ 1 ]; | ||
rb = b.e[ 0 ] * AbsR[ 1 ][ 2 ] + b.e[ 2 ] * AbsR[ 1 ][ 0 ]; | ||
if ( Math.abs( t[ 0 ] * R[ 2 ][ 1 ] - t[ 2 ] * R[ 0 ][ 1 ] ) > ra + rb ) return false; // test axis L = A1 x B2 | ||
if ( Math.abs( t[ 0 ] * R[ 2 ][ 1 ] - t[ 2 ] * R[ 0 ][ 1 ] ) > ra + rb ) return false; | ||
// test axis L = A1 x B2 | ||
ra = a.e[ 0 ] * AbsR[ 2 ][ 2 ] + a.e[ 2 ] * AbsR[ 0 ][ 2 ]; | ||
rb = b.e[ 0 ] * AbsR[ 1 ][ 1 ] + b.e[ 1 ] * AbsR[ 1 ][ 0 ]; | ||
if ( Math.abs( t[ 0 ] * R[ 2 ][ 2 ] - t[ 2 ] * R[ 0 ][ 2 ] ) > ra + rb ) return false; // test axis L = A2 x B0 | ||
if ( Math.abs( t[ 0 ] * R[ 2 ][ 2 ] - t[ 2 ] * R[ 0 ][ 2 ] ) > ra + rb ) return false; | ||
// test axis L = A2 x B0 | ||
ra = a.e[ 0 ] * AbsR[ 1 ][ 0 ] + a.e[ 1 ] * AbsR[ 0 ][ 0 ]; | ||
rb = b.e[ 1 ] * AbsR[ 2 ][ 2 ] + b.e[ 2 ] * AbsR[ 2 ][ 1 ]; | ||
if ( Math.abs( t[ 1 ] * R[ 0 ][ 0 ] - t[ 0 ] * R[ 1 ][ 0 ] ) > ra + rb ) return false; // test axis L = A2 x B1 | ||
if ( Math.abs( t[ 1 ] * R[ 0 ][ 0 ] - t[ 0 ] * R[ 1 ][ 0 ] ) > ra + rb ) return false; | ||
// test axis L = A2 x B1 | ||
ra = a.e[ 0 ] * AbsR[ 1 ][ 1 ] + a.e[ 1 ] * AbsR[ 0 ][ 1 ]; | ||
rb = b.e[ 0 ] * AbsR[ 2 ][ 2 ] + b.e[ 2 ] * AbsR[ 2 ][ 0 ]; | ||
if ( Math.abs( t[ 1 ] * R[ 0 ][ 1 ] - t[ 0 ] * R[ 1 ][ 1 ] ) > ra + rb ) return false; // test axis L = A2 x B2 | ||
if ( Math.abs( t[ 1 ] * R[ 0 ][ 1 ] - t[ 0 ] * R[ 1 ][ 1 ] ) > ra + rb ) return false; | ||
// test axis L = A2 x B2 | ||
ra = a.e[ 0 ] * AbsR[ 1 ][ 2 ] + a.e[ 1 ] * AbsR[ 0 ][ 2 ]; | ||
rb = b.e[ 0 ] * AbsR[ 2 ][ 1 ] + b.e[ 1 ] * AbsR[ 2 ][ 0 ]; | ||
if ( Math.abs( t[ 1 ] * R[ 0 ][ 2 ] - t[ 0 ] * R[ 1 ][ 2 ] ) > ra + rb ) return false; // since no separating axis is found, the OBBs must be intersecting | ||
if ( Math.abs( t[ 1 ] * R[ 0 ][ 2 ] - t[ 0 ] * R[ 1 ][ 2 ] ) > ra + rb ) return false; | ||
// since no separating axis is found, the OBBs must be intersecting | ||
return true; | ||
} | ||
/** | ||
@@ -251,15 +286,20 @@ * Reference: Testing Box Against Plane in Real-Time Collision Detection | ||
*/ | ||
intersectsPlane( plane ) { | ||
this.rotation.extractBasis( xAxis, yAxis, zAxis ); | ||
intersectsPlane( plane ) { | ||
// compute the projection interval radius of this OBB onto L(t) = this->center + t * p.normal; | ||
this.rotation.extractBasis( xAxis, yAxis, zAxis ); // compute the projection interval radius of this OBB onto L(t) = this->center + t * p.normal; | ||
const r = this.halfSize.x * Math.abs( plane.normal.dot( xAxis ) ) + this.halfSize.y * Math.abs( plane.normal.dot( yAxis ) ) + this.halfSize.z * Math.abs( plane.normal.dot( zAxis ) ); | ||
const r = this.halfSize.x * Math.abs( plane.normal.dot( xAxis ) ) + this.halfSize.y * Math.abs( plane.normal.dot( yAxis ) ) + this.halfSize.z * Math.abs( plane.normal.dot( zAxis ) ); // compute distance of the OBB's center from the plane | ||
// compute distance of the OBB's center from the plane | ||
const d = plane.normal.dot( this.center ) - plane.constant; // Intersection occurs when distance d falls within [-r,+r] interval | ||
const d = plane.normal.dot( this.center ) - plane.constant; | ||
// Intersection occurs when distance d falls within [-r,+r] interval | ||
return Math.abs( d ) <= r; | ||
} | ||
/** | ||
@@ -269,4 +309,2 @@ * Performs a ray/OBB intersection test and stores the intersection point | ||
*/ | ||
intersectRay( ray, result ) { | ||
@@ -276,14 +314,22 @@ | ||
// of the OBB. | ||
this.getSize( size ); | ||
aabb.setFromCenterAndSize( v1.set( 0, 0, 0 ), size ); // create a 4x4 transformation matrix | ||
aabb.setFromCenterAndSize( v1.set( 0, 0, 0 ), size ); | ||
// create a 4x4 transformation matrix | ||
matrix.setFromMatrix3( this.rotation ); | ||
matrix.setPosition( this.center ); // transform ray to the local space of the OBB | ||
matrix.setPosition( this.center ); | ||
// transform ray to the local space of the OBB | ||
inverse.copy( matrix ).invert(); | ||
localRay.copy( ray ).applyMatrix4( inverse ); // perform ray <-> AABB intersection test | ||
localRay.copy( ray ).applyMatrix4( inverse ); | ||
// perform ray <-> AABB intersection test | ||
if ( localRay.intersectBox( aabb, result ) ) { | ||
// transform the intersection point back to world space | ||
return result.applyMatrix4( matrix ); | ||
@@ -298,2 +344,3 @@ | ||
} | ||
/** | ||
@@ -303,4 +350,2 @@ * Performs a ray/OBB intersection test. Returns either true or false if | ||
*/ | ||
intersectsRay( ray ) { | ||
@@ -311,3 +356,2 @@ | ||
} | ||
fromBox3( box3 ) { | ||
@@ -321,3 +365,2 @@ | ||
} | ||
equals( obb ) { | ||
@@ -328,3 +371,2 @@ | ||
} | ||
applyMatrix4( matrix ) { | ||
@@ -362,3 +404,2 @@ | ||
} | ||
const obb = new OBB(); | ||
@@ -365,0 +406,0 @@ |
( function () { | ||
const _v1 = new THREE.Vector3(); | ||
const _v2 = new THREE.Vector3(); | ||
const _plane = new THREE.Plane(); | ||
const _line1 = new THREE.Line3(); | ||
const _line2 = new THREE.Line3(); | ||
const _sphere = new THREE.Sphere(); | ||
const _capsule = new THREE.Capsule(); | ||
class Octree { | ||
@@ -26,3 +19,2 @@ | ||
} | ||
addTriangle( triangle ) { | ||
@@ -41,7 +33,7 @@ | ||
} | ||
calcBox() { | ||
this.box = this.bounds.clone(); // offset small ammount to account for regular grid | ||
this.box = this.bounds.clone(); | ||
// offset small ammount to account for regular grid | ||
this.box.min.x -= 0.01; | ||
@@ -53,3 +45,2 @@ this.box.min.y -= 0.01; | ||
} | ||
split( level ) { | ||
@@ -59,5 +50,3 @@ | ||
const subTrees = []; | ||
const halfsize = _v2.copy( this.box.max ).sub( this.box.min ).multiplyScalar( 0.5 ); | ||
for ( let x = 0; x < 2; x ++ ) { | ||
@@ -70,5 +59,3 @@ | ||
const box = new THREE.Box3(); | ||
const v = _v1.set( x, y, z ); | ||
box.min.copy( this.box.min ).add( v.multiply( halfsize ) ); | ||
@@ -85,3 +72,2 @@ box.max.copy( box.min ).add( halfsize ); | ||
let triangle; | ||
while ( triangle = this.triangles.pop() ) { | ||
@@ -104,3 +90,2 @@ | ||
const len = subTrees[ i ].triangles.length; | ||
if ( len > 8 && level < 16 ) { | ||
@@ -123,3 +108,2 @@ | ||
} | ||
build() { | ||
@@ -132,3 +116,2 @@ | ||
} | ||
getRayTriangles( ray, triangles ) { | ||
@@ -140,3 +123,2 @@ | ||
if ( ! ray.intersectsBox( subTree.box ) ) continue; | ||
if ( subTree.triangles.length > 0 ) { | ||
@@ -161,3 +143,2 @@ | ||
} | ||
triangleCapsuleIntersect( capsule, triangle ) { | ||
@@ -168,3 +149,2 @@ | ||
const d2 = _plane.distanceToPoint( capsule.end ) - capsule.radius; | ||
if ( d1 > 0 && d2 > 0 || d1 < - capsule.radius && d2 < - capsule.radius ) { | ||
@@ -177,5 +157,3 @@ | ||
const delta = Math.abs( d1 / ( Math.abs( d1 ) + Math.abs( d2 ) ) ); | ||
const intersectPoint = _v1.copy( capsule.start ).lerp( capsule.end, delta ); | ||
if ( triangle.containsPoint( intersectPoint ) ) { | ||
@@ -192,13 +170,8 @@ | ||
const r2 = capsule.radius * capsule.radius; | ||
const line1 = _line1.set( capsule.start, capsule.end ); | ||
const lines = [[ triangle.a, triangle.b ], [ triangle.b, triangle.c ], [ triangle.c, triangle.a ]]; | ||
for ( let i = 0; i < lines.length; i ++ ) { | ||
const line2 = _line2.set( lines[ i ][ 0 ], lines[ i ][ 1 ] ); | ||
const [ point1, point2 ] = capsule.lineLineMinimumPoints( line1, line2 ); | ||
if ( point1.distanceToSquared( point2 ) < r2 ) { | ||
@@ -219,3 +192,2 @@ | ||
} | ||
triangleSphereIntersect( sphere, triangle ) { | ||
@@ -227,5 +199,3 @@ | ||
const r2 = sphere.radius * sphere.radius - depth * depth; | ||
const plainPoint = _plane.projectPoint( sphere.center, _v1 ); | ||
if ( triangle.containsPoint( sphere.center ) ) { | ||
@@ -242,11 +212,7 @@ | ||
const lines = [[ triangle.a, triangle.b ], [ triangle.b, triangle.c ], [ triangle.c, triangle.a ]]; | ||
for ( let i = 0; i < lines.length; i ++ ) { | ||
_line1.set( lines[ i ][ 0 ], lines[ i ][ 1 ] ); | ||
_line1.closestPointToPoint( plainPoint, true, _v2 ); | ||
const d = _v2.distanceToSquared( sphere.center ); | ||
if ( d < r2 ) { | ||
@@ -267,3 +233,2 @@ | ||
} | ||
getSphereTriangles( sphere, triangles ) { | ||
@@ -275,3 +240,2 @@ | ||
if ( ! sphere.intersectsBox( subTree.box ) ) continue; | ||
if ( subTree.triangles.length > 0 ) { | ||
@@ -294,3 +258,2 @@ | ||
} | ||
getCapsuleTriangles( capsule, triangles ) { | ||
@@ -302,3 +265,2 @@ | ||
if ( ! capsule.intersectsBox( subTree.box ) ) continue; | ||
if ( subTree.triangles.length > 0 ) { | ||
@@ -321,7 +283,5 @@ | ||
} | ||
sphereIntersect( sphere ) { | ||
_sphere.copy( sphere ); | ||
const triangles = []; | ||
@@ -331,3 +291,2 @@ let result, | ||
this.getSphereTriangles( sphere, triangles ); | ||
for ( let i = 0; i < triangles.length; i ++ ) { | ||
@@ -338,3 +297,2 @@ | ||
hit = true; | ||
_sphere.center.add( result.normal.multiplyScalar( result.depth ) ); | ||
@@ -349,3 +307,2 @@ | ||
const collisionVector = _sphere.center.clone().sub( sphere.center ); | ||
const depth = collisionVector.length(); | ||
@@ -362,7 +319,5 @@ return { | ||
} | ||
capsuleIntersect( capsule ) { | ||
_capsule.copy( capsule ); | ||
const triangles = []; | ||
@@ -372,3 +327,2 @@ let result, | ||
this.getCapsuleTriangles( _capsule, triangles ); | ||
for ( let i = 0; i < triangles.length; i ++ ) { | ||
@@ -379,3 +333,2 @@ | ||
hit = true; | ||
_capsule.translate( result.normal.multiplyScalar( result.depth ) ); | ||
@@ -390,3 +343,2 @@ | ||
const collisionVector = _capsule.getCenter( new THREE.Vector3() ).sub( capsule.getCenter( _v1 ) ); | ||
const depth = collisionVector.length(); | ||
@@ -403,3 +355,2 @@ return { | ||
} | ||
rayIntersect( ray ) { | ||
@@ -413,11 +364,8 @@ | ||
this.getRayTriangles( ray, triangles ); | ||
for ( let i = 0; i < triangles.length; i ++ ) { | ||
const result = ray.intersectTriangle( triangles[ i ].a, triangles[ i ].b, triangles[ i ].c, true, _v1 ); | ||
if ( result ) { | ||
const newdistance = result.sub( ray.origin ).length(); | ||
if ( distance > newdistance ) { | ||
@@ -442,3 +390,2 @@ | ||
} | ||
fromGraphNode( group ) { | ||
@@ -453,3 +400,2 @@ | ||
isTemp = false; | ||
if ( obj.geometry.index !== null ) { | ||
@@ -467,3 +413,2 @@ | ||
const positionAttribute = geometry.getAttribute( 'position' ); | ||
for ( let i = 0; i < positionAttribute.count; i += 3 ) { | ||
@@ -470,0 +415,0 @@ |
@@ -22,3 +22,2 @@ ( function () { | ||
this.p = []; | ||
for ( let i = 0; i < 256; i ++ ) { | ||
@@ -28,7 +27,6 @@ | ||
} // To remove the need for index wrapping, double the permutation table length | ||
} | ||
// To remove the need for index wrapping, double the permutation table length | ||
this.perm = []; | ||
for ( let i = 0; i < 512; i ++ ) { | ||
@@ -38,10 +36,9 @@ | ||
} // A lookup table to traverse the simplex around a given point in 4D. | ||
} | ||
// 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 ]]; | ||
} | ||
dot( g, x, y ) { | ||
@@ -52,3 +49,2 @@ | ||
} | ||
dot3( g, x, y, z ) { | ||
@@ -59,3 +55,2 @@ | ||
} | ||
dot4( g, x, y, z, w ) { | ||
@@ -66,13 +61,10 @@ | ||
} | ||
noise( xin, yin ) { | ||
let n0; // Noise contributions from the three corners | ||
let n1; | ||
let n2; // Skew the input space to determine which simplex cell we're in | ||
let n2; | ||
// Skew the input space to determine which simplex cell we're in | ||
const F2 = 0.5 * ( Math.sqrt( 3.0 ) - 1.0 ); | ||
const s = ( xin + yin ) * F2; // Hairy factor for 2D | ||
const i = Math.floor( xin + s ); | ||
@@ -83,18 +75,18 @@ const j = Math.floor( yin + s ); | ||
const X0 = i - t; // Unskew the cell origin back to (x,y) space | ||
const Y0 = j - t; | ||
const x0 = xin - X0; // The x,y distances from the cell origin | ||
const y0 = yin - Y0; | ||
const y0 = yin - Y0; // For the 2D case, the simplex shape is an equilateral triangle. | ||
// For the 2D case, the simplex shape is an equilateral triangle. | ||
// Determine which simplex we are in. | ||
let i1; // Offsets for second (middle) corner of simplex in (i,j) coords | ||
let j1; | ||
if ( x0 > y0 ) { | ||
i1 = 1; | ||
j1 = 0; // lower triangle, XY order: (0,0)->(1,0)->(1,1) | ||
j1 = 0; | ||
// lower triangle, XY order: (0,0)->(1,0)->(1,1) | ||
} else { | ||
@@ -106,14 +98,11 @@ | ||
} // 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 | ||
const x1 = x0 - i1 + G2; // Offsets for middle corner in (x,y) unskewed coords | ||
const y1 = y0 - j1 + G2; | ||
const x2 = x0 - 1.0 + 2.0 * G2; // Offsets for last corner in (x,y) unskewed coords | ||
const y2 = y0 - 1.0 + 2.0 * G2; // Work out the hashed gradient indices of the three simplex corners | ||
const y2 = y0 - 1.0 + 2.0 * G2; | ||
// Work out the hashed gradient indices of the three simplex corners | ||
const ii = i & 255; | ||
@@ -123,4 +112,4 @@ const jj = j & 255; | ||
const gi1 = this.perm[ ii + i1 + this.perm[ jj + j1 ] ] % 12; | ||
const gi2 = this.perm[ ii + 1 + this.perm[ jj + 1 ] ] % 12; // Calculate the contribution from the three corners | ||
const gi2 = this.perm[ ii + 1 + this.perm[ jj + 1 ] ] % 12; | ||
// Calculate the contribution from the three corners | ||
let t0 = 0.5 - x0 * x0 - y0 * y0; | ||
@@ -148,21 +137,20 @@ if ( t0 < 0 ) n0 = 0.0; else { | ||
} // Add contributions from each corner to get the final noise value. | ||
} | ||
// 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 | ||
} | ||
// 3D simplex noise | ||
noise3d( xin, yin, zin ) { | ||
let n0; // Noise contributions from the four corners | ||
let n1; | ||
let n2; | ||
let n3; // Skew the input space to determine which simplex cell we're in | ||
let n3; | ||
// Skew the input space to determine which simplex cell we're in | ||
const F3 = 1.0 / 3.0; | ||
const s = ( xin + yin + zin ) * F3; // Very nice and simple skew factor for 3D | ||
const i = Math.floor( xin + s ); | ||
@@ -172,14 +160,12 @@ const j = Math.floor( yin + s ); | ||
const G3 = 1.0 / 6.0; // Very nice and simple unskew factor, too | ||
const t = ( i + j + k ) * G3; | ||
const X0 = i - t; // Unskew the cell origin back to (x,y,z) space | ||
const Y0 = j - t; | ||
const Z0 = k - t; | ||
const x0 = xin - X0; // The x,y,z distances from the cell origin | ||
const y0 = yin - Y0; | ||
const z0 = zin - Z0; | ||
const y0 = yin - Y0; | ||
const z0 = zin - Z0; // For the 3D case, the simplex shape is a slightly irregular tetrahedron. | ||
// For the 3D case, the simplex shape is a slightly irregular tetrahedron. | ||
// Determine which simplex we are in. | ||
let i1; // Offsets for second corner of simplex in (i,j,k) coords | ||
@@ -190,6 +176,4 @@ | ||
let i2; // Offsets for third corner of simplex in (i,j,k) coords | ||
let j2; | ||
let k2; | ||
if ( x0 >= y0 ) { | ||
@@ -204,4 +188,6 @@ | ||
j2 = 1; | ||
k2 = 0; // X Y Z order | ||
k2 = 0; | ||
// X Y Z order | ||
} else if ( x0 >= z0 ) { | ||
@@ -214,4 +200,6 @@ | ||
j2 = 0; | ||
k2 = 1; // X Z Y order | ||
k2 = 1; | ||
// X Z Y order | ||
} else { | ||
@@ -231,2 +219,3 @@ | ||
// x0<y0 | ||
if ( y0 < z0 ) { | ||
@@ -239,4 +228,6 @@ | ||
j2 = 1; | ||
k2 = 1; // Z Y X order | ||
k2 = 1; | ||
// Z Y X order | ||
} else if ( x0 < z0 ) { | ||
@@ -249,4 +240,6 @@ | ||
j2 = 1; | ||
k2 = 1; // Y Z X order | ||
k2 = 1; | ||
// Y Z X order | ||
} else { | ||
@@ -263,21 +256,18 @@ | ||
} // 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 (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. | ||
const x1 = x0 - i1 + G3; // Offsets for second corner in (x,y,z) coords | ||
const y1 = y0 - j1 + G3; | ||
const z1 = z0 - k1 + G3; | ||
const x2 = x0 - i2 + 2.0 * G3; // Offsets for third corner in (x,y,z) coords | ||
const y2 = y0 - j2 + 2.0 * G3; | ||
const z2 = z0 - k2 + 2.0 * G3; | ||
const x3 = x0 - 1.0 + 3.0 * G3; // Offsets for last corner in (x,y,z) coords | ||
const y3 = y0 - 1.0 + 3.0 * G3; | ||
const z3 = z0 - 1.0 + 3.0 * G3; // Work out the hashed gradient indices of the four simplex corners | ||
const z3 = z0 - 1.0 + 3.0 * G3; | ||
// Work out the hashed gradient indices of the four simplex corners | ||
const ii = i & 255; | ||
@@ -289,4 +279,4 @@ const jj = j & 255; | ||
const gi2 = this.perm[ ii + i2 + this.perm[ jj + j2 + this.perm[ kk + k2 ] ] ] % 12; | ||
const gi3 = this.perm[ ii + 1 + this.perm[ jj + 1 + this.perm[ kk + 1 ] ] ] % 12; // Calculate the contribution from the four corners | ||
const gi3 = this.perm[ ii + 1 + this.perm[ jj + 1 + this.perm[ kk + 1 ] ] ] % 12; | ||
// Calculate the contribution from the four corners | ||
let t0 = 0.6 - x0 * x0 - y0 * y0 - z0 * z0; | ||
@@ -322,10 +312,11 @@ if ( t0 < 0 ) n0 = 0.0; else { | ||
} // Add contributions from each corner to get the final noise value. | ||
} | ||
// 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 | ||
} | ||
// 4D simplex noise | ||
noise4d( x, y, z, w ) { | ||
@@ -336,15 +327,14 @@ | ||
const simplex = this.simplex; | ||
const perm = this.perm; // The skewing and unskewing factors are hairy again for the 4D case | ||
const perm = this.perm; | ||
// The skewing and unskewing factors are hairy again for the 4D case | ||
const F4 = ( Math.sqrt( 5.0 ) - 1.0 ) / 4.0; | ||
const G4 = ( 5.0 - Math.sqrt( 5.0 ) ) / 20.0; | ||
let n0; // Noise contributions from the five corners | ||
let n1; | ||
let n2; | ||
let n3; | ||
let n4; // Skew the (x,y,z,w) space to determine which cell of 24 simplices we're in | ||
let n4; | ||
// Skew the (x,y,z,w) space to determine which cell of 24 simplices we're in | ||
const s = ( x + y + z + w ) * F4; // Factor for 4D skewing | ||
const i = Math.floor( x + s ); | ||
@@ -355,5 +345,3 @@ const j = Math.floor( y + s ); | ||
const t = ( i + j + k + l ) * G4; // Factor for 4D unskewing | ||
const X0 = i - t; // Unskew the cell origin back to (x,y,z,w) space | ||
const Y0 = j - t; | ||
@@ -363,6 +351,7 @@ const Z0 = k - t; | ||
const x0 = x - X0; // The x,y,z,w distances from the cell origin | ||
const y0 = y - Y0; | ||
const z0 = z - Z0; | ||
const w0 = w - W0; // For the 4D case, the simplex is a 4D shape I won't even try to describe. | ||
const 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 | ||
@@ -375,3 +364,2 @@ // determine the magnitude ordering of x0, y0, z0 and w0. | ||
// for an integer index. | ||
const c1 = x0 > y0 ? 32 : 0; | ||
@@ -383,3 +371,5 @@ const c2 = x0 > z0 ? 16 : 0; | ||
const c6 = z0 > w0 ? 1 : 0; | ||
const c = c1 + c2 + c3 + c4 + c5 + c6; // simplex[c] is a 4-vector with the numbers 0, 1, 2 and 3 in some order. | ||
const c = c1 + c2 + c3 + c4 + c5 + c6; | ||
// 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 | ||
@@ -389,20 +379,18 @@ // impossible. Only the 24 indices which have non-zero entries make any sense. | ||
// The number 3 in the "simplex" array is at the position of the largest coordinate. | ||
const i1 = simplex[ c ][ 0 ] >= 3 ? 1 : 0; | ||
const j1 = simplex[ c ][ 1 ] >= 3 ? 1 : 0; | ||
const k1 = simplex[ c ][ 2 ] >= 3 ? 1 : 0; | ||
const l1 = simplex[ c ][ 3 ] >= 3 ? 1 : 0; // The number 2 in the "simplex" array is at the second largest coordinate. | ||
const l1 = simplex[ c ][ 3 ] >= 3 ? 1 : 0; | ||
// The number 2 in the "simplex" array is at the second largest coordinate. | ||
const i2 = simplex[ c ][ 0 ] >= 2 ? 1 : 0; | ||
const j2 = simplex[ c ][ 1 ] >= 2 ? 1 : 0; | ||
const k2 = simplex[ c ][ 2 ] >= 2 ? 1 : 0; | ||
const l2 = simplex[ c ][ 3 ] >= 2 ? 1 : 0; // The number 1 in the "simplex" array is at the second smallest coordinate. | ||
const l2 = simplex[ c ][ 3 ] >= 2 ? 1 : 0; | ||
// The number 1 in the "simplex" array is at the second smallest coordinate. | ||
const i3 = simplex[ c ][ 0 ] >= 1 ? 1 : 0; | ||
const j3 = simplex[ c ][ 1 ] >= 1 ? 1 : 0; | ||
const k3 = simplex[ c ][ 2 ] >= 1 ? 1 : 0; | ||
const l3 = simplex[ c ][ 3 ] >= 1 ? 1 : 0; // The fifth corner has all coordinate offsets = 1, so no need to look that up. | ||
const l3 = simplex[ c ][ 3 ] >= 1 ? 1 : 0; | ||
// The fifth corner has all coordinate offsets = 1, so no need to look that up. | ||
const x1 = x0 - i1 + G4; // Offsets for second corner in (x,y,z,w) coords | ||
const y1 = y0 - j1 + G4; | ||
@@ -412,3 +400,2 @@ const z1 = z0 - k1 + G4; | ||
const x2 = x0 - i2 + 2.0 * G4; // Offsets for third corner in (x,y,z,w) coords | ||
const y2 = y0 - j2 + 2.0 * G4; | ||
@@ -418,3 +405,2 @@ const z2 = z0 - k2 + 2.0 * G4; | ||
const x3 = x0 - i3 + 3.0 * G4; // Offsets for fourth corner in (x,y,z,w) coords | ||
const y3 = y0 - j3 + 3.0 * G4; | ||
@@ -424,7 +410,6 @@ const z3 = z0 - k3 + 3.0 * G4; | ||
const x4 = x0 - 1.0 + 4.0 * G4; // Offsets for last corner in (x,y,z,w) coords | ||
const y4 = y0 - 1.0 + 4.0 * G4; | ||
const z4 = z0 - 1.0 + 4.0 * G4; | ||
const w4 = w0 - 1.0 + 4.0 * G4; // Work out the hashed gradient indices of the five simplex corners | ||
const w4 = w0 - 1.0 + 4.0 * G4; | ||
// Work out the hashed gradient indices of the five simplex corners | ||
const ii = i & 255; | ||
@@ -438,4 +423,4 @@ const jj = j & 255; | ||
const gi3 = perm[ ii + i3 + perm[ jj + j3 + perm[ kk + k3 + perm[ ll + l3 ] ] ] ] % 32; | ||
const gi4 = perm[ ii + 1 + perm[ jj + 1 + perm[ kk + 1 + perm[ ll + 1 ] ] ] ] % 32; // Calculate the contribution from the five corners | ||
const gi4 = perm[ ii + 1 + perm[ jj + 1 + perm[ kk + 1 + perm[ ll + 1 ] ] ] ] % 32; | ||
// Calculate the contribution from the five corners | ||
let t0 = 0.6 - x0 * x0 - y0 * y0 - z0 * z0 - w0 * w0; | ||
@@ -479,4 +464,5 @@ if ( t0 < 0 ) n0 = 0.0; else { | ||
} // Sum up and scale the result to cover the range [-1,1] | ||
} | ||
// Sum up and scale the result to cover the range [-1,1] | ||
return 27.0 * ( n0 + n1 + n2 + n3 + n4 ); | ||
@@ -483,0 +469,0 @@ |
@@ -33,3 +33,2 @@ ( function () { | ||
const _v1 = new THREE.Vector3(); | ||
class ConvexObjectBreaker { | ||
@@ -63,7 +62,5 @@ | ||
const n = 30 * 30; | ||
for ( let i = 0; i < n; i ++ ) this.segments[ i ] = false; | ||
} | ||
prepareBreakableObject( object, mass, velocity, angularVelocity, breakable ) { | ||
@@ -74,2 +71,3 @@ | ||
// mass must be > 0 | ||
if ( ! object.geometry.isBufferGeometry ) { | ||
@@ -88,2 +86,3 @@ | ||
} | ||
/* | ||
@@ -95,4 +94,2 @@ * @param {int} maxRadialIterations Iterations for radial cuts. | ||
*/ | ||
subdivideByImpact( object, pointOfImpact, normal, maxRadialIterations, maxRandomIterations ) { | ||
@@ -107,3 +104,2 @@ | ||
const scope = this; | ||
function subdivideRadial( subObject, startAngle, endAngle, numIterations ) { | ||
@@ -119,3 +115,2 @@ | ||
let angle = Math.PI; | ||
if ( numIterations === 0 ) { | ||
@@ -130,4 +125,5 @@ | ||
angle = ( endAngle - startAngle ) * ( 0.2 + 0.6 * Math.random() ) + startAngle; // Rotate tempPlane2 at impact point around normal axis and the angle | ||
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 ); | ||
@@ -138,4 +134,5 @@ tempPlane2.setFromCoplanarPoints( pointOfImpact, scope.tempVector3, scope.tempVector3_2 ); | ||
angle = ( 0.5 * ( numIterations & 1 ) + 0.2 * ( 2 - Math.random() ) ) * Math.PI; // Rotate tempPlane2 at object position around normal axis and the angle | ||
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 ); | ||
@@ -147,9 +144,8 @@ scope.tempVector3_3.copy( normal ).add( subObject.position ); | ||
} // Perform the cut | ||
} | ||
// Perform the cut | ||
scope.cutByPlane( subObject, tempPlane2, scope.tempResultObjects ); | ||
const obj1 = scope.tempResultObjects.object1; | ||
const obj2 = scope.tempResultObjects.object2; | ||
if ( obj1 ) { | ||
@@ -173,3 +169,2 @@ | ||
} | ||
cutByPlane( object, plane, output ) { | ||
@@ -181,2 +176,3 @@ | ||
// Returned value is number of pieces, 0 for error. | ||
const geometry = object.geometry; | ||
@@ -188,3 +184,2 @@ const coords = geometry.attributes.position.array; | ||
let indices = geometry.getIndex(); | ||
if ( indices ) { | ||
@@ -200,2 +195,3 @@ | ||
// vert = 0, 1 or 2. | ||
const idx = faceIdx * 3 + vert; | ||
@@ -208,13 +204,13 @@ return indices ? indices[ idx ] : idx; | ||
const points2 = []; | ||
const delta = this.smallDelta; // Reset segments mark | ||
const delta = this.smallDelta; | ||
// Reset segments mark | ||
const numPointPairs = numPoints * numPoints; | ||
for ( let i = 0; i < numPointPairs; i ++ ) this.segments[ i ] = false; | ||
const p0 = this.tempVector3_P0; | ||
const p1 = this.tempVector3_P1; | ||
const n0 = this.tempVector3_N0; | ||
const n1 = this.tempVector3_N1; // Iterate through the faces to mark edges shared by coplanar faces | ||
const n1 = this.tempVector3_N1; | ||
// Iterate through the faces to mark edges shared by coplanar faces | ||
for ( let i = 0; i < numFaces - 1; i ++ ) { | ||
@@ -224,6 +220,6 @@ | ||
const b1 = getVertexIndex( i, 1 ); | ||
const c1 = getVertexIndex( i, 2 ); // Assuming all 3 vertices have the same normal | ||
const c1 = getVertexIndex( i, 2 ); | ||
// Assuming all 3 vertices have the same normal | ||
n0.set( normals[ a1 ], normals[ a1 ] + 1, normals[ a1 ] + 2 ); | ||
for ( let j = i + 1; j < numFaces; j ++ ) { | ||
@@ -233,7 +229,7 @@ | ||
const b2 = getVertexIndex( j, 1 ); | ||
const c2 = getVertexIndex( j, 2 ); // Assuming all 3 vertices have the same normal | ||
const c2 = getVertexIndex( j, 2 ); | ||
// Assuming all 3 vertices have the same normal | ||
n1.set( normals[ a2 ], normals[ a2 ] + 1, normals[ a2 ] + 2 ); | ||
const coplanar = 1 - n0.dot( n1 ) < delta; | ||
if ( coplanar ) { | ||
@@ -266,9 +262,10 @@ | ||
} // Transform the plane to object local space | ||
} | ||
// Transform the plane to object local space | ||
const localPlane = this.tempPlane_Cut; | ||
object.updateMatrix(); | ||
ConvexObjectBreaker.transformPlaneToLocalSpace( plane, object.matrix, localPlane ); // Iterate through the faces adding points to both pieces | ||
ConvexObjectBreaker.transformPlaneToLocalSpace( plane, object.matrix, localPlane ); | ||
// Iterate through the faces adding points to both pieces | ||
for ( let i = 0; i < numFaces; i ++ ) { | ||
@@ -279,3 +276,2 @@ | ||
const vc = getVertexIndex( i, 2 ); | ||
for ( let segment = 0; segment < 3; segment ++ ) { | ||
@@ -287,12 +283,12 @@ | ||
if ( segmentState ) continue; // The segment already has been processed in another face | ||
// Mark segment as processed (also inverted segment) | ||
this.segments[ i0 * numPoints + i1 ] = true; | ||
this.segments[ i1 * numPoints + i0 ] = true; | ||
p0.set( coords[ 3 * i0 ], coords[ 3 * i0 + 1 ], coords[ 3 * i0 + 2 ] ); | ||
p1.set( coords[ 3 * i1 ], coords[ 3 * i1 + 1 ], coords[ 3 * i1 + 2 ] ); // mark: 1 for negative side, 2 for positive side, 3 for coplanar point | ||
p1.set( coords[ 3 * i1 ], coords[ 3 * i1 + 1 ], coords[ 3 * i1 + 2 ] ); | ||
// mark: 1 for negative side, 2 for positive side, 3 for coplanar point | ||
let mark0 = 0; | ||
let d = localPlane.distanceToPoint( p0 ); | ||
if ( d > delta ) { | ||
@@ -314,8 +310,7 @@ | ||
} // mark: 1 for negative side, 2 for positive side, 3 for coplanar point | ||
} | ||
// mark: 1 for negative side, 2 for positive side, 3 for coplanar point | ||
let mark1 = 0; | ||
d = localPlane.distanceToPoint( p1 ); | ||
if ( d > delta ) { | ||
@@ -342,2 +337,3 @@ | ||
// Intersection of segment with the plane | ||
this.tempLine1.start.copy( p0 ); | ||
@@ -347,3 +343,2 @@ this.tempLine1.end.copy( p1 ); | ||
intersection = localPlane.intersectLine( this.tempLine1, intersection ); | ||
if ( intersection === null ) { | ||
@@ -366,17 +361,15 @@ | ||
} // Calculate debris mass (very fast and imprecise): | ||
} | ||
// Calculate debris mass (very fast and imprecise): | ||
const newMass = object.userData.mass * 0.5; | ||
const newMass = object.userData.mass * 0.5; // Calculate debris Center of Mass (again fast and imprecise) | ||
// Calculate debris Center of Mass (again fast and imprecise) | ||
this.tempCM1.set( 0, 0, 0 ); | ||
let radius1 = 0; | ||
const numPoints1 = points1.length; | ||
if ( numPoints1 > 0 ) { | ||
for ( let i = 0; i < numPoints1; i ++ ) this.tempCM1.add( points1[ i ] ); | ||
this.tempCM1.divideScalar( numPoints1 ); | ||
for ( let i = 0; i < numPoints1; i ++ ) { | ||
@@ -397,9 +390,6 @@ | ||
const numPoints2 = points2.length; | ||
if ( numPoints2 > 0 ) { | ||
for ( let i = 0; i < numPoints2; i ++ ) this.tempCM2.add( points2[ i ] ); | ||
this.tempCM2.divideScalar( numPoints2 ); | ||
for ( let i = 0; i < numPoints2; i ++ ) { | ||
@@ -420,3 +410,2 @@ | ||
let numObjects = 0; | ||
if ( numPoints1 > 4 ) { | ||
@@ -447,3 +436,2 @@ | ||
} | ||
static transformFreeVector( v, m ) { | ||
@@ -454,2 +442,3 @@ | ||
// THREE.Matrix4 orthogonal matrix (matrix without scale) | ||
const x = v.x, | ||
@@ -465,3 +454,2 @@ y = v.y, | ||
} | ||
static transformFreeVectorInverse( v, m ) { | ||
@@ -472,2 +460,3 @@ | ||
// THREE.Matrix4 orthogonal matrix (matrix without scale) | ||
const x = v.x, | ||
@@ -483,3 +472,2 @@ y = v.y, | ||
} | ||
static transformTiedVectorInverse( v, m ) { | ||
@@ -490,2 +478,3 @@ | ||
// THREE.Matrix4 orthogonal matrix (matrix without scale) | ||
const x = v.x, | ||
@@ -501,3 +490,2 @@ y = v.y, | ||
} | ||
static transformPlaneToLocalSpace( plane, m, resultPlane ) { | ||
@@ -508,4 +496,5 @@ | ||
const referencePoint = ConvexObjectBreaker.transformTiedVectorInverse( plane.coplanarPoint( _v1 ), m ); | ||
ConvexObjectBreaker.transformFreeVectorInverse( resultPlane.normal, m ); // recalculate constant (like in setFromNormalAndCoplanarPoint) | ||
ConvexObjectBreaker.transformFreeVectorInverse( resultPlane.normal, m ); | ||
// recalculate constant (like in setFromNormalAndCoplanarPoint) | ||
resultPlane.constant = - referencePoint.dot( resultPlane.normal ); | ||
@@ -512,0 +501,0 @@ |
@@ -118,3 +118,2 @@ ( function () { | ||
scene.add( mesh ); | ||
this.setDataType = function ( type ) { | ||
@@ -168,12 +167,13 @@ | ||
const variable = this.variables[ i ]; // Creates rendertargets and initialize them with input texture | ||
const variable = this.variables[ i ]; | ||
// Creates rendertargets and initialize them with input texture | ||
variable.renderTargets[ 0 ] = this.createRenderTarget( sizeX, sizeY, variable.wrapS, variable.wrapT, variable.minFilter, variable.magFilter ); | ||
variable.renderTargets[ 1 ] = this.createRenderTarget( sizeX, sizeY, variable.wrapS, variable.wrapT, variable.minFilter, variable.magFilter ); | ||
this.renderTexture( variable.initialValueTexture, variable.renderTargets[ 0 ] ); | ||
this.renderTexture( variable.initialValueTexture, variable.renderTargets[ 1 ] ); // Adds dependencies uniforms to the THREE.ShaderMaterial | ||
this.renderTexture( variable.initialValueTexture, variable.renderTargets[ 1 ] ); | ||
// Adds dependencies uniforms to the THREE.ShaderMaterial | ||
const material = variable.material; | ||
const uniforms = material.uniforms; | ||
if ( variable.dependencies !== null ) { | ||
@@ -184,3 +184,2 @@ | ||
const depVar = variable.dependencies[ d ]; | ||
if ( depVar.name !== variable.name ) { | ||
@@ -190,3 +189,2 @@ | ||
let found = false; | ||
for ( let j = 0; j < this.variables.length; j ++ ) { | ||
@@ -231,11 +229,10 @@ | ||
const nextTextureIndex = this.currentTextureIndex === 0 ? 1 : 0; | ||
for ( let i = 0, il = this.variables.length; i < il; i ++ ) { | ||
const variable = this.variables[ i ]; // Sets texture dependencies uniforms | ||
const variable = this.variables[ i ]; | ||
// Sets texture dependencies uniforms | ||
if ( variable.dependencies !== null ) { | ||
const uniforms = variable.material.uniforms; | ||
for ( let d = 0, dl = variable.dependencies.length; d < dl; d ++ ) { | ||
@@ -248,5 +245,5 @@ | ||
} // Performs the computation for this variable | ||
} | ||
// Performs the computation for this variable | ||
this.doRenderTarget( variable.material, variable.renderTargets[ nextTextureIndex ] ); | ||
@@ -277,3 +274,2 @@ | ||
const variables = this.variables; | ||
for ( let i = 0; i < variables.length; i ++ ) { | ||
@@ -284,3 +280,2 @@ | ||
const renderTargets = variable.renderTargets; | ||
for ( let j = 0; j < renderTargets.length; j ++ ) { | ||
@@ -303,4 +298,6 @@ | ||
this.addResolutionDefine = addResolutionDefine; // The following functions can be used to compute things manually | ||
this.addResolutionDefine = addResolutionDefine; | ||
// The following functions can be used to compute things manually | ||
function createShaderMaterial( computeFragmentShader, uniforms ) { | ||
@@ -320,3 +317,2 @@ | ||
this.createShaderMaterial = createShaderMaterial; | ||
this.createRenderTarget = function ( sizeXTexture, sizeYTexture, wrapS, wrapT, minFilter, magFilter ) { | ||
@@ -357,2 +353,3 @@ | ||
// output = RenderTarget | ||
passThruUniforms.passThruTexture.value = input; | ||
@@ -372,5 +369,3 @@ this.doRenderTarget( passThruShader, output ); | ||
renderer.xr.enabled = false; // Avoid camera modification | ||
renderer.shadowMap.autoUpdate = false; // Avoid re-computing shadows | ||
renderer.outputEncoding = THREE.LinearEncoding; | ||
@@ -388,4 +383,5 @@ renderer.toneMapping = THREE.NoToneMapping; | ||
}; // Shaders | ||
}; | ||
// Shaders | ||
@@ -392,0 +388,0 @@ function getPassThroughVertexShader() { |
( function () { | ||
const _translationObject = new THREE.Vector3(); | ||
const _quaternionObject = new THREE.Quaternion(); | ||
const _scaleObject = new THREE.Vector3(); | ||
const _translationWorld = new THREE.Vector3(); | ||
const _quaternionWorld = new THREE.Quaternion(); | ||
const _scaleWorld = new THREE.Vector3(); | ||
class Gyroscope extends THREE.Object3D { | ||
@@ -22,7 +16,8 @@ | ||
} | ||
updateMatrixWorld( force ) { | ||
this.matrixAutoUpdate && this.updateMatrix(); // update matrixWorld | ||
this.matrixAutoUpdate && this.updateMatrix(); | ||
// update matrixWorld | ||
if ( this.matrixWorldNeedsUpdate || force ) { | ||
@@ -46,4 +41,5 @@ | ||
} // update children | ||
} | ||
// update children | ||
@@ -50,0 +46,0 @@ for ( let i = 0, l = this.children.length; i < l; i ++ ) { |
@@ -17,3 +17,2 @@ ( function () { | ||
this.mixer = null; | ||
this.onLoadComplete = function () {}; | ||
@@ -24,7 +23,5 @@ | ||
} | ||
loadParts( config ) { | ||
const scope = this; | ||
function createPart( geometry, skinMap ) { | ||
@@ -40,9 +37,13 @@ | ||
map: skinMap | ||
} ); // | ||
} ); | ||
// | ||
const mesh = new THREE.Mesh( geometry, materialTexture ); | ||
mesh.rotation.y = - Math.PI / 2; | ||
mesh.castShadow = true; | ||
mesh.receiveShadow = true; // | ||
mesh.receiveShadow = true; | ||
// | ||
mesh.materialTexture = materialTexture; | ||
@@ -58,3 +59,2 @@ mesh.materialWireframe = materialWireframe; | ||
const textures = []; | ||
for ( let i = 0; i < textureUrls.length; i ++ ) { | ||
@@ -82,9 +82,10 @@ | ||
const weaponsTextures = []; | ||
for ( let i = 0; i < config.weapons.length; i ++ ) weaponsTextures[ i ] = config.weapons[ i ][ 1 ]; | ||
// SKINS | ||
for ( let i = 0; i < config.weapons.length; i ++ ) weaponsTextures[ i ] = config.weapons[ i ][ 1 ]; // SKINS | ||
this.skinsBody = loadTextures( config.baseUrl + 'skins/', config.skins ); | ||
this.skinsWeapon = loadTextures( config.baseUrl + 'skins/', weaponsTextures ); | ||
// BODY | ||
this.skinsBody = loadTextures( config.baseUrl + 'skins/', config.skins ); | ||
this.skinsWeapon = loadTextures( config.baseUrl + 'skins/', weaponsTextures ); // BODY | ||
const loader = new THREE.MD2Loader(); | ||
@@ -105,4 +106,6 @@ loader.load( config.baseUrl + config.body, function ( geo ) { | ||
} ); // WEAPONS | ||
} ); | ||
// WEAPONS | ||
const generateCallback = function ( index, name ) { | ||
@@ -132,3 +135,2 @@ | ||
} | ||
setPlaybackRate( rate ) { | ||
@@ -147,3 +149,2 @@ | ||
} | ||
setWireframe( wireframeEnabled ) { | ||
@@ -164,3 +165,2 @@ | ||
} | ||
setSkin( index ) { | ||
@@ -175,9 +175,6 @@ | ||
} | ||
setWeapon( index ) { | ||
for ( let i = 0; i < this.weapons.length; i ++ ) this.weapons[ i ].visible = false; | ||
const activeWeapon = this.weapons[ index ]; | ||
if ( activeWeapon ) { | ||
@@ -192,3 +189,2 @@ | ||
} | ||
setAnimation( clipName ) { | ||
@@ -206,3 +202,2 @@ | ||
const action = this.mixer.clipAction( clipName, this.meshBody ); | ||
if ( action ) { | ||
@@ -220,7 +215,5 @@ | ||
} | ||
syncWeaponAnimation() { | ||
const clipName = this.activeClipName; | ||
if ( this.meshWeapon ) { | ||
@@ -236,3 +229,2 @@ | ||
const action = this.mixer.clipAction( clipName, this.meshWeapon ); | ||
if ( action ) { | ||
@@ -247,3 +239,2 @@ | ||
} | ||
update( delta ) { | ||
@@ -250,0 +241,0 @@ |
@@ -7,7 +7,11 @@ ( function () { | ||
this.scale = 1; // animation parameters | ||
this.scale = 1; | ||
// animation parameters | ||
this.animationFPS = 6; | ||
this.transitionFrames = 15; // movement model parameters | ||
this.transitionFrames = 15; | ||
// movement model parameters | ||
this.maxSpeed = 275; | ||
@@ -18,29 +22,42 @@ this.maxReverseSpeed = - 275; | ||
this.frontDecceleration = 600; | ||
this.angularSpeed = 2.5; // rig | ||
this.angularSpeed = 2.5; | ||
// rig | ||
this.root = new THREE.Object3D(); | ||
this.meshBody = null; | ||
this.meshWeapon = null; | ||
this.controls = null; // skins | ||
this.controls = null; | ||
// skins | ||
this.skinsBody = []; | ||
this.skinsWeapon = []; | ||
this.weapons = []; | ||
this.currentSkin = undefined; // | ||
this.currentSkin = undefined; | ||
this.onLoadComplete = function () {}; // internals | ||
// | ||
this.onLoadComplete = function () {}; | ||
// internals | ||
this.meshes = []; | ||
this.animations = {}; | ||
this.loadCounter = 0; // internal movement control variables | ||
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.crouchSpeed = this.maxSpeed * 0.5; | ||
// internal animation parameters | ||
this.activeAnimation = null; | ||
this.oldAnimation = null; // API | ||
this.oldAnimation = null; | ||
// API | ||
} | ||
@@ -58,3 +75,2 @@ | ||
} | ||
setVisible( enable ) { | ||
@@ -70,3 +86,2 @@ | ||
} | ||
shareParts( original ) { | ||
@@ -78,6 +93,7 @@ | ||
this.skinsBody = original.skinsBody; | ||
this.skinsWeapon = original.skinsWeapon; // BODY | ||
this.skinsWeapon = original.skinsWeapon; | ||
// BODY | ||
const mesh = this._createPart( original.meshBody.geometry, this.skinsBody[ 0 ] ); | ||
mesh.scale.set( this.scale, this.scale, this.scale ); | ||
@@ -87,8 +103,9 @@ this.root.position.y = original.root.position.y; | ||
this.meshBody = mesh; | ||
this.meshes.push( mesh ); // WEAPONS | ||
this.meshes.push( mesh ); | ||
// WEAPONS | ||
for ( let i = 0; i < original.weapons.length; i ++ ) { | ||
const meshWeapon = this._createPart( original.weapons[ i ].geometry, this.skinsWeapon[ i ] ); | ||
meshWeapon.scale.set( this.scale, this.scale, this.scale ); | ||
@@ -105,7 +122,5 @@ meshWeapon.visible = false; | ||
} | ||
loadParts( config ) { | ||
const scope = this; | ||
function loadTextures( baseUrl, textureUrls ) { | ||
@@ -115,3 +130,2 @@ | ||
const textures = []; | ||
for ( let i = 0; i < textureUrls.length; i ++ ) { | ||
@@ -142,9 +156,11 @@ | ||
const weaponsTextures = []; | ||
for ( let i = 0; i < config.weapons.length; i ++ ) weaponsTextures[ i ] = config.weapons[ i ][ 1 ]; | ||
for ( let i = 0; i < config.weapons.length; i ++ ) weaponsTextures[ i ] = config.weapons[ i ][ 1 ]; // SKINS | ||
// SKINS | ||
this.skinsBody = loadTextures( config.baseUrl + 'skins/', config.skins ); | ||
this.skinsWeapon = loadTextures( config.baseUrl + 'skins/', weaponsTextures ); // BODY | ||
this.skinsWeapon = loadTextures( config.baseUrl + 'skins/', weaponsTextures ); | ||
// BODY | ||
const loader = new THREE.MD2Loader(); | ||
@@ -156,5 +172,3 @@ loader.load( config.baseUrl + config.body, function ( geo ) { | ||
scope.root.position.y = - scope.scale * boundingBox.min.y; | ||
const mesh = scope._createPart( geo, scope.skinsBody[ 0 ] ); | ||
mesh.scale.set( scope.scale, scope.scale, scope.scale ); | ||
@@ -166,4 +180,6 @@ scope.root.add( mesh ); | ||
} ); // WEAPONS | ||
} ); | ||
// WEAPONS | ||
const generateCallback = function ( index, name ) { | ||
@@ -174,3 +190,2 @@ | ||
const mesh = scope._createPart( geo, scope.skinsWeapon[ index ] ); | ||
mesh.scale.set( scope.scale, scope.scale, scope.scale ); | ||
@@ -196,3 +211,2 @@ mesh.visible = false; | ||
} | ||
setPlaybackRate( rate ) { | ||
@@ -204,3 +218,2 @@ | ||
} | ||
setWireframe( wireframeEnabled ) { | ||
@@ -221,3 +234,2 @@ | ||
} | ||
setSkin( index ) { | ||
@@ -233,9 +245,6 @@ | ||
} | ||
setWeapon( index ) { | ||
for ( let i = 0; i < this.weapons.length; i ++ ) this.weapons[ i ].visible = false; | ||
const activeWeapon = this.weapons[ index ]; | ||
if ( activeWeapon ) { | ||
@@ -245,3 +254,2 @@ | ||
this.meshWeapon = activeWeapon; | ||
if ( this.activeAnimation ) { | ||
@@ -257,7 +265,5 @@ | ||
} | ||
setAnimation( animationName ) { | ||
if ( animationName === this.activeAnimation || ! animationName ) return; | ||
if ( this.meshBody ) { | ||
@@ -281,7 +287,5 @@ | ||
} | ||
update( delta ) { | ||
if ( this.controls ) this.updateMovementModel( delta ); | ||
if ( this.animations ) { | ||
@@ -295,7 +299,5 @@ | ||
} | ||
updateAnimations( delta ) { | ||
let mix = 1; | ||
if ( this.blendCounter > 0 ) { | ||
@@ -325,3 +327,2 @@ | ||
} | ||
updateBehaviors() { | ||
@@ -331,4 +332,6 @@ | ||
const animations = this.animations; | ||
let moveAnimation, idleAnimation; // crouch vs stand | ||
let moveAnimation, idleAnimation; | ||
// crouch vs stand | ||
if ( controls.crouch ) { | ||
@@ -344,4 +347,5 @@ | ||
} // actions | ||
} | ||
// actions | ||
@@ -369,4 +373,5 @@ if ( controls.jump ) { | ||
} // set animations | ||
} | ||
// set animations | ||
@@ -391,4 +396,5 @@ if ( controls.moveForward || controls.moveBackward || controls.moveLeft || controls.moveRight ) { | ||
} // set animation direction | ||
} | ||
// set animation direction | ||
@@ -432,3 +438,2 @@ if ( controls.moveForward ) { | ||
} | ||
updateMovementModel( delta ) { | ||
@@ -442,12 +447,15 @@ | ||
const controls = this.controls; // speed based on controls | ||
const 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.MathUtils.clamp( this.speed + delta * this.frontAcceleration, this.maxReverseSpeed, this.maxSpeed ); | ||
if ( controls.moveBackward ) this.speed = THREE.MathUtils.clamp( this.speed - delta * this.backAcceleration, this.maxReverseSpeed, this.maxSpeed ); // orientation based on controls | ||
if ( controls.moveBackward ) this.speed = THREE.MathUtils.clamp( this.speed - delta * this.backAcceleration, this.maxReverseSpeed, this.maxSpeed ); | ||
// orientation based on controls | ||
// (don't just stand while turning) | ||
const dir = 1; | ||
if ( controls.moveLeft ) { | ||
@@ -465,4 +473,5 @@ | ||
} // speed decay | ||
} | ||
// speed decay | ||
@@ -483,13 +492,17 @@ if ( ! ( controls.moveForward || controls.moveBackward ) ) { | ||
} // displacement | ||
} | ||
// displacement | ||
const forwardDelta = this.speed * delta; | ||
this.root.position.x += Math.sin( this.bodyOrientation ) * forwardDelta; | ||
this.root.position.z += Math.cos( this.bodyOrientation ) * forwardDelta; // steering | ||
this.root.position.z += Math.cos( this.bodyOrientation ) * forwardDelta; | ||
// steering | ||
this.root.rotation.y = this.bodyOrientation; | ||
} // internal | ||
} | ||
// internal | ||
@@ -506,10 +519,16 @@ _createPart( geometry, skinMap ) { | ||
map: skinMap | ||
} ); // | ||
} ); | ||
// | ||
const mesh = new THREE.MorphBlendMesh( geometry, materialTexture ); | ||
mesh.rotation.y = - Math.PI / 2; // | ||
mesh.rotation.y = - Math.PI / 2; | ||
// | ||
mesh.materialTexture = materialTexture; | ||
mesh.materialWireframe = materialWireframe; // | ||
mesh.materialWireframe = materialWireframe; | ||
// | ||
mesh.autoCreateAnimations( this.animationFPS ); | ||
@@ -516,0 +535,0 @@ return mesh; |
@@ -13,3 +13,2 @@ ( function () { | ||
} | ||
setDirectionForward() { | ||
@@ -20,3 +19,2 @@ | ||
} | ||
setDirectionBackward() { | ||
@@ -27,3 +25,2 @@ | ||
} | ||
playAnimation( label, fps ) { | ||
@@ -39,3 +36,2 @@ | ||
const clip = THREE.AnimationClip.findByName( this, label ); | ||
if ( clip ) { | ||
@@ -54,3 +50,2 @@ | ||
} | ||
updateAnimation( delta ) { | ||
@@ -61,3 +56,2 @@ | ||
} | ||
copy( source, recursive ) { | ||
@@ -64,0 +58,0 @@ |
@@ -9,3 +9,5 @@ ( function () { | ||
this.animationsMap = {}; | ||
this.animationsList = []; // prepare default animation | ||
this.animationsList = []; | ||
// prepare default animation | ||
// (all frames played together in 1 second) | ||
@@ -22,3 +24,2 @@ | ||
} | ||
createAnimation( name, start, end, fps ) { | ||
@@ -45,3 +46,2 @@ | ||
} | ||
autoCreateAnimations( fps ) { | ||
@@ -53,7 +53,5 @@ | ||
let i = 0; | ||
for ( const key in this.morphTargetDictionary ) { | ||
const chunks = key.match( pattern ); | ||
if ( chunks && chunks.length > 1 ) { | ||
@@ -87,7 +85,5 @@ | ||
} | ||
setAnimationDirectionForward( name ) { | ||
const animation = this.animationsMap[ name ]; | ||
if ( animation ) { | ||
@@ -101,7 +97,5 @@ | ||
} | ||
setAnimationDirectionBackward( name ) { | ||
const animation = this.animationsMap[ name ]; | ||
if ( animation ) { | ||
@@ -115,7 +109,5 @@ | ||
} | ||
setAnimationFPS( name, fps ) { | ||
const animation = this.animationsMap[ name ]; | ||
if ( animation ) { | ||
@@ -129,7 +121,5 @@ | ||
} | ||
setAnimationDuration( name, duration ) { | ||
const animation = this.animationsMap[ name ]; | ||
if ( animation ) { | ||
@@ -143,7 +133,5 @@ | ||
} | ||
setAnimationWeight( name, weight ) { | ||
const animation = this.animationsMap[ name ]; | ||
if ( animation ) { | ||
@@ -156,7 +144,5 @@ | ||
} | ||
setAnimationTime( name, time ) { | ||
const animation = this.animationsMap[ name ]; | ||
if ( animation ) { | ||
@@ -169,3 +155,2 @@ | ||
} | ||
getAnimationTime( name ) { | ||
@@ -175,3 +160,2 @@ | ||
const animation = this.animationsMap[ name ]; | ||
if ( animation ) { | ||
@@ -186,3 +170,2 @@ | ||
} | ||
getAnimationDuration( name ) { | ||
@@ -192,3 +175,2 @@ | ||
const animation = this.animationsMap[ name ]; | ||
if ( animation ) { | ||
@@ -203,7 +185,5 @@ | ||
} | ||
playAnimation( name ) { | ||
const animation = this.animationsMap[ name ]; | ||
if ( animation ) { | ||
@@ -221,7 +201,5 @@ | ||
} | ||
stopAnimation( name ) { | ||
const animation = this.animationsMap[ name ]; | ||
if ( animation ) { | ||
@@ -234,3 +212,2 @@ | ||
} | ||
update( delta ) { | ||
@@ -244,3 +221,2 @@ | ||
animation.time += animation.direction * delta; | ||
if ( animation.mirroredLoop ) { | ||
@@ -251,3 +227,2 @@ | ||
animation.direction *= - 1; | ||
if ( animation.time > animation.duration ) { | ||
@@ -278,3 +253,2 @@ | ||
const weight = animation.weight; | ||
if ( keyframe !== animation.currentFrame ) { | ||
@@ -292,3 +266,2 @@ | ||
if ( animation.directionBackwards ) mix = 1 - mix; | ||
if ( animation.currentFrame !== animation.lastFrame ) { | ||
@@ -295,0 +268,0 @@ |
@@ -19,3 +19,2 @@ ( function () { | ||
*/ | ||
class ProgressiveLightMap { | ||
@@ -34,4 +33,5 @@ | ||
this.firstUpdate = true; | ||
this.warned = false; // Create the Progressive LightMap Texture | ||
this.warned = false; | ||
// Create the Progressive LightMap Texture | ||
const format = /(Android|iPad|iPhone|iPod)/g.test( navigator.userAgent ) ? THREE.HalfFloatType : THREE.FloatType; | ||
@@ -43,17 +43,19 @@ this.progressiveLightMap1 = new THREE.WebGLRenderTarget( this.res, this.res, { | ||
type: format | ||
} ); // Inject some spicy new logic into a standard phong material | ||
} ); | ||
// Inject some spicy new logic into a standard phong material | ||
this.uvMat = new THREE.MeshPhongMaterial(); | ||
this.uvMat.uniforms = {}; | ||
this.uvMat.onBeforeCompile = shader => { | ||
// Vertex Shader: Set Vertex Positions to the Unwrapped UV Positions | ||
shader.vertexShader = '#define USE_LIGHTMAP\n' + shader.vertexShader.slice( 0, - 1 ) + ' gl_Position = vec4((uv2 - 0.5) * 2.0, 1.0, 1.0); }'; // Fragment Shader: Set Pixels to average in the Previous frame's Shadows | ||
shader.vertexShader = '#define USE_LIGHTMAP\n' + shader.vertexShader.slice( 0, - 1 ) + ' gl_Position = vec4((uv2 - 0.5) * 2.0, 1.0, 1.0); }'; | ||
// Fragment Shader: Set Pixels to average in the Previous frame's Shadows | ||
const bodyStart = shader.fragmentShader.indexOf( 'void main() {' ); | ||
shader.fragmentShader = 'varying vec2 vUv2;\n' + shader.fragmentShader.slice( 0, bodyStart ) + ' uniform sampler2D previousShadowMap;\n uniform float averagingWindow;\n' + shader.fragmentShader.slice( bodyStart - 1, - 1 ) + `\nvec3 texelOld = texture2D(previousShadowMap, vUv2).rgb; | ||
gl_FragColor.rgb = mix(texelOld, gl_FragColor.rgb, 1.0/averagingWindow); | ||
}`; // Set the Previous Frame's Texture Buffer and Averaging Window | ||
}`; | ||
// Set the Previous Frame's Texture Buffer and Averaging Window | ||
shader.uniforms.previousShadowMap = { | ||
@@ -65,4 +67,5 @@ value: this.progressiveLightMap1.texture | ||
}; | ||
this.uvMat.uniforms = shader.uniforms; // Set the new Shader to this | ||
this.uvMat.uniforms = shader.uniforms; | ||
// Set the new Shader to this | ||
this.uvMat.userData.shader = shader; | ||
@@ -74,2 +77,3 @@ this.compiled = true; | ||
} | ||
/** | ||
@@ -79,4 +83,2 @@ * Sets these objects' materials' lightmaps and modifies their uv2's. | ||
*/ | ||
addObjectsToLightMap( objects ) { | ||
@@ -87,7 +89,7 @@ | ||
const padding = 3 / this.res; | ||
for ( let ob = 0; ob < objects.length; ob ++ ) { | ||
const object = objects[ ob ]; // If this object is a light, simply add it to the internal scene | ||
const object = objects[ ob ]; | ||
// If this object is a light, simply add it to the internal scene | ||
if ( object.isLight ) { | ||
@@ -111,5 +113,5 @@ | ||
} // Apply the lightmap to the object | ||
} | ||
// Apply the lightmap to the object | ||
object.material.lightMap = this.progressiveLightMap2.texture; | ||
@@ -119,5 +121,6 @@ object.material.dithering = true; | ||
object.receiveShadow = true; | ||
object.renderOrder = 1000 + ob; // Prepare UV boxes for potpack | ||
object.renderOrder = 1000 + ob; | ||
// Prepare UV boxes for potpack | ||
// TODO: Size these by object surface area | ||
this.uv_boxes.push( { | ||
@@ -134,5 +137,5 @@ w: 1 + padding * 2, | ||
} // Pack the objects' lightmap UVs into the same global space | ||
} | ||
// Pack the objects' lightmap UVs into the same global space | ||
const dimensions = potpack( this.uv_boxes ); | ||
@@ -142,3 +145,2 @@ this.uv_boxes.forEach( box => { | ||
const uv2 = objects[ box.index ].geometry.getAttribute( 'uv' ).clone(); | ||
for ( let i = 0; i < uv2.array.length; i += uv2.itemSize ) { | ||
@@ -157,2 +159,3 @@ | ||
} | ||
/** | ||
@@ -164,4 +167,2 @@ * This function renders each mesh one at a time into their respective surface maps | ||
*/ | ||
update( camera, blendWindow = 100, blurEdges = true ) { | ||
@@ -173,9 +174,11 @@ | ||
} // Store the original Render Target | ||
} | ||
// Store the original Render Target | ||
const oldTarget = this.renderer.getRenderTarget(); | ||
const oldTarget = this.renderer.getRenderTarget(); // The blurring plane applies blur to the seams of the lightmap | ||
// The blurring plane applies blur to the seams of the lightmap | ||
this.blurringPlane.visible = blurEdges; | ||
this.blurringPlane.visible = blurEdges; // Steal the Object3D from the real world to our special dimension | ||
// Steal the Object3D from the real world to our special dimension | ||
for ( let l = 0; l < this.lightMapContainers.length; l ++ ) { | ||
@@ -186,15 +189,14 @@ | ||
} // Render once normally to initialize everything | ||
} | ||
// Render once normally to initialize everything | ||
if ( this.firstUpdate ) { | ||
this.renderer.setRenderTarget( this.tinyTarget ); // Tiny for Speed | ||
this.renderer.render( this.scene, camera ); | ||
this.firstUpdate = false; | ||
} // Set each object's material to the UV Unwrapped Surface Mapping Version | ||
} | ||
// Set each object's material to the UV Unwrapped Surface Mapping Version | ||
for ( let l = 0; l < this.lightMapContainers.length; l ++ ) { | ||
@@ -209,8 +211,9 @@ | ||
} // Ping-pong two surface buffers for reading/writing | ||
} | ||
// Ping-pong two surface buffers for reading/writing | ||
const activeMap = this.buffer1Active ? this.progressiveLightMap1 : this.progressiveLightMap2; | ||
const inactiveMap = this.buffer1Active ? this.progressiveLightMap2 : this.progressiveLightMap1; // Render the object's surface maps | ||
const inactiveMap = this.buffer1Active ? this.progressiveLightMap2 : this.progressiveLightMap1; | ||
// Render the object's surface maps | ||
this.renderer.setRenderTarget( activeMap ); | ||
@@ -224,4 +227,5 @@ this.uvMat.uniforms.previousShadowMap = { | ||
this.buffer1Active = ! this.buffer1Active; | ||
this.renderer.render( this.scene, camera ); // Restore the object's Real-time Material and add it back to the original world | ||
this.renderer.render( this.scene, camera ); | ||
// Restore the object's Real-time Material and add it back to the original world | ||
for ( let l = 0; l < this.lightMapContainers.length; l ++ ) { | ||
@@ -233,8 +237,9 @@ | ||
} // Restore the original Render Target | ||
} | ||
// Restore the original Render Target | ||
this.renderer.setRenderTarget( oldTarget ); | ||
} | ||
/** DEBUG | ||
@@ -245,4 +250,2 @@ * Draw the lightmap in the main scene. Call this after adding the objects to it. | ||
*/ | ||
showDebugLightmap( visible, position = undefined ) { | ||
@@ -285,2 +288,3 @@ | ||
} | ||
/** | ||
@@ -291,4 +295,2 @@ * INTERNAL Creates the Blurring Plane | ||
*/ | ||
_initializeBlurPlane( res, lightMap = null ) { | ||
@@ -308,8 +310,8 @@ | ||
}; | ||
blurMaterial.onBeforeCompile = shader => { | ||
// Vertex Shader: Set Vertex Positions to the Unwrapped UV Positions | ||
shader.vertexShader = '#define USE_UV\n' + shader.vertexShader.slice( 0, - 1 ) + ' gl_Position = vec4((uv - 0.5) * 2.0, 1.0, 1.0); }'; // Fragment Shader: Set Pixels to 9-tap box blur the current frame's Shadows | ||
shader.vertexShader = '#define USE_UV\n' + shader.vertexShader.slice( 0, - 1 ) + ' gl_Position = vec4((uv - 0.5) * 2.0, 1.0, 1.0); }'; | ||
// Fragment Shader: Set Pixels to 9-tap box blur the current frame's Shadows | ||
const bodyStart = shader.fragmentShader.indexOf( 'void main() {' ); | ||
@@ -325,4 +327,5 @@ shader.fragmentShader = '#define USE_UV\n' + shader.fragmentShader.slice( 0, bodyStart ) + ' uniform sampler2D previousShadowMap;\n uniform float pixelOffset;\n' + shader.fragmentShader.slice( bodyStart - 1, - 1 ) + ` gl_FragColor.rgb = ( | ||
texture2D(previousShadowMap, vUv + vec2(-pixelOffset, -pixelOffset)).rgb)/8.0; | ||
}`; // Set the LightMap Accumulation Buffer | ||
}`; | ||
// Set the LightMap Accumulation Buffer | ||
shader.uniforms.previousShadowMap = { | ||
@@ -334,4 +337,5 @@ value: lightMap.texture | ||
}; | ||
blurMaterial.uniforms = shader.uniforms; // Set the new Shader to this | ||
blurMaterial.uniforms = shader.uniforms; | ||
// Set the new Shader to this | ||
blurMaterial.userData.shader = shader; | ||
@@ -338,0 +342,0 @@ this.compiled = true; |
@@ -21,4 +21,6 @@ ( function () { | ||
const prevPoint = new THREE.Vector3(); | ||
prevPoint.copy( curve.getPointAt( 0 ) ); // shapes | ||
prevPoint.copy( curve.getPointAt( 0 ) ); | ||
// shapes | ||
const step = [ new THREE.Vector3( - 0.225, 0, 0 ), new THREE.Vector3( 0, - 0.050, 0 ), new THREE.Vector3( 0, - 0.175, 0 ), new THREE.Vector3( 0, - 0.050, 0 ), new THREE.Vector3( 0.225, 0, 0 ), new THREE.Vector3( 0, - 0.175, 0 ) ]; | ||
@@ -28,3 +30,2 @@ const PI2 = Math.PI * 2; | ||
const tube1 = []; | ||
for ( let i = 0; i < sides; i ++ ) { | ||
@@ -39,3 +40,2 @@ | ||
const tube2 = []; | ||
for ( let i = 0; i < sides; i ++ ) { | ||
@@ -50,7 +50,5 @@ | ||
const normal = new THREE.Vector3(); | ||
function drawShape( shape, color ) { | ||
normal.set( 0, 0, - 1 ).applyQuaternion( quaternion ); | ||
for ( let j = 0; j < shape.length; j ++ ) { | ||
@@ -68,3 +66,2 @@ | ||
normal.set( 0, 0, 1 ).applyQuaternion( quaternion ); | ||
for ( let j = shape.length - 1; j >= 0; j -- ) { | ||
@@ -91,3 +88,2 @@ | ||
const normal4 = new THREE.Vector3(); | ||
function extrudeShape( shape, offset, color ) { | ||
@@ -116,4 +112,6 @@ | ||
vertices.push( vector3.x, vector3.y, vector3.z ); | ||
vertices.push( vector4.x, vector4.y, vector4.z ); // | ||
vertices.push( vector4.x, vector4.y, vector4.z ); | ||
// | ||
normal1.copy( point1 ); | ||
@@ -149,3 +147,2 @@ normal1.applyQuaternion( quaternion ); | ||
const offset = new THREE.Vector3(); | ||
for ( let i = 1; i <= divisions; i ++ ) { | ||
@@ -160,3 +157,2 @@ | ||
quaternion.setFromAxisAngle( up, angle ); | ||
if ( i % 2 === 0 ) { | ||
@@ -174,4 +170,5 @@ | ||
} // console.log( vertices.length ); | ||
} | ||
// console.log( vertices.length ); | ||
@@ -185,3 +182,2 @@ this.setAttribute( 'position', new THREE.BufferAttribute( new Float32Array( vertices ), 3 ) ); | ||
} | ||
class RollerCoasterLiftersGeometry extends THREE.BufferGeometry { | ||
@@ -197,4 +193,6 @@ | ||
const point = new THREE.Vector3(); | ||
const tangent = new THREE.Vector3(); // shapes | ||
const tangent = new THREE.Vector3(); | ||
// shapes | ||
const tube1 = [ new THREE.Vector3( 0, 0.05, - 0.05 ), new THREE.Vector3( 0, 0.05, 0.05 ), new THREE.Vector3( 0, - 0.05, 0 ) ]; | ||
@@ -211,3 +209,2 @@ const tube2 = [ new THREE.Vector3( - 0.05, 0, 0.05 ), new THREE.Vector3( - 0.05, 0, - 0.05 ), new THREE.Vector3( 0.05, 0, 0 ) ]; | ||
const normal4 = new THREE.Vector3(); | ||
function extrudeShape( shape, fromPoint, toPoint ) { | ||
@@ -236,4 +233,6 @@ | ||
vertices.push( vector3.x, vector3.y, vector3.z ); | ||
vertices.push( vector4.x, vector4.y, vector4.z ); // | ||
vertices.push( vector4.x, vector4.y, vector4.z ); | ||
// | ||
normal1.copy( point1 ); | ||
@@ -264,3 +263,2 @@ normal1.applyQuaternion( quaternion ); | ||
const toPoint = new THREE.Vector3(); | ||
for ( let i = 1; i <= divisions; i ++ ) { | ||
@@ -271,4 +269,6 @@ | ||
const angle = Math.atan2( tangent.x, tangent.z ); | ||
quaternion.setFromAxisAngle( up, angle ); // | ||
quaternion.setFromAxisAngle( up, angle ); | ||
// | ||
if ( point.y > 10 ) { | ||
@@ -318,3 +318,2 @@ | ||
} | ||
class RollerCoasterShadowGeometry extends THREE.BufferGeometry { | ||
@@ -339,3 +338,2 @@ | ||
const vector4 = new THREE.Vector3(); | ||
for ( let i = 1; i <= divisions; i ++ ) { | ||
@@ -376,3 +374,2 @@ | ||
} | ||
class SkyGeometry extends THREE.BufferGeometry { | ||
@@ -384,3 +381,2 @@ | ||
const vertices = []; | ||
for ( let i = 0; i < 100; i ++ ) { | ||
@@ -406,3 +402,2 @@ | ||
} | ||
class TreesGeometry extends THREE.BufferGeometry { | ||
@@ -417,3 +412,2 @@ | ||
raycaster.ray.direction.set( 0, - 1, 0 ); | ||
for ( let i = 0; i < 2000; i ++ ) { | ||
@@ -437,3 +431,2 @@ | ||
const random = Math.random() * 0.1; | ||
for ( let j = 0; j < 6; j ++ ) { | ||
@@ -440,0 +433,0 @@ |
@@ -21,4 +21,6 @@ ( function () { | ||
const mesh = new THREE.Mesh( geometry, material ); | ||
mesh.frustumCulled = false; // | ||
mesh.frustumCulled = false; | ||
// | ||
function getPoints( size ) { | ||
@@ -30,3 +32,2 @@ | ||
const radius = 0.01 * size; | ||
for ( let i = 0; i < sides; i ++ ) { | ||
@@ -41,4 +42,5 @@ | ||
} // | ||
} | ||
// | ||
@@ -51,3 +53,2 @@ const vector1 = new THREE.Vector3(); | ||
let size = 1; | ||
function stroke( position1, position2, matrix1, matrix2 ) { | ||
@@ -58,8 +59,9 @@ | ||
const points = getPoints( size ); | ||
for ( let i = 0, il = points.length; i < il; i ++ ) { | ||
const vertex1 = points[ i ]; | ||
const vertex2 = points[ ( i + 1 ) % il ]; // positions | ||
const vertex2 = points[ ( i + 1 ) % il ]; | ||
// positions | ||
vector1.copy( vertex1 ).applyMatrix4( matrix2 ).add( position2 ); | ||
@@ -74,4 +76,6 @@ vector2.copy( vertex2 ).applyMatrix4( matrix2 ).add( position2 ); | ||
vector3.toArray( positions.array, ( count + 4 ) * 3 ); | ||
vector4.toArray( positions.array, ( count + 5 ) * 3 ); // normals | ||
vector4.toArray( positions.array, ( count + 5 ) * 3 ); | ||
// normals | ||
vector1.copy( vertex1 ).applyMatrix4( matrix2 ).normalize(); | ||
@@ -86,4 +90,6 @@ vector2.copy( vertex2 ).applyMatrix4( matrix2 ).normalize(); | ||
vector3.toArray( normals.array, ( count + 4 ) * 3 ); | ||
vector4.toArray( normals.array, ( count + 5 ) * 3 ); // colors | ||
vector4.toArray( normals.array, ( count + 5 ) * 3 ); | ||
// colors | ||
color.toArray( colors.array, ( count + 0 ) * 3 ); | ||
@@ -101,4 +107,5 @@ color.toArray( colors.array, ( count + 1 ) * 3 ); | ||
} // | ||
} | ||
// | ||
@@ -110,3 +117,2 @@ const up = new THREE.Vector3( 0, 1, 0 ); | ||
const matrix2 = new THREE.Matrix4(); | ||
function moveTo( position ) { | ||
@@ -135,7 +141,7 @@ | ||
} // | ||
} | ||
// | ||
let count = 0; | ||
function update() { | ||
@@ -142,0 +148,0 @@ |
@@ -15,3 +15,2 @@ ( function () { | ||
*/ | ||
class Volume { | ||
@@ -30,3 +29,2 @@ | ||
*/ | ||
this.yLength = Number( yLength ) || 1; | ||
@@ -36,3 +34,2 @@ /** | ||
*/ | ||
this.zLength = Number( zLength ) || 1; | ||
@@ -42,3 +39,2 @@ /** | ||
*/ | ||
this.axisOrder = [ 'x', 'y', 'z' ]; | ||
@@ -58,3 +54,2 @@ /** | ||
break; | ||
case 'Int8': | ||
@@ -66,3 +61,2 @@ case 'int8': | ||
break; | ||
case 'Int16': | ||
@@ -77,3 +71,2 @@ case 'int16': | ||
break; | ||
case 'Uint16': | ||
@@ -87,3 +80,2 @@ case 'uint16': | ||
break; | ||
case 'Int32': | ||
@@ -96,3 +88,2 @@ case 'int32': | ||
break; | ||
case 'Uint32': | ||
@@ -105,3 +96,2 @@ case 'uint32': | ||
break; | ||
case 'longlong': | ||
@@ -121,3 +111,2 @@ case 'long long': | ||
break; | ||
case 'Float32': | ||
@@ -128,3 +117,2 @@ case 'float32': | ||
break; | ||
case 'Float64': | ||
@@ -135,3 +123,2 @@ case 'float64': | ||
break; | ||
default: | ||
@@ -149,7 +136,6 @@ this.data = new Uint8Array( arrayBuffer ); | ||
} | ||
/** | ||
* @member {Array} spacing Spacing to apply to the volume from IJK to RAS coordinate system | ||
*/ | ||
this.spacing = [ 1, 1, 1 ]; | ||
@@ -159,3 +145,2 @@ /** | ||
*/ | ||
this.offset = [ 0, 0, 0 ]; | ||
@@ -165,3 +150,2 @@ /** | ||
*/ | ||
this.matrix = new THREE.Matrix3(); | ||
@@ -172,3 +156,2 @@ this.matrix.identity(); | ||
*/ | ||
/** | ||
@@ -178,3 +161,2 @@ * @member {number} lowerThreshold The voxels with values under this threshold won't appear in the slices. | ||
*/ | ||
let lowerThreshold = - Infinity; | ||
@@ -202,3 +184,2 @@ Object.defineProperty( this, 'lowerThreshold', { | ||
*/ | ||
let upperThreshold = Infinity; | ||
@@ -222,7 +203,8 @@ Object.defineProperty( this, 'upperThreshold', { | ||
} ); | ||
/** | ||
* @member {Array} sliceList The list of all the slices associated to this volume | ||
*/ | ||
this.sliceList = []; | ||
this.sliceList = []; | ||
/** | ||
@@ -233,2 +215,3 @@ * @member {Array} RASDimensions This array holds the dimensions of the volume in the RAS space | ||
} | ||
/** | ||
@@ -242,4 +225,2 @@ * @member {Function} getData Shortcut for data[access(i,j,k)] | ||
*/ | ||
getData( i, j, k ) { | ||
@@ -250,2 +231,3 @@ | ||
} | ||
/** | ||
@@ -259,4 +241,2 @@ * @member {Function} access compute the index in the data array corresponding to the given coordinates in IJK system | ||
*/ | ||
access( i, j, k ) { | ||
@@ -267,2 +247,3 @@ | ||
} | ||
/** | ||
@@ -274,4 +255,2 @@ * @member {Function} reverseAccess Retrieve the IJK coordinates of the voxel corresponding of the given index in the data | ||
*/ | ||
reverseAccess( index ) { | ||
@@ -285,2 +264,3 @@ | ||
} | ||
/** | ||
@@ -296,4 +276,2 @@ * @member {Function} map Apply a function to all the voxels, be careful, the value will be replaced | ||
*/ | ||
map( functionToMap, context ) { | ||
@@ -303,3 +281,2 @@ | ||
context = context || this; | ||
for ( let i = 0; i < length; i ++ ) { | ||
@@ -314,2 +291,3 @@ | ||
} | ||
/** | ||
@@ -322,4 +300,2 @@ * @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. | ||
*/ | ||
extractPerpendicularPlane( axis, RASIndex ) { | ||
@@ -334,3 +310,2 @@ | ||
const dimensions = new THREE.Vector3( this.xLength, this.yLength, this.zLength ); | ||
switch ( axis ) { | ||
@@ -349,3 +324,2 @@ | ||
break; | ||
case 'y': | ||
@@ -362,3 +336,2 @@ axisInIJK.set( 0, 1, 0 ); | ||
break; | ||
case 'z': | ||
@@ -404,3 +377,2 @@ default: | ||
} ); | ||
function sliceAccess( i, j ) { | ||
@@ -410,4 +382,6 @@ | ||
const sj = jDirection === axisInIJK ? IJKIndex : jDirection.arglet === 'i' ? i : j; | ||
const sk = kDirection === axisInIJK ? IJKIndex : kDirection.arglet === 'i' ? i : j; // invert indices if necessary | ||
const sk = kDirection === axisInIJK ? IJKIndex : kDirection.arglet === 'i' ? i : j; | ||
// invert indices if necessary | ||
const accessI = iDirection.dot( base[ 0 ] ) > 0 ? si : volume.xLength - 1 - si; | ||
@@ -430,2 +404,3 @@ const accessJ = jDirection.dot( base[ 1 ] ) > 0 ? sj : volume.yLength - 1 - sj; | ||
} | ||
/** | ||
@@ -439,4 +414,2 @@ * @member {Function} extractSlice Returns a slice corresponding to the given axis and index | ||
*/ | ||
extractSlice( axis, index ) { | ||
@@ -449,2 +422,3 @@ | ||
} | ||
/** | ||
@@ -456,4 +430,2 @@ * @member {Function} repaintAllSlices Call repaint on all the slices extracted from this volume | ||
*/ | ||
repaintAllSlices() { | ||
@@ -469,2 +441,3 @@ | ||
} | ||
/** | ||
@@ -475,12 +448,10 @@ * @member {Function} computeMinMax Compute the minimum and the maximum of the data in the volume | ||
*/ | ||
computeMinMax() { | ||
let min = Infinity; | ||
let max = - Infinity; // buffer the length | ||
let max = - Infinity; | ||
// buffer the length | ||
const datasize = this.data.length; | ||
let i = 0; | ||
for ( i = 0; i < datasize; i ++ ) { | ||
@@ -487,0 +458,0 @@ |
@@ -11,3 +11,2 @@ ( function () { | ||
*/ | ||
class VolumeSlice { | ||
@@ -21,3 +20,2 @@ | ||
*/ | ||
this.volume = volume; | ||
@@ -27,3 +25,2 @@ /** | ||
*/ | ||
index = index || 0; | ||
@@ -47,12 +44,10 @@ Object.defineProperty( this, 'index', { | ||
*/ | ||
this.axis = axis || 'z'; | ||
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' ); | ||
@@ -62,7 +57,5 @@ /** | ||
*/ | ||
/** | ||
* @member {CanvasRenderingContext2D} ctxBuffer Context of the canvas buffer | ||
*/ | ||
this.canvasBuffer = document.createElement( 'canvas' ); | ||
@@ -81,3 +74,2 @@ this.updateGeometry(); | ||
*/ | ||
this.mesh = new THREE.Mesh( this.geometry, material ); | ||
@@ -88,5 +80,5 @@ this.mesh.matrixAutoUpdate = false; | ||
*/ | ||
this.geometryNeedsUpdate = true; | ||
this.repaint(); | ||
/** | ||
@@ -109,2 +101,3 @@ * @member {Number} iLength Width of slice in the original coordinate system, corresponds to the width of the buffer canvas | ||
} | ||
/** | ||
@@ -114,4 +107,2 @@ * @member {Function} repaint Refresh the texture and the geometry if geometryNeedsUpdate is set to true | ||
*/ | ||
repaint() { | ||
@@ -130,4 +121,5 @@ | ||
canvas = this.canvasBuffer, | ||
ctx = this.ctxBuffer; // get the imageData and pixel array from the canvas | ||
ctx = this.ctxBuffer; | ||
// get the imageData and pixel array from the canvas | ||
const imgData = ctx.getImageData( 0, 0, iLength, jLength ); | ||
@@ -139,6 +131,6 @@ const data = imgData.data; | ||
const windowLow = volume.windowLow; | ||
const windowHigh = volume.windowHigh; // manipulate some pixel elements | ||
const windowHigh = volume.windowHigh; | ||
// manipulate some pixel elements | ||
let pixelCount = 0; | ||
if ( volume.dataType === 'label' ) { | ||
@@ -171,6 +163,6 @@ | ||
let value = volumeData[ sliceAccess( i, j ) ]; | ||
let alpha = 0xff; //apply threshold | ||
alpha = upperThreshold >= value ? lowerThreshold <= value ? alpha : 0 : 0; //apply window level | ||
let alpha = 0xff; | ||
//apply threshold | ||
alpha = upperThreshold >= value ? lowerThreshold <= value ? alpha : 0 : 0; | ||
//apply window level | ||
value = Math.floor( 255 * ( value - windowLow ) / ( windowHigh - windowLow ) ); | ||
@@ -195,2 +187,3 @@ value = value > 255 ? 255 : value < 0 ? 0 : value | 0; | ||
} | ||
/** | ||
@@ -201,4 +194,2 @@ * @member {Function} Refresh the geometry according to axis and index | ||
*/ | ||
updateGeometry() { | ||
@@ -220,7 +211,6 @@ | ||
this.geometry = new THREE.PlaneGeometry( extracted.planeWidth, extracted.planeHeight ); | ||
if ( this.mesh ) { | ||
this.mesh.geometry = this.geometry; //reset mesh matrix | ||
this.mesh.geometry = this.geometry; | ||
//reset mesh matrix | ||
this.mesh.matrix.identity(); | ||
@@ -227,0 +217,0 @@ this.mesh.applyMatrix4( this.matrix ); |
@@ -7,2 +7,3 @@ ( function () { | ||
const TEXTURE_HEIGHT = 4; | ||
/** | ||
@@ -13,3 +14,2 @@ * Make a new THREE.DataTexture to store the descriptions of the curves. | ||
*/ | ||
function initSplineTexture( numberOfCurves = 1 ) { | ||
@@ -26,2 +26,3 @@ | ||
} | ||
/** | ||
@@ -34,3 +35,2 @@ * Write the curve description to the data texture | ||
*/ | ||
function updateSplineTexture( texture, splineCurve, offset = 0 ) { | ||
@@ -43,3 +43,2 @@ | ||
const frenetFrames = splineCurve.computeFrenetFrames( numberOfPoints, true ); | ||
for ( let i = 0; i < numberOfPoints; i ++ ) { | ||
@@ -71,3 +70,2 @@ | ||
const i = CHANNELS * TEXTURE_WIDTH * o; // Row Offset | ||
data[ index * CHANNELS + i + 0 ] = x; | ||
@@ -79,2 +77,3 @@ data[ index * CHANNELS + i + 1 ] = y; | ||
} | ||
/** | ||
@@ -85,4 +84,2 @@ * Create a new set of uniforms for describing the curve modifier | ||
*/ | ||
function getUniforms( splineTexture ) { | ||
@@ -125,3 +122,2 @@ | ||
material.__ok = true; | ||
material.onBeforeCompile = shader => { | ||
@@ -144,6 +140,13 @@ | ||
${shader.vertexShader} | ||
` // chunk import moved in front of modified shader below | ||
.replace( '#include <beginnormal_vertex>', '' ) // vec3 transformedNormal declaration overriden below | ||
.replace( '#include <defaultnormal_vertex>', '' ) // vec3 transformed declaration overriden below | ||
.replace( '#include <begin_vertex>', '' ) // shader override | ||
` | ||
// chunk import moved in front of modified shader below | ||
.replace( '#include <beginnormal_vertex>', '' ) | ||
// vec3 transformedNormal declaration overriden below | ||
.replace( '#include <defaultnormal_vertex>', '' ) | ||
// vec3 transformed declaration overriden below | ||
.replace( '#include <begin_vertex>', '' ) | ||
// shader override | ||
.replace( /void\s*main\s*\(\)\s*\{/, ` | ||
@@ -193,6 +196,6 @@ void main() { | ||
} | ||
/** | ||
* A helper class for making meshes bend aroudn curves | ||
*/ | ||
class Flow { | ||
@@ -226,3 +229,2 @@ | ||
} | ||
updateCurve( index, curve ) { | ||
@@ -238,3 +240,2 @@ | ||
} | ||
moveAlongCurve( amount ) { | ||
@@ -248,6 +249,6 @@ | ||
const matrix = new THREE.Matrix4(); | ||
/** | ||
* A helper class for creating instanced versions of flow, where the instances are placed on the curve. | ||
*/ | ||
class InstancedFlow extends Flow { | ||
@@ -271,2 +272,3 @@ | ||
} | ||
/** | ||
@@ -278,4 +280,2 @@ * The extra information about which curve and curve position is stored in the translation components of the matrix for the instanced objects | ||
*/ | ||
writeChanges( index ) { | ||
@@ -288,2 +288,3 @@ | ||
} | ||
/** | ||
@@ -295,4 +296,2 @@ * Move an individual element along the curve by a specific amount | ||
*/ | ||
moveIndividualAlongCurve( index, offset ) { | ||
@@ -304,2 +303,3 @@ | ||
} | ||
/** | ||
@@ -311,4 +311,2 @@ * Select which curve to use for an element | ||
*/ | ||
setCurve( index, curveNo ) { | ||
@@ -315,0 +313,0 @@ |
( function () { | ||
const _A = new THREE.Vector3(); | ||
const _B = new THREE.Vector3(); | ||
const _C = new THREE.Vector3(); | ||
class EdgeSplitModifier { | ||
@@ -16,23 +13,13 @@ | ||
normals = new Float32Array( indexes.length * 3 ); | ||
for ( let i = 0; i < indexes.length; i += 3 ) { | ||
let index = indexes[ i ]; | ||
_A.set( positions[ 3 * index ], positions[ 3 * index + 1 ], positions[ 3 * index + 2 ] ); | ||
index = indexes[ i + 1 ]; | ||
_B.set( positions[ 3 * index ], positions[ 3 * index + 1 ], positions[ 3 * index + 2 ] ); | ||
index = indexes[ i + 2 ]; | ||
_C.set( positions[ 3 * index ], positions[ 3 * index + 1 ], positions[ 3 * index + 2 ] ); | ||
_C.sub( _B ); | ||
_A.sub( _B ); | ||
const normal = _C.cross( _A ).normalize(); | ||
for ( let j = 0; j < 3; j ++ ) { | ||
@@ -53,7 +40,5 @@ | ||
pointToIndexMap = Array( positions.length / 3 ); | ||
for ( let i = 0; i < indexes.length; i ++ ) { | ||
const index = indexes[ i ]; | ||
if ( pointToIndexMap[ index ] == null ) { | ||
@@ -74,3 +59,2 @@ | ||
_A.set( normals[ 3 * firstIndex ], normals[ 3 * firstIndex + 1 ], normals[ 3 * firstIndex + 2 ] ).normalize(); | ||
const result = { | ||
@@ -80,3 +64,2 @@ splitGroup: [], | ||
}; | ||
for ( const j of indexes ) { | ||
@@ -87,3 +70,2 @@ | ||
_B.set( normals[ 3 * j ], normals[ 3 * j + 1 ], normals[ 3 * j + 2 ] ).normalize(); | ||
if ( _B.dot( _A ) < cutOff ) { | ||
@@ -111,3 +93,2 @@ | ||
const groupResults = []; | ||
for ( const index of indexes ) { | ||
@@ -120,3 +101,2 @@ | ||
let result = groupResults[ 0 ]; | ||
for ( const groupResult of groupResults ) { | ||
@@ -151,3 +131,2 @@ | ||
let oldNormals = null; | ||
if ( geometry.attributes.normal ) { | ||
@@ -157,3 +136,2 @@ | ||
geometry = geometry.clone(); | ||
if ( tryKeepNormals === true && geometry.index !== null ) { | ||
@@ -182,3 +160,2 @@ | ||
const splitIndexes = []; | ||
for ( const vertexIndexes of pointToIndexMap ) { | ||
@@ -191,3 +168,2 @@ | ||
const newAttributes = {}; | ||
for ( const name of Object.keys( geometry.attributes ) ) { | ||
@@ -204,3 +180,2 @@ | ||
newIndexes.set( indexes ); | ||
for ( let i = 0; i < splitIndexes.length; i ++ ) { | ||
@@ -210,3 +185,2 @@ | ||
const index = indexes[ split.original ]; | ||
for ( const attribute of Object.values( newAttributes ) ) { | ||
@@ -232,3 +206,2 @@ | ||
geometry.setIndex( new THREE.BufferAttribute( newIndexes, 1 ) ); | ||
for ( const name of Object.keys( newAttributes ) ) { | ||
@@ -243,9 +216,6 @@ | ||
geometry.computeVertexNormals(); | ||
if ( oldNormals !== null ) { | ||
const changedNormals = new Array( oldNormals.length / 3 ).fill( false ); | ||
for ( const splitData of splitIndexes ) changedNormals[ splitData.original ] = true; | ||
for ( let i = 0; i < changedNormals.length; i ++ ) { | ||
@@ -252,0 +222,0 @@ |
@@ -13,3 +13,2 @@ ( function () { | ||
_ab = new THREE.Vector3(); | ||
class SimplifyModifier { | ||
@@ -20,4 +19,6 @@ | ||
geometry = geometry.clone(); | ||
const attributes = geometry.attributes; // this modifier can only process indexed and non-indexed geomtries with a position attribute | ||
const attributes = geometry.attributes; | ||
// this modifier can only process indexed and non-indexed geomtries with a position attribute | ||
for ( const name in attributes ) { | ||
@@ -29,3 +30,5 @@ | ||
geometry = THREE.BufferGeometryUtils.mergeVertices( geometry ); // | ||
geometry = THREE.BufferGeometryUtils.mergeVertices( geometry ); | ||
// | ||
// put data of original geometry in different data structures | ||
@@ -35,6 +38,7 @@ // | ||
const vertices = []; | ||
const faces = []; // add vertices | ||
const faces = []; | ||
// add vertices | ||
const positionAttribute = geometry.getAttribute( 'position' ); | ||
for ( let i = 0; i < positionAttribute.count; i ++ ) { | ||
@@ -46,7 +50,7 @@ | ||
} // add faces | ||
} | ||
// add faces | ||
let index = geometry.getIndex(); | ||
if ( index !== null ) { | ||
@@ -76,4 +80,5 @@ | ||
} // compute all edge collapse costs | ||
} | ||
// compute all edge collapse costs | ||
@@ -88,7 +93,5 @@ for ( let i = 0, il = vertices.length; i < il; i ++ ) { | ||
let z = count; | ||
while ( z -- ) { | ||
nextVertex = minimumCostEdge( vertices ); | ||
if ( ! nextVertex ) { | ||
@@ -103,18 +106,22 @@ | ||
} // | ||
} | ||
// | ||
const simplifiedGeometry = new THREE.BufferGeometry(); | ||
const position = []; | ||
index = []; // | ||
index = []; | ||
// | ||
for ( let i = 0; i < vertices.length; i ++ ) { | ||
const vertex = vertices[ i ].position; | ||
position.push( vertex.x, vertex.y, vertex.z ); // cache final index to GREATLY speed up faces reconstruction | ||
position.push( vertex.x, vertex.y, vertex.z ); | ||
// cache final index to GREATLY speed up faces reconstruction | ||
vertices[ i ].id = i; | ||
} // | ||
} | ||
// | ||
@@ -126,4 +133,5 @@ for ( let i = 0; i < faces.length; i ++ ) { | ||
} // | ||
} | ||
// | ||
@@ -137,3 +145,2 @@ simplifiedGeometry.setAttribute( 'position', new THREE.Float32BufferAttribute( position, 3 ) ); | ||
} | ||
function pushIfUnique( array, object ) { | ||
@@ -156,10 +163,11 @@ | ||
// much different will the model change, i.e. the "error". | ||
const edgelength = v.position.distanceTo( u.position ); | ||
let curvature = 0; | ||
const sideFaces = []; // find the "sides" triangles that are on the edge uv | ||
const sideFaces = []; | ||
// find the "sides" triangles that are on the edge uv | ||
for ( let i = 0, il = u.faces.length; i < il; i ++ ) { | ||
const face = u.faces[ i ]; | ||
if ( face.hasVertex( v ) ) { | ||
@@ -171,6 +179,6 @@ | ||
} // use the triangle facing most away from the sides | ||
} | ||
// use the triangle facing most away from the sides | ||
// to determine our curvature term | ||
for ( let i = 0, il = u.faces.length; i < il; i ++ ) { | ||
@@ -180,7 +188,6 @@ | ||
const face = u.faces[ i ]; | ||
for ( let j = 0; j < sideFaces.length; j ++ ) { | ||
const sideFace = sideFaces[ j ]; // use dot product of face normals. | ||
const sideFace = sideFaces[ j ]; | ||
// use dot product of face normals. | ||
const dotProd = face.normal.dot( sideFace.normal ); | ||
@@ -193,8 +200,7 @@ minCurvature = Math.min( minCurvature, ( 1.001 - dotProd ) / 2 ); | ||
} // crude approach in attempt to preserve borders | ||
} | ||
// crude approach in attempt to preserve borders | ||
// though it seems not to be totally correct | ||
const borders = 0; | ||
if ( sideFaces.length < 2 ) { | ||
@@ -221,2 +227,3 @@ | ||
// cost (in member variable collapseCost). | ||
if ( v.neighbors.length === 0 ) { | ||
@@ -232,8 +239,8 @@ | ||
v.collapseCost = 100000; | ||
v.collapseNeighbor = null; // search all neighboring edges for "least cost" edge | ||
v.collapseNeighbor = null; | ||
// search all neighboring edges for "least cost" edge | ||
for ( let i = 0; i < v.neighbors.length; i ++ ) { | ||
const collapseCost = computeEdgeCollapseCost( v, v.neighbors[ i ] ); | ||
if ( ! v.collapseNeighbor ) { | ||
@@ -251,3 +258,2 @@ | ||
v.totalCost += collapseCost; | ||
if ( collapseCost < v.minCost ) { | ||
@@ -260,7 +266,8 @@ | ||
} // we average the cost of collapsing at this vertex | ||
} | ||
// we average the cost of collapsing at this vertex | ||
v.collapseCost = v.totalCost / v.costCount; | ||
// v.collapseCost = v.minCost; | ||
v.collapseCost = v.totalCost / v.costCount; // v.collapseCost = v.minCost; | ||
} | ||
@@ -271,3 +278,2 @@ | ||
console.assert( v.faces.length === 0 ); | ||
while ( v.neighbors.length ) { | ||
@@ -289,6 +295,6 @@ | ||
if ( f.v2 ) removeFromArray( f.v2.faces, f ); | ||
if ( f.v3 ) removeFromArray( f.v3.faces, f ); // TODO optimize this! | ||
if ( f.v3 ) removeFromArray( f.v3.faces, f ); | ||
// TODO optimize this! | ||
const vs = [ f.v1, f.v2, f.v3 ]; | ||
for ( let i = 0; i < 3; i ++ ) { | ||
@@ -309,3 +315,5 @@ | ||
// u and v are pointers to vertices of an edge | ||
// Collapse the edge uv by moving vertex u onto v | ||
if ( ! v ) { | ||
@@ -320,3 +328,2 @@ | ||
const tmpVertices = []; | ||
for ( let i = 0; i < u.neighbors.length; i ++ ) { | ||
@@ -326,5 +333,5 @@ | ||
} // delete triangles on edge uv: | ||
} | ||
// delete triangles on edge uv: | ||
for ( let i = u.faces.length - 1; i >= 0; i -- ) { | ||
@@ -338,5 +345,5 @@ | ||
} // update remaining triangles to have v instead of u | ||
} | ||
// update remaining triangles to have v instead of u | ||
for ( let i = u.faces.length - 1; i >= 0; i -- ) { | ||
@@ -348,4 +355,5 @@ | ||
removeVertex( u, vertices ); // recompute the edge collapse costs in neighborhood | ||
removeVertex( u, vertices ); | ||
// recompute the edge collapse costs in neighborhood | ||
for ( let i = 0; i < tmpVertices.length; i ++ ) { | ||
@@ -362,4 +370,4 @@ | ||
// O(n * n) approach. TODO optimize this | ||
let least = vertices[ 0 ]; | ||
for ( let i = 0; i < vertices.length; i ++ ) { | ||
@@ -377,4 +385,5 @@ | ||
} // we use a triangle class to represent structure of face slightly differently | ||
} | ||
// we use a triangle class to represent structure of face slightly differently | ||
@@ -404,3 +413,2 @@ class Triangle { | ||
} | ||
computeNormal() { | ||
@@ -411,13 +419,8 @@ | ||
const vC = this.v3.position; | ||
_cb.subVectors( vC, vB ); | ||
_ab.subVectors( vA, vB ); | ||
_cb.cross( _ab ).normalize(); | ||
this.normal.copy( _cb ); | ||
} | ||
hasVertex( v ) { | ||
@@ -428,3 +431,2 @@ | ||
} | ||
replaceVertex( oldv, newv ) { | ||
@@ -452,3 +454,2 @@ | ||
} | ||
class Vertex { | ||
@@ -462,8 +463,6 @@ | ||
this.faces = []; // faces vertex is connected | ||
this.neighbors = []; // neighbouring vertices aka "adjacentVertices" | ||
this.neighbors = []; // neighbouring vertices aka "adjacentVertices" | ||
// these will be computed in computeEdgeCostAtVertex() | ||
this.collapseCost = 0; // cost of collapsing this vertex, the less the better. aka objdist | ||
this.collapseNeighbor = null; // best candinate for collapsing | ||
@@ -478,3 +477,2 @@ | ||
} | ||
removeIfNonNeighbor( n ) { | ||
@@ -486,3 +484,2 @@ | ||
if ( offset === - 1 ) return; | ||
for ( let i = 0; i < faces.length; i ++ ) { | ||
@@ -489,0 +486,0 @@ |
@@ -15,3 +15,2 @@ ( function () { | ||
} | ||
modify( geometry ) { | ||
@@ -23,4 +22,5 @@ | ||
} // | ||
} | ||
// | ||
@@ -71,3 +71,2 @@ const maxIterations = this.maxIterations; | ||
let tessellating = true; | ||
function addTriangle( a, b, c ) { | ||
@@ -81,3 +80,2 @@ | ||
positions2.push( v3.x, v3.y, v3.z ); | ||
if ( hasNormals ) { | ||
@@ -135,3 +133,2 @@ | ||
positions2 = []; | ||
if ( hasNormals ) { | ||
@@ -170,3 +167,2 @@ | ||
vc.fromArray( positions, i + 6 ); | ||
if ( hasNormals ) { | ||
@@ -207,7 +203,5 @@ | ||
const dac = va.distanceToSquared( vc ); | ||
if ( dab > maxEdgeLengthSquared || dbc > maxEdgeLengthSquared || dac > maxEdgeLengthSquared ) { | ||
tessellating = true; | ||
if ( dab >= dbc && dab >= dac ) { | ||
@@ -257,3 +251,2 @@ | ||
geometry2.setAttribute( 'position', new THREE.Float32BufferAttribute( positions2, 3 ) ); | ||
if ( hasNormals ) { | ||
@@ -260,0 +253,0 @@ |
@@ -7,3 +7,2 @@ ( function () { | ||
*/ | ||
class GroundProjectedEnv extends THREE.Mesh { | ||
@@ -16,13 +15,8 @@ | ||
const cubeSize = w / 4; | ||
const _lodMax = Math.floor( Math.log2( cubeSize ) ); | ||
const _cubeSize = Math.pow( 2, _lodMax ); | ||
const width = 3 * Math.max( _cubeSize, 16 * 7 ); | ||
const height = 4 * _cubeSize; | ||
const defines = [ isCubeMap ? '#define ENVMAP_TYPE_CUBE' : '', `#define CUBEUV_TEXEL_WIDTH ${1.0 / width}`, `#define CUBEUV_TEXEL_HEIGHT ${1.0 / height}`, `#define CUBEUV_MAX_MIP ${_lodMax}.0` ]; | ||
const vertexShader = | ||
/* glsl */ | ||
` | ||
const vertexShader = /* glsl */` | ||
varying vec3 vWorldPosition; | ||
@@ -40,5 +34,3 @@ | ||
`; | ||
const fragmentShader = defines.join( '\n' ) + | ||
/* glsl */ | ||
` | ||
const fragmentShader = defines.join( '\n' ) + /* glsl */` | ||
#define ENVMAP_TYPE_CUBE_UV | ||
@@ -167,3 +159,2 @@ | ||
} | ||
set radius( radius ) { | ||
@@ -174,3 +165,2 @@ | ||
} | ||
get radius() { | ||
@@ -181,3 +171,2 @@ | ||
} | ||
set height( height ) { | ||
@@ -188,3 +177,2 @@ | ||
} | ||
get height() { | ||
@@ -191,0 +179,0 @@ |
@@ -14,10 +14,16 @@ ( function () { | ||
this.frustumCulled = false; | ||
this.renderOrder = Infinity; // | ||
this.renderOrder = Infinity; | ||
// | ||
const positionScreen = new THREE.Vector3(); | ||
const positionView = new THREE.Vector3(); // textures | ||
const positionView = new THREE.Vector3(); | ||
// textures | ||
const tempMap = new THREE.FramebufferTexture( 16, 16, THREE.RGBAFormat ); | ||
const occlusionMap = new THREE.FramebufferTexture( 16, 16, THREE.RGBAFormat ); // material | ||
const occlusionMap = new THREE.FramebufferTexture( 16, 16, THREE.RGBAFormat ); | ||
// material | ||
const geometry = Lensflare.Geometry; | ||
@@ -33,5 +39,3 @@ const material1a = new THREE.RawShaderMaterial( { | ||
}, | ||
vertexShader: | ||
/* glsl */ | ||
` | ||
vertexShader: /* glsl */` | ||
@@ -50,5 +54,3 @@ precision highp float; | ||
}`, | ||
fragmentShader: | ||
/* glsl */ | ||
` | ||
fragmentShader: /* glsl */` | ||
@@ -78,5 +80,3 @@ precision highp float; | ||
}, | ||
vertexShader: | ||
/* glsl */ | ||
` | ||
vertexShader: /* glsl */` | ||
@@ -100,5 +100,3 @@ precision highp float; | ||
}`, | ||
fragmentShader: | ||
/* glsl */ | ||
` | ||
fragmentShader: /* glsl */` | ||
@@ -119,6 +117,10 @@ precision highp float; | ||
transparent: false | ||
} ); // the following object is used for occlusionMap generation | ||
} ); | ||
const mesh1 = new THREE.Mesh( geometry, material1a ); // | ||
// the following object is used for occlusionMap generation | ||
const mesh1 = new THREE.Mesh( geometry, material1a ); | ||
// | ||
const elements = []; | ||
@@ -151,3 +153,2 @@ const shader = LensflareElement.Shader; | ||
const mesh2 = new THREE.Mesh( geometry, material2 ); | ||
this.addElement = function ( element ) { | ||
@@ -157,4 +158,5 @@ | ||
}; // | ||
}; | ||
// | ||
@@ -165,3 +167,2 @@ const scale = new THREE.Vector2(); | ||
const viewport = new THREE.Vector4(); | ||
this.onBeforeRender = function ( renderer, scene, camera ) { | ||
@@ -176,4 +177,6 @@ | ||
validArea.min.set( viewport.x, viewport.y ); | ||
validArea.max.set( viewport.x + ( viewport.z - 16 ), viewport.y + ( viewport.w - 16 ) ); // calculate position in screen space | ||
validArea.max.set( viewport.x + ( viewport.z - 16 ), viewport.y + ( viewport.w - 16 ) ); | ||
// calculate position in screen space | ||
positionView.setFromMatrixPosition( this.matrixWorld ); | ||
@@ -183,27 +186,39 @@ positionView.applyMatrix4( camera.matrixWorldInverse ); | ||
positionScreen.copy( positionView ).applyMatrix4( camera.projectionMatrix ); // horizontal and vertical coordinate of the lower left corner of the pixels to copy | ||
positionScreen.copy( positionView ).applyMatrix4( camera.projectionMatrix ); | ||
// horizontal and vertical coordinate of the lower left corner of the pixels to copy | ||
screenPositionPixels.x = viewport.x + positionScreen.x * halfViewportWidth + halfViewportWidth - 8; | ||
screenPositionPixels.y = viewport.y + positionScreen.y * halfViewportHeight + halfViewportHeight - 8; // screen cull | ||
screenPositionPixels.y = viewport.y + positionScreen.y * halfViewportHeight + halfViewportHeight - 8; | ||
// screen cull | ||
if ( validArea.containsPoint( screenPositionPixels ) ) { | ||
// save current RGB to temp texture | ||
renderer.copyFramebufferToTexture( screenPositionPixels, tempMap ); // render pink quad | ||
renderer.copyFramebufferToTexture( screenPositionPixels, tempMap ); | ||
// render pink quad | ||
let uniforms = material1a.uniforms; | ||
uniforms[ 'scale' ].value = scale; | ||
uniforms[ 'screenPosition' ].value = positionScreen; | ||
renderer.renderBufferDirect( camera, null, geometry, material1a, mesh1, null ); // copy result to occlusionMap | ||
renderer.renderBufferDirect( camera, null, geometry, material1a, mesh1, null ); | ||
renderer.copyFramebufferToTexture( screenPositionPixels, occlusionMap ); // restore graphics | ||
// copy result to occlusionMap | ||
renderer.copyFramebufferToTexture( screenPositionPixels, occlusionMap ); | ||
// restore graphics | ||
uniforms = material1b.uniforms; | ||
uniforms[ 'scale' ].value = scale; | ||
uniforms[ 'screenPosition' ].value = positionScreen; | ||
renderer.renderBufferDirect( camera, null, geometry, material1b, mesh1, null ); // render elements | ||
renderer.renderBufferDirect( camera, null, geometry, material1b, mesh1, null ); | ||
// render elements | ||
const vecX = - positionScreen.x * 2; | ||
const vecY = - positionScreen.y * 2; | ||
for ( let i = 0, l = elements.length; i < l; i ++ ) { | ||
@@ -236,3 +251,2 @@ | ||
occlusionMap.dispose(); | ||
for ( let i = 0, l = elements.length; i < l; i ++ ) { | ||
@@ -248,4 +262,5 @@ | ||
} // | ||
} | ||
// | ||
@@ -264,3 +279,2 @@ class LensflareElement { | ||
} | ||
LensflareElement.Shader = { | ||
@@ -284,5 +298,3 @@ uniforms: { | ||
}, | ||
vertexShader: | ||
/* glsl */ | ||
` | ||
vertexShader: /* glsl */` | ||
@@ -325,5 +337,3 @@ precision highp float; | ||
}`, | ||
fragmentShader: | ||
/* glsl */ | ||
` | ||
fragmentShader: /* glsl */` | ||
@@ -347,3 +357,2 @@ precision highp float; | ||
}; | ||
Lensflare.Geometry = function () { | ||
@@ -350,0 +359,0 @@ |
@@ -54,4 +54,6 @@ ( function () { | ||
super(); | ||
this.isLightningStorm = true; // Parameters | ||
this.isLightningStorm = true; | ||
// Parameters | ||
this.stormParams = stormParams; | ||
@@ -72,3 +74,2 @@ stormParams.size = stormParams.size !== undefined ? stormParams.size : 1000.0; | ||
} ); | ||
if ( stormParams.onRayPosition !== undefined ) { | ||
@@ -90,4 +91,6 @@ | ||
this.onLightningDown = stormParams.onLightningDown; // Internal state | ||
this.onLightningDown = stormParams.onLightningDown; | ||
// Internal state | ||
this.inited = false; | ||
@@ -97,3 +100,2 @@ this.nextLightningTime = 0; | ||
this.deadLightningsMeshes = []; | ||
for ( let i = 0; i < this.stormParams.maxLightnings; i ++ ) { | ||
@@ -108,3 +110,2 @@ | ||
} | ||
update( time ) { | ||
@@ -122,4 +123,4 @@ | ||
// Lightning creation | ||
const lightningMesh = this.deadLightningsMeshes.pop(); | ||
if ( lightningMesh ) { | ||
@@ -135,5 +136,5 @@ | ||
} // Schedule next lightning | ||
} | ||
// Schedule next lightning | ||
this.nextLightningTime = this.getNextLightningTime( time ); | ||
@@ -145,3 +146,2 @@ | ||
il = this.lightningsMeshes.length; | ||
while ( i < il ) { | ||
@@ -153,3 +153,2 @@ | ||
lightning.update( time ); | ||
if ( prevState === THREE.LightningStrike.RAY_PROPAGATING && lightning.state > prevState ) { | ||
@@ -168,2 +167,3 @@ | ||
// Lightning is to be destroyed | ||
this.lightningsMeshes.splice( this.lightningsMeshes.indexOf( mesh ), 1 ); | ||
@@ -183,3 +183,2 @@ this.deadLightningsMeshes.push( mesh ); | ||
} | ||
getNextLightningTime( currentTime ) { | ||
@@ -190,3 +189,2 @@ | ||
} | ||
copy( source, recursive ) { | ||
@@ -210,3 +208,2 @@ | ||
} | ||
clone() { | ||
@@ -213,0 +210,0 @@ |
@@ -14,4 +14,6 @@ ( function () { | ||
this.isMarchingCubes = true; | ||
const scope = this; // temp buffers used in polygonize | ||
const scope = this; | ||
// temp buffers used in polygonize | ||
const vlist = new Float32Array( 12 * 3 ); | ||
@@ -21,3 +23,5 @@ const nlist = new Float32Array( 12 * 3 ); | ||
this.enableUvs = enableUvs; | ||
this.enableColors = enableColors; // functions have to be object properties | ||
this.enableColors = enableColors; | ||
// functions have to be object properties | ||
// prototype functions kill performance | ||
@@ -28,11 +32,17 @@ // (tested and it was 4x slower !!!) | ||
this.resolution = resolution; // parameters | ||
this.resolution = resolution; | ||
this.isolation = 80.0; // size of field, 32 is pushing it in Javascript :) | ||
// parameters | ||
this.isolation = 80.0; | ||
// size of field, 32 is pushing it in Javascript :) | ||
this.size = resolution; | ||
this.size2 = this.size * this.size; | ||
this.size3 = this.size2 * this.size; | ||
this.halfsize = this.size / 2.0; // deltas | ||
this.halfsize = this.size / 2.0; | ||
// deltas | ||
this.delta = 2.0 / this.size; | ||
@@ -43,4 +53,6 @@ this.yd = this.size; | ||
this.normal_cache = new Float32Array( this.size3 * 3 ); | ||
this.palette = new Float32Array( this.size3 * 3 ); // | ||
this.palette = new Float32Array( this.size3 * 3 ); | ||
// | ||
this.count = 0; | ||
@@ -56,3 +68,2 @@ const maxVertexCount = maxPolyCount * 3; | ||
geometry.setAttribute( 'normal', normalAttribute ); | ||
if ( this.enableUvs ) { | ||
@@ -76,7 +87,8 @@ | ||
}; /////////////////////// | ||
}; | ||
/////////////////////// | ||
// Polygonization | ||
/////////////////////// | ||
function lerp( a, b, t ) { | ||
@@ -141,3 +153,2 @@ | ||
const q3 = q * 3; | ||
if ( scope.normal_cache[ q3 ] === 0.0 ) { | ||
@@ -151,6 +162,7 @@ | ||
} // Returns total number of triangles. Fills triangles. | ||
} | ||
// Returns total number of triangles. Fills triangles. | ||
// (this is where most of time is spent - it's inner work of O(n3) loop ) | ||
function polygonize( fx, fy, fz, q, isol ) { | ||
@@ -182,4 +194,6 @@ | ||
if ( field6 < isol ) cubeindex |= 128; | ||
if ( field7 < isol ) cubeindex |= 64; // if cube is entirely in/out of the surface - bail, nothing to draw | ||
if ( field7 < isol ) cubeindex |= 64; | ||
// if cube is entirely in/out of the surface - bail, nothing to draw | ||
const bits = edgeTable[ cubeindex ]; | ||
@@ -190,4 +204,6 @@ if ( bits === 0 ) return 0; | ||
fy2 = fy + d, | ||
fz2 = fz + d; // top of the cube | ||
fz2 = fz + d; | ||
// top of the cube | ||
if ( bits & 1 ) { | ||
@@ -223,4 +239,5 @@ | ||
} // bottom of the cube | ||
} | ||
// bottom of the cube | ||
@@ -257,5 +274,5 @@ if ( bits & 16 ) { | ||
} // vertical lines of the cube | ||
} | ||
// vertical lines of the cube | ||
if ( bits & 256 ) { | ||
@@ -299,4 +316,6 @@ | ||
numtris = 0, | ||
i = 0; // here is where triangles are created | ||
i = 0; | ||
// here is where triangles are created | ||
while ( triTable[ cubeindex + i ] != - 1 ) { | ||
@@ -319,4 +338,6 @@ | ||
const c = scope.count * 3; // positions | ||
const c = scope.count * 3; | ||
// positions | ||
scope.positionArray[ c + 0 ] = pos[ o1 ]; | ||
@@ -330,4 +351,6 @@ scope.positionArray[ c + 1 ] = pos[ o1 + 1 ]; | ||
scope.positionArray[ c + 7 ] = pos[ o3 + 1 ]; | ||
scope.positionArray[ c + 8 ] = pos[ o3 + 2 ]; // normals | ||
scope.positionArray[ c + 8 ] = pos[ o3 + 2 ]; | ||
// normals | ||
if ( scope.material.flatShading === true ) { | ||
@@ -360,4 +383,5 @@ | ||
} // uvs | ||
} | ||
// uvs | ||
@@ -374,4 +398,5 @@ if ( scope.enableUvs ) { | ||
} // colors | ||
} | ||
// colors | ||
@@ -394,9 +419,11 @@ if ( scope.enableColors ) { | ||
} ///////////////////////////////////// | ||
} | ||
///////////////////////////////////// | ||
// Metaballs | ||
///////////////////////////////////// | ||
// Adds a reciprocal ball (nice and blobby) that, to be fast, fades to zero after | ||
// a fixed distance, determined by strength and subtract. | ||
this.addBall = function ( ballx, bally, ballz, strength, subtract, colors ) { | ||
@@ -408,3 +435,2 @@ | ||
let ballColor = new THREE.Color( ballx, bally, ballz ); | ||
if ( userDefineColor ) { | ||
@@ -422,3 +448,5 @@ | ||
} // Let's solve the equation to find the radius: | ||
} | ||
// Let's solve the equation to find the radius: | ||
// 1.0 / (0.000001 + radius^2) * strength - subtract = 0 | ||
@@ -430,3 +458,2 @@ // strength / (radius^2) = subtract | ||
const radius = this.size * Math.sqrt( strength / subtract ), | ||
@@ -447,7 +474,8 @@ zs = ballz * this.size, | ||
let max_x = Math.floor( xs + radius ); | ||
if ( max_x > this.size - 1 ) max_x = this.size - 1; // Don't polygonize in the outer layer because normals aren't | ||
if ( max_x > this.size - 1 ) max_x = this.size - 1; | ||
// Don't polygonize in the outer layer because normals aren't | ||
// well-defined there. | ||
let x, y, z, y_offset, z_offset, fx, fy, fz, fz2, fy2, val; | ||
for ( z = min_z; z < max_z; z ++ ) { | ||
@@ -458,3 +486,2 @@ | ||
fz2 = fz * fz; | ||
for ( y = min_y; y < max_y; y ++ ) { | ||
@@ -465,3 +492,2 @@ | ||
fy2 = fy * fy; | ||
for ( x = min_x; x < max_x; x ++ ) { | ||
@@ -471,8 +497,8 @@ | ||
val = strength / ( 0.000001 + fx * fx + fy2 + fz2 ) - subtract; | ||
if ( val > 0.0 ) { | ||
this.field[ y_offset + x ] += val * sign; // optimization | ||
this.field[ y_offset + x ] += val * sign; | ||
// optimization | ||
// http://www.geisswerks.com/ryan/BLOBS/blobs.html | ||
const ratio = Math.sqrt( ( x - xs ) * ( x - xs ) + ( y - ys ) * ( y - ys ) + ( z - zs ) * ( z - zs ) ) / radius; | ||
@@ -510,3 +536,2 @@ const contrib = 1 - ratio * ratio * ratio * ( ratio * ( ratio * 6 - 15 ) + 10 ); | ||
if ( dist > size ) dist = size; | ||
for ( x = 0; x < dist; x ++ ) { | ||
@@ -517,3 +542,2 @@ | ||
val = strength / ( 0.0001 + xx ) - subtract; | ||
if ( val > 0.0 ) { | ||
@@ -524,3 +548,2 @@ | ||
cxy = x + y * yd; | ||
for ( z = 0; z < size; z ++ ) { | ||
@@ -557,3 +580,2 @@ | ||
if ( dist > size ) dist = size; | ||
for ( y = 0; y < dist; y ++ ) { | ||
@@ -564,11 +586,8 @@ | ||
val = strength / ( 0.0001 + yy ) - subtract; | ||
if ( val > 0.0 ) { | ||
cy = y * yd; | ||
for ( x = 0; x < size; x ++ ) { | ||
cxy = cy + x; | ||
for ( z = 0; z < size; z ++ ) field[ zd * z + cxy ] += val; | ||
@@ -587,2 +606,3 @@ | ||
// cache attribute lookups | ||
const size = this.size, | ||
@@ -602,3 +622,2 @@ yd = this.yd, | ||
if ( dist > size ) dist = size; | ||
for ( z = 0; z < dist; z ++ ) { | ||
@@ -609,11 +628,8 @@ | ||
val = strength / ( 0.0001 + zz ) - subtract; | ||
if ( val > 0.0 ) { | ||
cz = zd * z; | ||
for ( y = 0; y < size; y ++ ) { | ||
cyz = cz + y * yd; | ||
for ( x = 0; x < size; x ++ ) field[ cyz + x ] += val; | ||
@@ -627,7 +643,8 @@ | ||
}; ///////////////////////////////////// | ||
}; | ||
///////////////////////////////////// | ||
// Updates | ||
///////////////////////////////////// | ||
this.setCell = function ( x, y, z, value ) { | ||
@@ -653,3 +670,2 @@ | ||
const size2 = this.size2; | ||
for ( let x = 0; x < size; x ++ ) { | ||
@@ -664,3 +680,2 @@ | ||
let count = 1; | ||
for ( let x2 = - 1; x2 <= 1; x2 += 2 ) { | ||
@@ -670,3 +685,2 @@ | ||
if ( x3 < 0 || x3 >= size ) continue; | ||
for ( let y2 = - 1; y2 <= 1; y2 += 2 ) { | ||
@@ -676,3 +690,2 @@ | ||
if ( y3 < 0 || y3 >= size ) continue; | ||
for ( let z2 = - 1; z2 <= 1; z2 += 2 ) { | ||
@@ -706,2 +719,3 @@ | ||
// wipe the normal cache | ||
for ( let i = 0; i < this.size3; i ++ ) { | ||
@@ -719,6 +733,7 @@ | ||
this.count = 0; // Triangulate. Yeah, this is slow. | ||
this.count = 0; | ||
// Triangulate. Yeah, this is slow. | ||
const smin2 = this.size - 2; | ||
for ( let z = 1; z < smin2; z ++ ) { | ||
@@ -737,3 +752,2 @@ | ||
const fx = ( x - this.halfsize ) / this.halfsize; //+ 1 | ||
const q = y_offset + x; | ||
@@ -746,12 +760,17 @@ polygonize( fx, fy, fz, q, this.isolation ); | ||
} // set the draw range to only the processed triangles | ||
} | ||
// set the draw range to only the processed triangles | ||
this.geometry.setDrawRange( 0, this.count ); // update geometry data | ||
this.geometry.setDrawRange( 0, this.count ); | ||
// update geometry data | ||
geometry.getAttribute( 'position' ).needsUpdate = true; | ||
geometry.getAttribute( 'normal' ).needsUpdate = true; | ||
if ( this.enableUvs ) geometry.getAttribute( 'uv' ).needsUpdate = true; | ||
if ( this.enableColors ) geometry.getAttribute( 'color' ).needsUpdate = true; // safety check | ||
if ( this.enableColors ) geometry.getAttribute( 'color' ).needsUpdate = true; | ||
// safety check | ||
if ( this.count / 3 > maxPolyCount ) console.warn( 'THREE.MarchingCubes: Geometry buffers too small for rendering. Please create an instance with a higher poly count.' ); | ||
@@ -765,5 +784,8 @@ | ||
} ///////////////////////////////////// | ||
} | ||
///////////////////////////////////// | ||
// Marching cubes lookup tables | ||
///////////////////////////////////// | ||
// These tables are straight from Paul Bourke's page: | ||
@@ -773,3 +795,2 @@ // http://paulbourke.net/geometry/polygonise/ | ||
const edgeTable = new Int32Array( [ 0x0, 0x109, 0x203, 0x30a, 0x406, 0x50f, 0x605, 0x70c, 0x80c, 0x905, 0xa0f, 0xb06, 0xc0a, 0xd03, 0xe09, 0xf00, 0x190, 0x99, 0x393, 0x29a, 0x596, 0x49f, 0x795, 0x69c, 0x99c, 0x895, 0xb9f, 0xa96, 0xd9a, 0xc93, 0xf99, 0xe90, 0x230, 0x339, 0x33, 0x13a, 0x636, 0x73f, 0x435, 0x53c, 0xa3c, 0xb35, 0x83f, 0x936, 0xe3a, 0xf33, 0xc39, 0xd30, 0x3a0, 0x2a9, 0x1a3, 0xaa, 0x7a6, 0x6af, 0x5a5, 0x4ac, 0xbac, 0xaa5, 0x9af, 0x8a6, 0xfaa, 0xea3, 0xda9, 0xca0, 0x460, 0x569, 0x663, 0x76a, 0x66, 0x16f, 0x265, 0x36c, 0xc6c, 0xd65, 0xe6f, 0xf66, 0x86a, 0x963, 0xa69, 0xb60, 0x5f0, 0x4f9, 0x7f3, 0x6fa, 0x1f6, 0xff, 0x3f5, 0x2fc, 0xdfc, 0xcf5, 0xfff, 0xef6, 0x9fa, 0x8f3, 0xbf9, 0xaf0, 0x650, 0x759, 0x453, 0x55a, 0x256, 0x35f, 0x55, 0x15c, 0xe5c, 0xf55, 0xc5f, 0xd56, 0xa5a, 0xb53, 0x859, 0x950, 0x7c0, 0x6c9, 0x5c3, 0x4ca, 0x3c6, 0x2cf, 0x1c5, 0xcc, 0xfcc, 0xec5, 0xdcf, 0xcc6, 0xbca, 0xac3, 0x9c9, 0x8c0, 0x8c0, 0x9c9, 0xac3, 0xbca, 0xcc6, 0xdcf, 0xec5, 0xfcc, 0xcc, 0x1c5, 0x2cf, 0x3c6, 0x4ca, 0x5c3, 0x6c9, 0x7c0, 0x950, 0x859, 0xb53, 0xa5a, 0xd56, 0xc5f, 0xf55, 0xe5c, 0x15c, 0x55, 0x35f, 0x256, 0x55a, 0x453, 0x759, 0x650, 0xaf0, 0xbf9, 0x8f3, 0x9fa, 0xef6, 0xfff, 0xcf5, 0xdfc, 0x2fc, 0x3f5, 0xff, 0x1f6, 0x6fa, 0x7f3, 0x4f9, 0x5f0, 0xb60, 0xa69, 0x963, 0x86a, 0xf66, 0xe6f, 0xd65, 0xc6c, 0x36c, 0x265, 0x16f, 0x66, 0x76a, 0x663, 0x569, 0x460, 0xca0, 0xda9, 0xea3, 0xfaa, 0x8a6, 0x9af, 0xaa5, 0xbac, 0x4ac, 0x5a5, 0x6af, 0x7a6, 0xaa, 0x1a3, 0x2a9, 0x3a0, 0xd30, 0xc39, 0xf33, 0xe3a, 0x936, 0x83f, 0xb35, 0xa3c, 0x53c, 0x435, 0x73f, 0x636, 0x13a, 0x33, 0x339, 0x230, 0xe90, 0xf99, 0xc93, 0xd9a, 0xa96, 0xb9f, 0x895, 0x99c, 0x69c, 0x795, 0x49f, 0x596, 0x29a, 0x393, 0x99, 0x190, 0xf00, 0xe09, 0xd03, 0xc0a, 0xb06, 0xa0f, 0x905, 0x80c, 0x70c, 0x605, 0x50f, 0x406, 0x30a, 0x203, 0x109, 0x0 ] ); | ||
@@ -776,0 +797,0 @@ const triTable = new Int32Array( [ - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 0, 8, 3, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 0, 1, 9, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 1, 8, 3, 9, 8, 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 1, 2, 10, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 0, 8, 3, 1, 2, 10, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 9, 2, 10, 0, 2, 9, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 2, 8, 3, 2, 10, 8, 10, 9, 8, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 3, 11, 2, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 0, 11, 2, 8, 11, 0, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 1, 9, 0, 2, 3, 11, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 1, 11, 2, 1, 9, 11, 9, 8, 11, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 3, 10, 1, 11, 10, 3, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 0, 10, 1, 0, 8, 10, 8, 11, 10, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 3, 9, 0, 3, 11, 9, 11, 10, 9, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 9, 8, 10, 10, 8, 11, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 4, 7, 8, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 4, 3, 0, 7, 3, 4, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 0, 1, 9, 8, 4, 7, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 4, 1, 9, 4, 7, 1, 7, 3, 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 1, 2, 10, 8, 4, 7, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 3, 4, 7, 3, 0, 4, 1, 2, 10, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 9, 2, 10, 9, 0, 2, 8, 4, 7, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 2, 10, 9, 2, 9, 7, 2, 7, 3, 7, 9, 4, - 1, - 1, - 1, - 1, 8, 4, 7, 3, 11, 2, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 11, 4, 7, 11, 2, 4, 2, 0, 4, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 9, 0, 1, 8, 4, 7, 2, 3, 11, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 4, 7, 11, 9, 4, 11, 9, 11, 2, 9, 2, 1, - 1, - 1, - 1, - 1, 3, 10, 1, 3, 11, 10, 7, 8, 4, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 1, 11, 10, 1, 4, 11, 1, 0, 4, 7, 11, 4, - 1, - 1, - 1, - 1, 4, 7, 8, 9, 0, 11, 9, 11, 10, 11, 0, 3, - 1, - 1, - 1, - 1, 4, 7, 11, 4, 11, 9, 9, 11, 10, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 9, 5, 4, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 9, 5, 4, 0, 8, 3, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 0, 5, 4, 1, 5, 0, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 8, 5, 4, 8, 3, 5, 3, 1, 5, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 1, 2, 10, 9, 5, 4, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 3, 0, 8, 1, 2, 10, 4, 9, 5, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 5, 2, 10, 5, 4, 2, 4, 0, 2, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 2, 10, 5, 3, 2, 5, 3, 5, 4, 3, 4, 8, - 1, - 1, - 1, - 1, 9, 5, 4, 2, 3, 11, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 0, 11, 2, 0, 8, 11, 4, 9, 5, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 0, 5, 4, 0, 1, 5, 2, 3, 11, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 2, 1, 5, 2, 5, 8, 2, 8, 11, 4, 8, 5, - 1, - 1, - 1, - 1, 10, 3, 11, 10, 1, 3, 9, 5, 4, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 4, 9, 5, 0, 8, 1, 8, 10, 1, 8, 11, 10, - 1, - 1, - 1, - 1, 5, 4, 0, 5, 0, 11, 5, 11, 10, 11, 0, 3, - 1, - 1, - 1, - 1, 5, 4, 8, 5, 8, 10, 10, 8, 11, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 9, 7, 8, 5, 7, 9, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 9, 3, 0, 9, 5, 3, 5, 7, 3, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 0, 7, 8, 0, 1, 7, 1, 5, 7, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 1, 5, 3, 3, 5, 7, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 9, 7, 8, 9, 5, 7, 10, 1, 2, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 10, 1, 2, 9, 5, 0, 5, 3, 0, 5, 7, 3, - 1, - 1, - 1, - 1, 8, 0, 2, 8, 2, 5, 8, 5, 7, 10, 5, 2, - 1, - 1, - 1, - 1, 2, 10, 5, 2, 5, 3, 3, 5, 7, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 7, 9, 5, 7, 8, 9, 3, 11, 2, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 9, 5, 7, 9, 7, 2, 9, 2, 0, 2, 7, 11, - 1, - 1, - 1, - 1, 2, 3, 11, 0, 1, 8, 1, 7, 8, 1, 5, 7, - 1, - 1, - 1, - 1, 11, 2, 1, 11, 1, 7, 7, 1, 5, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 9, 5, 8, 8, 5, 7, 10, 1, 3, 10, 3, 11, - 1, - 1, - 1, - 1, 5, 7, 0, 5, 0, 9, 7, 11, 0, 1, 0, 10, 11, 10, 0, - 1, 11, 10, 0, 11, 0, 3, 10, 5, 0, 8, 0, 7, 5, 7, 0, - 1, 11, 10, 5, 7, 11, 5, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 10, 6, 5, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 0, 8, 3, 5, 10, 6, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 9, 0, 1, 5, 10, 6, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 1, 8, 3, 1, 9, 8, 5, 10, 6, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 1, 6, 5, 2, 6, 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 1, 6, 5, 1, 2, 6, 3, 0, 8, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 9, 6, 5, 9, 0, 6, 0, 2, 6, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 5, 9, 8, 5, 8, 2, 5, 2, 6, 3, 2, 8, - 1, - 1, - 1, - 1, 2, 3, 11, 10, 6, 5, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 11, 0, 8, 11, 2, 0, 10, 6, 5, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 0, 1, 9, 2, 3, 11, 5, 10, 6, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 5, 10, 6, 1, 9, 2, 9, 11, 2, 9, 8, 11, - 1, - 1, - 1, - 1, 6, 3, 11, 6, 5, 3, 5, 1, 3, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 0, 8, 11, 0, 11, 5, 0, 5, 1, 5, 11, 6, - 1, - 1, - 1, - 1, 3, 11, 6, 0, 3, 6, 0, 6, 5, 0, 5, 9, - 1, - 1, - 1, - 1, 6, 5, 9, 6, 9, 11, 11, 9, 8, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 5, 10, 6, 4, 7, 8, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 4, 3, 0, 4, 7, 3, 6, 5, 10, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 1, 9, 0, 5, 10, 6, 8, 4, 7, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 10, 6, 5, 1, 9, 7, 1, 7, 3, 7, 9, 4, - 1, - 1, - 1, - 1, 6, 1, 2, 6, 5, 1, 4, 7, 8, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 1, 2, 5, 5, 2, 6, 3, 0, 4, 3, 4, 7, - 1, - 1, - 1, - 1, 8, 4, 7, 9, 0, 5, 0, 6, 5, 0, 2, 6, - 1, - 1, - 1, - 1, 7, 3, 9, 7, 9, 4, 3, 2, 9, 5, 9, 6, 2, 6, 9, - 1, 3, 11, 2, 7, 8, 4, 10, 6, 5, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 5, 10, 6, 4, 7, 2, 4, 2, 0, 2, 7, 11, - 1, - 1, - 1, - 1, 0, 1, 9, 4, 7, 8, 2, 3, 11, 5, 10, 6, - 1, - 1, - 1, - 1, 9, 2, 1, 9, 11, 2, 9, 4, 11, 7, 11, 4, 5, 10, 6, - 1, 8, 4, 7, 3, 11, 5, 3, 5, 1, 5, 11, 6, - 1, - 1, - 1, - 1, 5, 1, 11, 5, 11, 6, 1, 0, 11, 7, 11, 4, 0, 4, 11, - 1, 0, 5, 9, 0, 6, 5, 0, 3, 6, 11, 6, 3, 8, 4, 7, - 1, 6, 5, 9, 6, 9, 11, 4, 7, 9, 7, 11, 9, - 1, - 1, - 1, - 1, 10, 4, 9, 6, 4, 10, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 4, 10, 6, 4, 9, 10, 0, 8, 3, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 10, 0, 1, 10, 6, 0, 6, 4, 0, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 8, 3, 1, 8, 1, 6, 8, 6, 4, 6, 1, 10, - 1, - 1, - 1, - 1, 1, 4, 9, 1, 2, 4, 2, 6, 4, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 3, 0, 8, 1, 2, 9, 2, 4, 9, 2, 6, 4, - 1, - 1, - 1, - 1, 0, 2, 4, 4, 2, 6, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 8, 3, 2, 8, 2, 4, 4, 2, 6, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 10, 4, 9, 10, 6, 4, 11, 2, 3, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 0, 8, 2, 2, 8, 11, 4, 9, 10, 4, 10, 6, - 1, - 1, - 1, - 1, 3, 11, 2, 0, 1, 6, 0, 6, 4, 6, 1, 10, - 1, - 1, - 1, - 1, 6, 4, 1, 6, 1, 10, 4, 8, 1, 2, 1, 11, 8, 11, 1, - 1, 9, 6, 4, 9, 3, 6, 9, 1, 3, 11, 6, 3, - 1, - 1, - 1, - 1, 8, 11, 1, 8, 1, 0, 11, 6, 1, 9, 1, 4, 6, 4, 1, - 1, 3, 11, 6, 3, 6, 0, 0, 6, 4, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 6, 4, 8, 11, 6, 8, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 7, 10, 6, 7, 8, 10, 8, 9, 10, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 0, 7, 3, 0, 10, 7, 0, 9, 10, 6, 7, 10, - 1, - 1, - 1, - 1, 10, 6, 7, 1, 10, 7, 1, 7, 8, 1, 8, 0, - 1, - 1, - 1, - 1, 10, 6, 7, 10, 7, 1, 1, 7, 3, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 1, 2, 6, 1, 6, 8, 1, 8, 9, 8, 6, 7, - 1, - 1, - 1, - 1, 2, 6, 9, 2, 9, 1, 6, 7, 9, 0, 9, 3, 7, 3, 9, - 1, 7, 8, 0, 7, 0, 6, 6, 0, 2, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 7, 3, 2, 6, 7, 2, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 2, 3, 11, 10, 6, 8, 10, 8, 9, 8, 6, 7, - 1, - 1, - 1, - 1, 2, 0, 7, 2, 7, 11, 0, 9, 7, 6, 7, 10, 9, 10, 7, - 1, 1, 8, 0, 1, 7, 8, 1, 10, 7, 6, 7, 10, 2, 3, 11, - 1, 11, 2, 1, 11, 1, 7, 10, 6, 1, 6, 7, 1, - 1, - 1, - 1, - 1, 8, 9, 6, 8, 6, 7, 9, 1, 6, 11, 6, 3, 1, 3, 6, - 1, 0, 9, 1, 11, 6, 7, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 7, 8, 0, 7, 0, 6, 3, 11, 0, 11, 6, 0, - 1, - 1, - 1, - 1, 7, 11, 6, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 7, 6, 11, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 3, 0, 8, 11, 7, 6, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 0, 1, 9, 11, 7, 6, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 8, 1, 9, 8, 3, 1, 11, 7, 6, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 10, 1, 2, 6, 11, 7, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 1, 2, 10, 3, 0, 8, 6, 11, 7, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 2, 9, 0, 2, 10, 9, 6, 11, 7, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 6, 11, 7, 2, 10, 3, 10, 8, 3, 10, 9, 8, - 1, - 1, - 1, - 1, 7, 2, 3, 6, 2, 7, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 7, 0, 8, 7, 6, 0, 6, 2, 0, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 2, 7, 6, 2, 3, 7, 0, 1, 9, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 1, 6, 2, 1, 8, 6, 1, 9, 8, 8, 7, 6, - 1, - 1, - 1, - 1, 10, 7, 6, 10, 1, 7, 1, 3, 7, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 10, 7, 6, 1, 7, 10, 1, 8, 7, 1, 0, 8, - 1, - 1, - 1, - 1, 0, 3, 7, 0, 7, 10, 0, 10, 9, 6, 10, 7, - 1, - 1, - 1, - 1, 7, 6, 10, 7, 10, 8, 8, 10, 9, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 6, 8, 4, 11, 8, 6, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 3, 6, 11, 3, 0, 6, 0, 4, 6, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 8, 6, 11, 8, 4, 6, 9, 0, 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 9, 4, 6, 9, 6, 3, 9, 3, 1, 11, 3, 6, - 1, - 1, - 1, - 1, 6, 8, 4, 6, 11, 8, 2, 10, 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 1, 2, 10, 3, 0, 11, 0, 6, 11, 0, 4, 6, - 1, - 1, - 1, - 1, 4, 11, 8, 4, 6, 11, 0, 2, 9, 2, 10, 9, - 1, - 1, - 1, - 1, 10, 9, 3, 10, 3, 2, 9, 4, 3, 11, 3, 6, 4, 6, 3, - 1, 8, 2, 3, 8, 4, 2, 4, 6, 2, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 0, 4, 2, 4, 6, 2, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 1, 9, 0, 2, 3, 4, 2, 4, 6, 4, 3, 8, - 1, - 1, - 1, - 1, 1, 9, 4, 1, 4, 2, 2, 4, 6, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 8, 1, 3, 8, 6, 1, 8, 4, 6, 6, 10, 1, - 1, - 1, - 1, - 1, 10, 1, 0, 10, 0, 6, 6, 0, 4, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 4, 6, 3, 4, 3, 8, 6, 10, 3, 0, 3, 9, 10, 9, 3, - 1, 10, 9, 4, 6, 10, 4, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 4, 9, 5, 7, 6, 11, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 0, 8, 3, 4, 9, 5, 11, 7, 6, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 5, 0, 1, 5, 4, 0, 7, 6, 11, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 11, 7, 6, 8, 3, 4, 3, 5, 4, 3, 1, 5, - 1, - 1, - 1, - 1, 9, 5, 4, 10, 1, 2, 7, 6, 11, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 6, 11, 7, 1, 2, 10, 0, 8, 3, 4, 9, 5, - 1, - 1, - 1, - 1, 7, 6, 11, 5, 4, 10, 4, 2, 10, 4, 0, 2, - 1, - 1, - 1, - 1, 3, 4, 8, 3, 5, 4, 3, 2, 5, 10, 5, 2, 11, 7, 6, - 1, 7, 2, 3, 7, 6, 2, 5, 4, 9, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 9, 5, 4, 0, 8, 6, 0, 6, 2, 6, 8, 7, - 1, - 1, - 1, - 1, 3, 6, 2, 3, 7, 6, 1, 5, 0, 5, 4, 0, - 1, - 1, - 1, - 1, 6, 2, 8, 6, 8, 7, 2, 1, 8, 4, 8, 5, 1, 5, 8, - 1, 9, 5, 4, 10, 1, 6, 1, 7, 6, 1, 3, 7, - 1, - 1, - 1, - 1, 1, 6, 10, 1, 7, 6, 1, 0, 7, 8, 7, 0, 9, 5, 4, - 1, 4, 0, 10, 4, 10, 5, 0, 3, 10, 6, 10, 7, 3, 7, 10, - 1, 7, 6, 10, 7, 10, 8, 5, 4, 10, 4, 8, 10, - 1, - 1, - 1, - 1, 6, 9, 5, 6, 11, 9, 11, 8, 9, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 3, 6, 11, 0, 6, 3, 0, 5, 6, 0, 9, 5, - 1, - 1, - 1, - 1, 0, 11, 8, 0, 5, 11, 0, 1, 5, 5, 6, 11, - 1, - 1, - 1, - 1, 6, 11, 3, 6, 3, 5, 5, 3, 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 1, 2, 10, 9, 5, 11, 9, 11, 8, 11, 5, 6, - 1, - 1, - 1, - 1, 0, 11, 3, 0, 6, 11, 0, 9, 6, 5, 6, 9, 1, 2, 10, - 1, 11, 8, 5, 11, 5, 6, 8, 0, 5, 10, 5, 2, 0, 2, 5, - 1, 6, 11, 3, 6, 3, 5, 2, 10, 3, 10, 5, 3, - 1, - 1, - 1, - 1, 5, 8, 9, 5, 2, 8, 5, 6, 2, 3, 8, 2, - 1, - 1, - 1, - 1, 9, 5, 6, 9, 6, 0, 0, 6, 2, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 1, 5, 8, 1, 8, 0, 5, 6, 8, 3, 8, 2, 6, 2, 8, - 1, 1, 5, 6, 2, 1, 6, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 1, 3, 6, 1, 6, 10, 3, 8, 6, 5, 6, 9, 8, 9, 6, - 1, 10, 1, 0, 10, 0, 6, 9, 5, 0, 5, 6, 0, - 1, - 1, - 1, - 1, 0, 3, 8, 5, 6, 10, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 10, 5, 6, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 11, 5, 10, 7, 5, 11, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 11, 5, 10, 11, 7, 5, 8, 3, 0, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 5, 11, 7, 5, 10, 11, 1, 9, 0, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 10, 7, 5, 10, 11, 7, 9, 8, 1, 8, 3, 1, - 1, - 1, - 1, - 1, 11, 1, 2, 11, 7, 1, 7, 5, 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 0, 8, 3, 1, 2, 7, 1, 7, 5, 7, 2, 11, - 1, - 1, - 1, - 1, 9, 7, 5, 9, 2, 7, 9, 0, 2, 2, 11, 7, - 1, - 1, - 1, - 1, 7, 5, 2, 7, 2, 11, 5, 9, 2, 3, 2, 8, 9, 8, 2, - 1, 2, 5, 10, 2, 3, 5, 3, 7, 5, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 8, 2, 0, 8, 5, 2, 8, 7, 5, 10, 2, 5, - 1, - 1, - 1, - 1, 9, 0, 1, 5, 10, 3, 5, 3, 7, 3, 10, 2, - 1, - 1, - 1, - 1, 9, 8, 2, 9, 2, 1, 8, 7, 2, 10, 2, 5, 7, 5, 2, - 1, 1, 3, 5, 3, 7, 5, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 0, 8, 7, 0, 7, 1, 1, 7, 5, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 9, 0, 3, 9, 3, 5, 5, 3, 7, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 9, 8, 7, 5, 9, 7, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 5, 8, 4, 5, 10, 8, 10, 11, 8, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 5, 0, 4, 5, 11, 0, 5, 10, 11, 11, 3, 0, - 1, - 1, - 1, - 1, 0, 1, 9, 8, 4, 10, 8, 10, 11, 10, 4, 5, - 1, - 1, - 1, - 1, 10, 11, 4, 10, 4, 5, 11, 3, 4, 9, 4, 1, 3, 1, 4, - 1, 2, 5, 1, 2, 8, 5, 2, 11, 8, 4, 5, 8, - 1, - 1, - 1, - 1, 0, 4, 11, 0, 11, 3, 4, 5, 11, 2, 11, 1, 5, 1, 11, - 1, 0, 2, 5, 0, 5, 9, 2, 11, 5, 4, 5, 8, 11, 8, 5, - 1, 9, 4, 5, 2, 11, 3, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 2, 5, 10, 3, 5, 2, 3, 4, 5, 3, 8, 4, - 1, - 1, - 1, - 1, 5, 10, 2, 5, 2, 4, 4, 2, 0, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 3, 10, 2, 3, 5, 10, 3, 8, 5, 4, 5, 8, 0, 1, 9, - 1, 5, 10, 2, 5, 2, 4, 1, 9, 2, 9, 4, 2, - 1, - 1, - 1, - 1, 8, 4, 5, 8, 5, 3, 3, 5, 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 0, 4, 5, 1, 0, 5, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 8, 4, 5, 8, 5, 3, 9, 0, 5, 0, 3, 5, - 1, - 1, - 1, - 1, 9, 4, 5, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 4, 11, 7, 4, 9, 11, 9, 10, 11, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 0, 8, 3, 4, 9, 7, 9, 11, 7, 9, 10, 11, - 1, - 1, - 1, - 1, 1, 10, 11, 1, 11, 4, 1, 4, 0, 7, 4, 11, - 1, - 1, - 1, - 1, 3, 1, 4, 3, 4, 8, 1, 10, 4, 7, 4, 11, 10, 11, 4, - 1, 4, 11, 7, 9, 11, 4, 9, 2, 11, 9, 1, 2, - 1, - 1, - 1, - 1, 9, 7, 4, 9, 11, 7, 9, 1, 11, 2, 11, 1, 0, 8, 3, - 1, 11, 7, 4, 11, 4, 2, 2, 4, 0, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 11, 7, 4, 11, 4, 2, 8, 3, 4, 3, 2, 4, - 1, - 1, - 1, - 1, 2, 9, 10, 2, 7, 9, 2, 3, 7, 7, 4, 9, - 1, - 1, - 1, - 1, 9, 10, 7, 9, 7, 4, 10, 2, 7, 8, 7, 0, 2, 0, 7, - 1, 3, 7, 10, 3, 10, 2, 7, 4, 10, 1, 10, 0, 4, 0, 10, - 1, 1, 10, 2, 8, 7, 4, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 4, 9, 1, 4, 1, 7, 7, 1, 3, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 4, 9, 1, 4, 1, 7, 0, 8, 1, 8, 7, 1, - 1, - 1, - 1, - 1, 4, 0, 3, 7, 4, 3, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 4, 8, 7, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 9, 10, 8, 10, 11, 8, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 3, 0, 9, 3, 9, 11, 11, 9, 10, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 0, 1, 10, 0, 10, 8, 8, 10, 11, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 3, 1, 10, 11, 3, 10, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 1, 2, 11, 1, 11, 9, 9, 11, 8, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 3, 0, 9, 3, 9, 11, 1, 2, 9, 2, 11, 9, - 1, - 1, - 1, - 1, 0, 2, 11, 8, 0, 11, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 3, 2, 11, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 2, 3, 8, 2, 8, 10, 10, 8, 9, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 9, 10, 2, 0, 9, 2, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 2, 3, 8, 2, 8, 10, 0, 1, 8, 1, 10, 8, - 1, - 1, - 1, - 1, 1, 10, 2, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 1, 3, 8, 9, 1, 8, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 0, 9, 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 0, 3, 8, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1 ] ); |
@@ -17,4 +17,6 @@ ( function () { | ||
const shader = options.shader || Reflector.ReflectorShader; | ||
const multisample = options.multisample !== undefined ? options.multisample : 4; // | ||
const multisample = options.multisample !== undefined ? options.multisample : 4; | ||
// | ||
const reflectorPlane = new THREE.Plane(); | ||
@@ -45,3 +47,2 @@ const normal = new THREE.Vector3(); | ||
this.material = material; | ||
this.onBeforeRender = function ( renderer, scene, camera ) { | ||
@@ -54,4 +55,6 @@ | ||
normal.applyMatrix4( rotationMatrix ); | ||
view.subVectors( reflectorWorldPosition, cameraWorldPosition ); // Avoid rendering when reflector is facing away | ||
view.subVectors( reflectorWorldPosition, cameraWorldPosition ); | ||
// Avoid rendering when reflector is facing away | ||
if ( view.dot( normal ) > 0 ) return; | ||
@@ -75,10 +78,12 @@ view.reflect( normal ).negate(); | ||
virtualCamera.updateMatrixWorld(); | ||
virtualCamera.projectionMatrix.copy( camera.projectionMatrix ); // Update the texture matrix | ||
virtualCamera.projectionMatrix.copy( camera.projectionMatrix ); | ||
// Update the texture matrix | ||
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 ); | ||
textureMatrix.multiply( virtualCamera.projectionMatrix ); | ||
textureMatrix.multiply( virtualCamera.matrixWorldInverse ); | ||
textureMatrix.multiply( scope.matrixWorld ); // Now update projection matrix with new clip plane, implementing code from: http://www.terathon.com/code/oblique.html | ||
textureMatrix.multiply( scope.matrixWorld ); | ||
// 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 | ||
reflectorPlane.setFromNormalAndCoplanarPoint( normal, reflectorWorldPosition ); | ||
@@ -91,11 +96,14 @@ reflectorPlane.applyMatrix4( virtualCamera.matrixWorldInverse ); | ||
q.z = - 1.0; | ||
q.w = ( 1.0 + projectionMatrix.elements[ 10 ] ) / projectionMatrix.elements[ 14 ]; // Calculate the scaled plane vector | ||
q.w = ( 1.0 + projectionMatrix.elements[ 10 ] ) / projectionMatrix.elements[ 14 ]; | ||
clipPlane.multiplyScalar( 2.0 / clipPlane.dot( q ) ); // Replacing the third row of the projection matrix | ||
// Calculate the scaled plane vector | ||
clipPlane.multiplyScalar( 2.0 / clipPlane.dot( q ) ); | ||
// Replacing the third row of the projection matrix | ||
projectionMatrix.elements[ 2 ] = clipPlane.x; | ||
projectionMatrix.elements[ 6 ] = clipPlane.y; | ||
projectionMatrix.elements[ 10 ] = clipPlane.z + 1.0 - clipBias; | ||
projectionMatrix.elements[ 14 ] = clipPlane.w; // Render | ||
projectionMatrix.elements[ 14 ] = clipPlane.w; | ||
// Render | ||
scope.visible = false; | ||
@@ -108,5 +116,3 @@ const currentRenderTarget = renderer.getRenderTarget(); | ||
renderer.xr.enabled = false; // Avoid camera modification | ||
renderer.shadowMap.autoUpdate = false; // Avoid re-computing shadows | ||
renderer.outputEncoding = THREE.LinearEncoding; | ||
@@ -123,6 +129,7 @@ renderer.toneMapping = THREE.NoToneMapping; | ||
renderer.toneMapping = currentToneMapping; | ||
renderer.setRenderTarget( currentRenderTarget ); // Restore viewport | ||
renderer.setRenderTarget( currentRenderTarget ); | ||
// Restore viewport | ||
const viewport = camera.viewport; | ||
if ( viewport !== undefined ) { | ||
@@ -154,3 +161,2 @@ | ||
} | ||
Reflector.ReflectorShader = { | ||
@@ -168,5 +174,3 @@ uniforms: { | ||
}, | ||
vertexShader: | ||
/* glsl */ | ||
` | ||
vertexShader: /* glsl */` | ||
uniform mat4 textureMatrix; | ||
@@ -187,5 +191,3 @@ varying vec4 vUv; | ||
}`, | ||
fragmentShader: | ||
/* glsl */ | ||
` | ||
fragmentShader: /* glsl */` | ||
uniform vec3 color; | ||
@@ -192,0 +194,0 @@ uniform sampler2D tDiffuse; |
@@ -19,4 +19,6 @@ ( function () { | ||
const vecTemp0 = new THREE.Vector3(); | ||
const vecTemp1 = new THREE.Vector3(); // | ||
const vecTemp1 = new THREE.Vector3(); | ||
// | ||
scope.needsUpdate = false; | ||
@@ -34,3 +36,2 @@ scope.maxDistance = ReflectorForSSRPass.ReflectorShader.uniforms.maxDistance.value; | ||
}, | ||
set( val ) { | ||
@@ -44,3 +45,2 @@ | ||
} | ||
} ); | ||
@@ -54,3 +54,2 @@ scope._fresnel = ReflectorForSSRPass.ReflectorShader.defines.FRESNEL; | ||
}, | ||
set( val ) { | ||
@@ -64,3 +63,2 @@ | ||
} | ||
} ); | ||
@@ -77,3 +75,2 @@ const normal = new THREE.Vector3(); | ||
let depthTexture; | ||
if ( useDepthTexture ) { | ||
@@ -105,3 +102,2 @@ | ||
material.uniforms[ 'textureMatrix' ].value = textureMatrix; | ||
if ( useDepthTexture ) { | ||
@@ -116,3 +112,2 @@ | ||
const globalPlanes = [ globalPlane ]; | ||
this.doRender = function ( renderer, scene, camera ) { | ||
@@ -132,4 +127,6 @@ | ||
normal.applyMatrix4( rotationMatrix ); | ||
view.subVectors( reflectorWorldPosition, cameraWorldPosition ); // Avoid rendering when reflector is facing away | ||
view.subVectors( reflectorWorldPosition, cameraWorldPosition ); | ||
// Avoid rendering when reflector is facing away | ||
if ( view.dot( normal ) > 0 ) return; | ||
@@ -159,9 +156,12 @@ view.reflect( normal ).negate(); | ||
material.uniforms[ 'virtualCameraProjectionMatrixInverse' ].value = camera.projectionMatrixInverse; | ||
material.uniforms[ 'resolution' ].value = scope.resolution; // Update the texture matrix | ||
material.uniforms[ 'resolution' ].value = scope.resolution; | ||
// Update the texture matrix | ||
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 ); | ||
textureMatrix.multiply( virtualCamera.projectionMatrix ); | ||
textureMatrix.multiply( virtualCamera.matrixWorldInverse ); | ||
textureMatrix.multiply( scope.matrixWorld ); // scope.visible = false; | ||
textureMatrix.multiply( scope.matrixWorld ); | ||
// scope.visible = false; | ||
const currentRenderTarget = renderer.getRenderTarget(); | ||
@@ -172,5 +172,3 @@ const currentXrEnabled = renderer.xr.enabled; | ||
renderer.xr.enabled = false; // Avoid camera modification | ||
renderer.shadowMap.autoUpdate = false; // Avoid re-computing shadows | ||
renderer.clippingPlanes = globalPlanes; | ||
@@ -185,6 +183,7 @@ renderer.setRenderTarget( renderTarget ); | ||
renderer.clippingPlanes = currentClippingPlanes; | ||
renderer.setRenderTarget( currentRenderTarget ); // Restore viewport | ||
renderer.setRenderTarget( currentRenderTarget ); | ||
// Restore viewport | ||
const viewport = camera.viewport; | ||
if ( viewport !== undefined ) { | ||
@@ -194,4 +193,6 @@ | ||
} // scope.visible = true; | ||
} | ||
// scope.visible = true; | ||
}; | ||
@@ -208,3 +209,2 @@ | ||
} | ||
ReflectorForSSRPass.ReflectorShader = { | ||
@@ -256,5 +256,3 @@ defines: { | ||
}, | ||
vertexShader: | ||
/* glsl */ | ||
` | ||
vertexShader: /* glsl */` | ||
uniform mat4 textureMatrix; | ||
@@ -270,5 +268,3 @@ varying vec4 vUv; | ||
}`, | ||
fragmentShader: | ||
/* glsl */ | ||
` | ||
fragmentShader: /* glsl */` | ||
uniform vec3 color; | ||
@@ -275,0 +271,0 @@ uniform sampler2D tDiffuse; |
@@ -17,16 +17,24 @@ ( function () { | ||
const shader = options.shader || Refractor.RefractorShader; | ||
const multisample = options.multisample !== undefined ? options.multisample : 4; // | ||
const multisample = options.multisample !== undefined ? options.multisample : 4; | ||
// | ||
const virtualCamera = this.camera; | ||
virtualCamera.matrixAutoUpdate = false; | ||
virtualCamera.userData.refractor = true; // | ||
virtualCamera.userData.refractor = true; | ||
// | ||
const refractorPlane = new THREE.Plane(); | ||
const textureMatrix = new THREE.Matrix4(); // render target | ||
const textureMatrix = new THREE.Matrix4(); | ||
// render target | ||
const renderTarget = new THREE.WebGLRenderTarget( textureWidth, textureHeight, { | ||
samples: multisample, | ||
type: THREE.HalfFloatType | ||
} ); // material | ||
} ); | ||
// material | ||
this.material = new THREE.ShaderMaterial( { | ||
@@ -37,8 +45,10 @@ uniforms: THREE.UniformsUtils.clone( shader.uniforms ), | ||
transparent: true // ensures, refractors are drawn from farthest to closest | ||
} ); | ||
} ); | ||
this.material.uniforms[ 'color' ].value = color; | ||
this.material.uniforms[ 'tDiffuse' ].value = renderTarget.texture; | ||
this.material.uniforms[ 'textureMatrix' ].value = textureMatrix; // functions | ||
this.material.uniforms[ 'textureMatrix' ].value = textureMatrix; | ||
// functions | ||
const visible = function () { | ||
@@ -64,3 +74,2 @@ | ||
}(); | ||
const updateRefractorPlane = function () { | ||
@@ -75,4 +84,6 @@ | ||
scope.matrixWorld.decompose( position, quaternion, scale ); | ||
normal.set( 0, 0, 1 ).applyQuaternion( quaternion ).normalize(); // flip the normal because we want to cull everything above the plane | ||
normal.set( 0, 0, 1 ).applyQuaternion( quaternion ).normalize(); | ||
// flip the normal because we want to cull everything above the plane | ||
normal.negate(); | ||
@@ -84,3 +95,2 @@ refractorPlane.setFromNormalAndCoplanarPoint( normal, position ); | ||
}(); | ||
const updateVirtualCamera = function () { | ||
@@ -97,2 +107,3 @@ | ||
virtualCamera.far = camera.far; // used in WebGLBackground | ||
// The following code creates an oblique view frustum for clipping. | ||
@@ -104,3 +115,5 @@ // see: Lengyel, Eric. “Oblique View Frustum Depth Projection and Clipping”. | ||
clipPlane.applyMatrix4( virtualCamera.matrixWorldInverse ); | ||
clipVector.set( clipPlane.normal.x, clipPlane.normal.y, clipPlane.normal.z, clipPlane.constant ); // calculate the clip-space corner point opposite the clipping plane and | ||
clipVector.set( clipPlane.normal.x, clipPlane.normal.y, clipPlane.normal.z, clipPlane.constant ); | ||
// calculate the clip-space corner point opposite the clipping plane and | ||
// transform it into camera space by multiplying it by the inverse of the projection matrix | ||
@@ -112,6 +125,10 @@ | ||
q.z = - 1.0; | ||
q.w = ( 1.0 + projectionMatrix.elements[ 10 ] ) / projectionMatrix.elements[ 14 ]; // calculate the scaled plane vector | ||
q.w = ( 1.0 + projectionMatrix.elements[ 10 ] ) / projectionMatrix.elements[ 14 ]; | ||
clipVector.multiplyScalar( 2.0 / clipVector.dot( q ) ); // replacing the third row of the projection matrix | ||
// calculate the scaled plane vector | ||
clipVector.multiplyScalar( 2.0 / clipVector.dot( q ) ); | ||
// replacing the third row of the projection matrix | ||
projectionMatrix.elements[ 2 ] = clipVector.x; | ||
@@ -124,10 +141,14 @@ projectionMatrix.elements[ 6 ] = clipVector.y; | ||
}(); // This will update the texture matrix that is used for projective texture mapping in the shader. | ||
}(); | ||
// This will update the texture matrix that is used for projective texture mapping in the shader. | ||
// see: http://developer.download.nvidia.com/assets/gamedev/docs/projective_texture_mapping.pdf | ||
function updateTextureMatrix( camera ) { | ||
// this matrix does range mapping to [ 0, 1 ] | ||
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 ); // we use "Object Linear Texgen", so we need to multiply the texture matrix T | ||
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 ); | ||
// we use "Object Linear Texgen", so we need to multiply the texture matrix T | ||
// (matrix above) with the projection and view matrix of the virtual camera | ||
@@ -140,4 +161,5 @@ // and the model matrix of the refractor | ||
} // | ||
} | ||
// | ||
@@ -153,5 +175,3 @@ function render( renderer, scene, camera ) { | ||
renderer.xr.enabled = false; // avoid camera modification | ||
renderer.shadowMap.autoUpdate = false; // avoid re-computing shadows | ||
renderer.outputEncoding = THREE.LinearEncoding; | ||
@@ -166,6 +186,7 @@ renderer.toneMapping = THREE.NoToneMapping; | ||
renderer.toneMapping = currentToneMapping; | ||
renderer.setRenderTarget( currentRenderTarget ); // restore viewport | ||
renderer.setRenderTarget( currentRenderTarget ); | ||
// restore viewport | ||
const viewport = camera.viewport; | ||
if ( viewport !== undefined ) { | ||
@@ -179,4 +200,5 @@ | ||
} // | ||
} | ||
// | ||
@@ -186,6 +208,11 @@ this.onBeforeRender = function ( renderer, scene, camera ) { | ||
// ensure refractors are rendered only once per frame | ||
if ( camera.userData.refractor === true ) return; // avoid rendering when the refractor is viewed from behind | ||
if ( ! visible( camera ) === true ) return; // update | ||
if ( camera.userData.refractor === true ) return; | ||
// avoid rendering when the refractor is viewed from behind | ||
if ( ! visible( camera ) === true ) return; | ||
// update | ||
updateRefractorPlane(); | ||
@@ -214,3 +241,2 @@ updateTextureMatrix( camera ); | ||
} | ||
Refractor.RefractorShader = { | ||
@@ -228,5 +254,3 @@ uniforms: { | ||
}, | ||
vertexShader: | ||
/* glsl */ | ||
` | ||
vertexShader: /* glsl */` | ||
@@ -243,5 +267,3 @@ uniform mat4 textureMatrix; | ||
}`, | ||
fragmentShader: | ||
/* glsl */ | ||
` | ||
fragmentShader: /* glsl */` | ||
@@ -248,0 +270,0 @@ uniform vec3 color; |
@@ -8,3 +8,2 @@ ( function () { | ||
const _shadowMatrix = new THREE.Matrix4(); | ||
class ShadowMesh extends THREE.Mesh { | ||
@@ -31,6 +30,6 @@ | ||
} | ||
update( plane, lightPosition4D ) { | ||
// based on https://www.opengl.org/archives/resources/features/StencilTalk/tsld021.htm | ||
const dot = plane.normal.x * lightPosition4D.x + plane.normal.y * lightPosition4D.y + plane.normal.z * lightPosition4D.z + - plane.constant * lightPosition4D.w; | ||
@@ -37,0 +36,0 @@ const sme = _shadowMatrix.elements; |
@@ -36,3 +36,2 @@ ( function () { | ||
} | ||
Sky.SkyShader = { | ||
@@ -59,5 +58,3 @@ uniforms: { | ||
}, | ||
vertexShader: | ||
/* glsl */ | ||
` | ||
vertexShader: /* glsl */` | ||
uniform vec3 sunPosition; | ||
@@ -133,5 +130,3 @@ uniform float rayleigh; | ||
}`, | ||
fragmentShader: | ||
/* glsl */ | ||
` | ||
fragmentShader: /* glsl */` | ||
varying vec3 vWorldPosition; | ||
@@ -138,0 +133,0 @@ varying vec3 vSunDirection; |
@@ -29,4 +29,6 @@ ( function () { | ||
const side = options.side !== undefined ? options.side : THREE.FrontSide; | ||
const fog = options.fog !== undefined ? options.fog : false; // | ||
const fog = options.fog !== undefined ? options.fog : false; | ||
// | ||
const mirrorPlane = new THREE.Plane(); | ||
@@ -81,5 +83,3 @@ const normal = new THREE.Vector3(); | ||
} ] ), | ||
vertexShader: | ||
/* glsl */ | ||
` | ||
vertexShader: /* glsl */` | ||
uniform mat4 textureMatrix; | ||
@@ -109,5 +109,3 @@ uniform float time; | ||
}`, | ||
fragmentShader: | ||
/* glsl */ | ||
` | ||
fragmentShader: /* glsl */` | ||
uniform sampler2D mirrorSampler; | ||
@@ -204,3 +202,2 @@ uniform float alpha; | ||
scope.material = material; | ||
scope.onBeforeRender = function ( renderer, scene, camera ) { | ||
@@ -213,4 +210,6 @@ | ||
normal.applyMatrix4( rotationMatrix ); | ||
view.subVectors( mirrorWorldPosition, cameraWorldPosition ); // Avoid rendering when mirror is facing away | ||
view.subVectors( mirrorWorldPosition, cameraWorldPosition ); | ||
// Avoid rendering when mirror is facing away | ||
if ( view.dot( normal ) > 0 ) return; | ||
@@ -234,9 +233,11 @@ view.reflect( normal ).negate(); | ||
mirrorCamera.updateMatrixWorld(); | ||
mirrorCamera.projectionMatrix.copy( camera.projectionMatrix ); // Update the texture matrix | ||
mirrorCamera.projectionMatrix.copy( camera.projectionMatrix ); | ||
// Update the texture matrix | ||
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 ); | ||
textureMatrix.multiply( mirrorCamera.projectionMatrix ); | ||
textureMatrix.multiply( mirrorCamera.matrixWorldInverse ); // Now update projection matrix with new clip plane, implementing code from: http://www.terathon.com/code/oblique.html | ||
textureMatrix.multiply( 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 | ||
mirrorPlane.setFromNormalAndCoplanarPoint( normal, mirrorWorldPosition ); | ||
@@ -249,6 +250,8 @@ mirrorPlane.applyMatrix4( mirrorCamera.matrixWorldInverse ); | ||
q.z = - 1.0; | ||
q.w = ( 1.0 + projectionMatrix.elements[ 10 ] ) / projectionMatrix.elements[ 14 ]; // Calculate the scaled plane vector | ||
q.w = ( 1.0 + projectionMatrix.elements[ 10 ] ) / projectionMatrix.elements[ 14 ]; | ||
clipPlane.multiplyScalar( 2.0 / clipPlane.dot( q ) ); // Replacing the third row of the projection matrix | ||
// Calculate the scaled plane vector | ||
clipPlane.multiplyScalar( 2.0 / clipPlane.dot( q ) ); | ||
// Replacing the third row of the projection matrix | ||
projectionMatrix.elements[ 2 ] = clipPlane.x; | ||
@@ -258,4 +261,6 @@ projectionMatrix.elements[ 6 ] = clipPlane.y; | ||
projectionMatrix.elements[ 14 ] = clipPlane.w; | ||
eye.setFromMatrixPosition( camera.matrixWorld ); // Render | ||
eye.setFromMatrixPosition( camera.matrixWorld ); | ||
// Render | ||
const currentRenderTarget = renderer.getRenderTarget(); | ||
@@ -266,3 +271,2 @@ const currentXrEnabled = renderer.xr.enabled; | ||
renderer.xr.enabled = false; // Avoid camera modification and recursion | ||
renderer.shadowMap.autoUpdate = false; // Avoid re-computing shadows | ||
@@ -278,6 +282,7 @@ | ||
renderer.shadowMap.autoUpdate = currentShadowAutoUpdate; | ||
renderer.setRenderTarget( currentRenderTarget ); // Restore viewport | ||
renderer.setRenderTarget( currentRenderTarget ); | ||
// Restore viewport | ||
const viewport = camera.viewport; | ||
if ( viewport !== undefined ) { | ||
@@ -284,0 +289,0 @@ |
@@ -32,7 +32,8 @@ ( function () { | ||
const cycle = 0.15; // a cycle of a flow map phase | ||
const halfCycle = cycle * 0.5; | ||
const textureMatrix = new THREE.Matrix4(); | ||
const clock = new THREE.Clock(); // internal components | ||
const clock = new THREE.Clock(); | ||
// internal components | ||
if ( THREE.Reflector === undefined ) { | ||
@@ -63,4 +64,6 @@ | ||
reflector.matrixAutoUpdate = false; | ||
refractor.matrixAutoUpdate = false; // material | ||
refractor.matrixAutoUpdate = false; | ||
// material | ||
this.material = new THREE.ShaderMaterial( { | ||
@@ -73,3 +76,2 @@ uniforms: THREE.UniformsUtils.merge( [ THREE.UniformsLib[ 'fog' ], shader.uniforms ] ), | ||
} ); | ||
if ( flowMap !== undefined ) { | ||
@@ -90,4 +92,5 @@ | ||
} // maps | ||
} | ||
// maps | ||
@@ -99,15 +102,17 @@ normalMap0.wrapS = normalMap0.wrapT = THREE.RepeatWrapping; | ||
this.material.uniforms[ 'tNormalMap0' ].value = normalMap0; | ||
this.material.uniforms[ 'tNormalMap1' ].value = normalMap1; // water | ||
this.material.uniforms[ 'tNormalMap1' ].value = normalMap1; | ||
// water | ||
this.material.uniforms[ 'color' ].value = color; | ||
this.material.uniforms[ 'reflectivity' ].value = reflectivity; | ||
this.material.uniforms[ 'textureMatrix' ].value = textureMatrix; // inital values | ||
this.material.uniforms[ 'textureMatrix' ].value = textureMatrix; | ||
// inital values | ||
this.material.uniforms[ 'config' ].value.x = 0; // flowMapOffset0 | ||
this.material.uniforms[ 'config' ].value.y = halfCycle; // flowMapOffset1 | ||
this.material.uniforms[ 'config' ].value.z = halfCycle; // halfCycle | ||
this.material.uniforms[ 'config' ].value.w = scale; // scale | ||
this.material.uniforms[ 'config' ].value.w = scale; // scale | ||
// functions | ||
@@ -129,4 +134,4 @@ | ||
config.value.x += flowSpeed * delta; // flowMapOffset0 | ||
config.value.y = config.value.x + halfCycle; // flowMapOffset1 | ||
config.value.y = config.value.x + halfCycle; // flowMapOffset1 | ||
// Important: The distance between offsets should be always the value of "halfCycle". | ||
@@ -147,4 +152,5 @@ // Moreover, both offsets should be in the range of [ 0, cycle ]. | ||
} // | ||
} | ||
// | ||
@@ -167,3 +173,2 @@ this.onBeforeRender = function ( renderer, scene, camera ) { | ||
} | ||
Water.WaterShader = { | ||
@@ -204,5 +209,3 @@ uniforms: { | ||
}, | ||
vertexShader: | ||
/* glsl */ | ||
` | ||
vertexShader: /* glsl */` | ||
@@ -234,5 +237,3 @@ #include <common> | ||
}`, | ||
fragmentShader: | ||
/* glsl */ | ||
` | ||
fragmentShader: /* glsl */` | ||
@@ -239,0 +240,0 @@ #include <common> |
@@ -21,8 +21,12 @@ ( function () { | ||
world.setGravity( new AmmoLib.btVector3( 0, - 9.8, 0 ) ); | ||
const worldTransform = new AmmoLib.btTransform(); // | ||
const worldTransform = new AmmoLib.btTransform(); | ||
// | ||
function getShape( geometry ) { | ||
const parameters = geometry.parameters; // TODO change type to is* | ||
const parameters = geometry.parameters; | ||
// TODO change type to is* | ||
if ( geometry.type === 'BoxGeometry' ) { | ||
@@ -52,7 +56,5 @@ | ||
const meshMap = new WeakMap(); | ||
function addMesh( mesh, mass = 0 ) { | ||
const shape = getShape( mesh.geometry ); | ||
if ( shape !== null ) { | ||
@@ -86,6 +88,5 @@ | ||
const rbInfo = new AmmoLib.btRigidBodyConstructionInfo( mass, motionState, shape, localInertia ); | ||
const body = new AmmoLib.btRigidBody( rbInfo ); // body.setFriction( 4 ); | ||
const body = new AmmoLib.btRigidBody( rbInfo ); | ||
// body.setFriction( 4 ); | ||
world.addRigidBody( body ); | ||
if ( mass > 0 ) { | ||
@@ -104,3 +105,2 @@ | ||
const bodies = []; | ||
for ( let i = 0; i < mesh.count; i ++ ) { | ||
@@ -128,4 +128,5 @@ | ||
} // | ||
} | ||
// | ||
@@ -155,25 +156,27 @@ function setMeshPosition( mesh, position, index = 0 ) { | ||
} // | ||
} | ||
// | ||
let lastTime = 0; | ||
function step() { | ||
const time = performance.now(); | ||
if ( lastTime > 0 ) { | ||
const delta = ( time - lastTime ) / 1000; // console.time( 'world.step' ); | ||
const delta = ( time - lastTime ) / 1000; | ||
world.stepSimulation( delta, 10 ); // console.timeEnd( 'world.step' ); | ||
// console.time( 'world.step' ); | ||
world.stepSimulation( delta, 10 ); | ||
// console.timeEnd( 'world.step' ); | ||
} | ||
lastTime = time; // | ||
lastTime = time; | ||
// | ||
for ( let i = 0, l = meshes.length; i < l; i ++ ) { | ||
const mesh = meshes[ i ]; | ||
if ( mesh.isInstancedMesh ) { | ||
@@ -183,3 +186,2 @@ | ||
const bodies = meshMap.get( mesh ); | ||
for ( let j = 0; j < bodies.length; j ++ ) { | ||
@@ -212,4 +214,5 @@ | ||
} // animate | ||
} | ||
// animate | ||
@@ -219,4 +222,4 @@ setInterval( step, 1000 / frameRate ); | ||
addMesh: addMesh, | ||
setMeshPosition: setMeshPosition // addCompoundMesh | ||
setMeshPosition: setMeshPosition | ||
// addCompoundMesh | ||
}; | ||
@@ -223,0 +226,0 @@ |
@@ -6,8 +6,12 @@ ( function () { | ||
const frameRate = 60; | ||
const world = new OIMO.World( 2, new OIMO.Vec3( 0, - 9.8, 0 ) ); // | ||
const world = new OIMO.World( 2, new OIMO.Vec3( 0, - 9.8, 0 ) ); | ||
// | ||
function getShape( geometry ) { | ||
const parameters = geometry.parameters; // TODO change type to is* | ||
const parameters = geometry.parameters; | ||
// TODO change type to is* | ||
if ( geometry.type === 'BoxGeometry' ) { | ||
@@ -33,7 +37,5 @@ | ||
const meshMap = new WeakMap(); | ||
function addMesh( mesh, mass = 0 ) { | ||
const shape = getShape( mesh.geometry ); | ||
if ( shape !== null ) { | ||
@@ -65,3 +67,2 @@ | ||
world.addRigidBody( body ); | ||
if ( mass > 0 ) { | ||
@@ -80,3 +81,2 @@ | ||
const bodies = []; | ||
for ( let i = 0; i < mesh.count; i ++ ) { | ||
@@ -104,4 +104,5 @@ | ||
} // | ||
} | ||
// | ||
@@ -123,24 +124,25 @@ function setMeshPosition( mesh, position, index = 0 ) { | ||
} // | ||
} | ||
// | ||
let lastTime = 0; | ||
function step() { | ||
const time = performance.now(); | ||
if ( lastTime > 0 ) { | ||
// console.time( 'world.step' ); | ||
world.step( 1 / frameRate ); // console.timeEnd( 'world.step' ); | ||
world.step( 1 / frameRate ); | ||
// console.timeEnd( 'world.step' ); | ||
} | ||
lastTime = time; // | ||
lastTime = time; | ||
// | ||
for ( let i = 0, l = meshes.length; i < l; i ++ ) { | ||
const mesh = meshes[ i ]; | ||
if ( mesh.isInstancedMesh ) { | ||
@@ -150,3 +152,2 @@ | ||
const bodies = meshMap.get( mesh ); | ||
for ( let j = 0; j < bodies.length; j ++ ) { | ||
@@ -171,4 +172,5 @@ | ||
} // animate | ||
} | ||
// animate | ||
@@ -178,4 +180,4 @@ setInterval( step, 1000 / frameRate ); | ||
addMesh: addMesh, | ||
setMeshPosition: setMeshPosition // addCompoundMesh | ||
setMeshPosition: setMeshPosition | ||
// addCompoundMesh | ||
}; | ||
@@ -182,0 +184,0 @@ |
@@ -111,7 +111,4 @@ ( function () { | ||
} | ||
render( renderer, writeBuffer, readBuffer, deltaTime /*, maskActive*/ ) { | ||
render( renderer, writeBuffer, readBuffer, deltaTime | ||
/*, maskActive*/ | ||
) { | ||
if ( this.needsInit ) { | ||
@@ -133,5 +130,6 @@ | ||
renderer.setRenderTarget( this.currentLuminanceRT ); | ||
this.fsQuad.render( renderer ); //Use the new luminance values, the previous luminance and the frame delta to | ||
this.fsQuad.render( renderer ); | ||
//Use the new luminance values, the previous luminance and the frame delta to | ||
//adapt the luminance over time. | ||
this.fsQuad.material = this.materialAdaptiveLum; | ||
@@ -142,4 +140,5 @@ this.materialAdaptiveLum.uniforms.delta.value = deltaTime; | ||
renderer.setRenderTarget( this.luminanceRT ); | ||
this.fsQuad.render( renderer ); //Copy the new adapted luminance value so that it can be used by the next frame. | ||
this.fsQuad.render( renderer ); | ||
//Copy the new adapted luminance value so that it can be used by the next frame. | ||
this.fsQuad.material = this.materialCopy; | ||
@@ -154,3 +153,2 @@ this.copyUniforms.tDiffuse.value = this.luminanceRT.texture; | ||
this.materialToneMap.uniforms.tDiffuse.value = readBuffer.texture; | ||
if ( this.renderToScreen ) { | ||
@@ -170,3 +168,2 @@ | ||
} | ||
reset() { | ||
@@ -198,4 +195,6 @@ | ||
this.previousLuminanceRT.texture.name = 'AdaptiveToneMappingPass.pl'; | ||
this.previousLuminanceRT.texture.generateMipmaps = false; // We only need mipmapping for the current luminosity because we want a down-sampled version to sample in our adaptive shader | ||
this.previousLuminanceRT.texture.generateMipmaps = false; | ||
// We only need mipmapping for the current luminosity because we want a down-sampled version to sample in our adaptive shader | ||
const pars = { | ||
@@ -207,3 +206,2 @@ minFilter: THREE.LinearMipmapLinearFilter, | ||
this.currentLuminanceRT.texture.name = 'AdaptiveToneMappingPass.cl'; | ||
if ( this.adaptive ) { | ||
@@ -214,5 +212,5 @@ | ||
} //Put something in the adaptive luminance texture so that the scene can render initially | ||
} | ||
//Put something in the adaptive luminance texture so that the scene can render initially | ||
this.fsQuad.material = new THREE.MeshBasicMaterial( { | ||
@@ -223,3 +221,4 @@ color: 0x777777 | ||
this.materialAdaptiveLum.needsUpdate = true; | ||
this.materialToneMap.needsUpdate = true; // renderer.render( this.scene, this.camera, this.luminanceRT ); | ||
this.materialToneMap.needsUpdate = true; | ||
// renderer.render( this.scene, this.camera, this.luminanceRT ); | ||
// renderer.render( this.scene, this.camera, this.previousLuminanceRT ); | ||
@@ -249,3 +248,2 @@ // renderer.render( this.scene, this.camera, this.currentLuminanceRT ); | ||
} | ||
setAdaptionRate( rate ) { | ||
@@ -260,3 +258,2 @@ | ||
} | ||
setMinLuminance( minLum ) { | ||
@@ -272,3 +269,2 @@ | ||
} | ||
setMaxLuminance( maxLum ) { | ||
@@ -283,3 +279,2 @@ | ||
} | ||
setAverageLuminance( avgLum ) { | ||
@@ -294,3 +289,2 @@ | ||
} | ||
setMiddleGrey( middleGrey ) { | ||
@@ -305,3 +299,2 @@ | ||
} | ||
dispose() { | ||
@@ -308,0 +301,0 @@ |
@@ -18,3 +18,3 @@ ( function () { | ||
} ); | ||
this.shaderMaterial = new THREE.ShaderMaterial( { | ||
this.compFsMaterial = new THREE.ShaderMaterial( { | ||
uniforms: this.uniforms, | ||
@@ -24,12 +24,9 @@ vertexShader: this.shader.vertexShader, | ||
} ); | ||
this.compFsQuad = new THREE.FullScreenQuad( this.shaderMaterial ); | ||
const material = new THREE.MeshBasicMaterial(); | ||
this.copyFsQuad = new THREE.FullScreenQuad( material ); | ||
this.compFsQuad = new THREE.FullScreenQuad( this.compFsMaterial ); | ||
this.copyFsMaterial = new THREE.MeshBasicMaterial(); | ||
this.copyFsQuad = new THREE.FullScreenQuad( this.copyFsMaterial ); | ||
} | ||
render( renderer, writeBuffer, readBuffer /*, deltaTime, maskActive*/ ) { | ||
render( renderer, writeBuffer, readBuffer | ||
/*, deltaTime, maskActive*/ | ||
) { | ||
this.uniforms[ 'tOld' ].value = this.textureOld.texture; | ||
@@ -40,3 +37,2 @@ this.uniforms[ 'tNew' ].value = readBuffer.texture; | ||
this.copyFsQuad.material.map = this.textureComp.texture; | ||
if ( this.renderToScreen ) { | ||
@@ -53,8 +49,9 @@ | ||
} // Swap buffers. | ||
} | ||
// Swap buffers. | ||
const temp = this.textureOld; | ||
this.textureOld = this.textureComp; | ||
this.textureComp = temp; // Now textureOld contains the latest image, ready for the next frame. | ||
this.textureComp = temp; | ||
// Now textureOld contains the latest image, ready for the next frame. | ||
@@ -69,3 +66,13 @@ } | ||
} | ||
dispose() { | ||
this.textureComp.dispose(); | ||
this.textureOld.dispose(); | ||
this.compFsMaterial.dispose(); | ||
this.copyFsMaterial.dispose(); | ||
this.compFsQuad.dispose(); | ||
this.copyFsQuad.dispose(); | ||
} | ||
} | ||
@@ -72,0 +79,0 @@ |
@@ -5,11 +5,15 @@ ( function () { | ||
constructor( strength = 1, kernelSize = 25, sigma = 4, resolution = 256 ) { | ||
constructor( strength = 1, kernelSize = 25, sigma = 4 ) { | ||
super(); // render targets | ||
super(); | ||
this.renderTargetX = new THREE.WebGLRenderTarget( resolution, resolution ); | ||
// render targets | ||
this.renderTargetX = new THREE.WebGLRenderTarget(); // will be resized later | ||
this.renderTargetX.texture.name = 'BloomPass.x'; | ||
this.renderTargetY = new THREE.WebGLRenderTarget( resolution, resolution ); | ||
this.renderTargetY.texture.name = 'BloomPass.y'; // combine material | ||
this.renderTargetY = new THREE.WebGLRenderTarget(); // will be resized later | ||
this.renderTargetY.texture.name = 'BloomPass.y'; | ||
// combine material | ||
this.combineUniforms = THREE.UniformsUtils.clone( CombineShader.uniforms ); | ||
@@ -23,4 +27,6 @@ this.combineUniforms[ 'strength' ].value = strength; | ||
transparent: true | ||
} ); // convolution material | ||
} ); | ||
// convolution material | ||
if ( THREE.ConvolutionShader === undefined ) console.error( 'THREE.BloomPass relies on THREE.ConvolutionShader' ); | ||
@@ -44,7 +50,8 @@ const convolutionShader = THREE.ConvolutionShader; | ||
} | ||
render( renderer, writeBuffer, readBuffer, deltaTime, maskActive ) { | ||
if ( maskActive ) renderer.state.buffers.stencil.setTest( false ); // Render quad with blured scene into texture (convolution pass 1) | ||
if ( maskActive ) renderer.state.buffers.stencil.setTest( false ); | ||
// Render quad with blured scene into texture (convolution pass 1) | ||
this.fsQuad.material = this.materialConvolution; | ||
@@ -55,4 +62,6 @@ this.convolutionUniforms[ 'tDiffuse' ].value = readBuffer.texture; | ||
renderer.clear(); | ||
this.fsQuad.render( renderer ); // Render quad with blured scene into texture (convolution pass 2) | ||
this.fsQuad.render( renderer ); | ||
// Render quad with blured scene into texture (convolution pass 2) | ||
this.convolutionUniforms[ 'tDiffuse' ].value = this.renderTargetX.texture; | ||
@@ -62,4 +71,6 @@ this.convolutionUniforms[ 'uImageIncrement' ].value = BloomPass.blurY; | ||
renderer.clear(); | ||
this.fsQuad.render( renderer ); // Render original scene with superimposed blur to texture | ||
this.fsQuad.render( renderer ); | ||
// Render original scene with superimposed blur to texture | ||
this.fsQuad.material = this.materialCombine; | ||
@@ -73,5 +84,19 @@ this.combineUniforms[ 'tDiffuse' ].value = this.renderTargetY.texture; | ||
} | ||
setSize( width, height ) { | ||
this.renderTargetX.setSize( width, height ); | ||
this.renderTargetY.setSize( width, height ); | ||
} | ||
dispose() { | ||
this.renderTargetX.dispose(); | ||
this.renderTargetY.dispose(); | ||
this.materialCombine.dispose(); | ||
this.materialConvolution.dispose(); | ||
this.fsQuad.dispose(); | ||
} | ||
} | ||
const CombineShader = { | ||
@@ -86,5 +111,3 @@ uniforms: { | ||
}, | ||
vertexShader: | ||
/* glsl */ | ||
` | ||
vertexShader: /* glsl */` | ||
@@ -99,5 +122,3 @@ varying vec2 vUv; | ||
}`, | ||
fragmentShader: | ||
/* glsl */ | ||
` | ||
fragmentShader: /* glsl */` | ||
@@ -104,0 +125,0 @@ uniform float strength; |
@@ -17,16 +17,21 @@ ( function () { | ||
const aperture = params.aperture !== undefined ? params.aperture : 0.025; | ||
const maxblur = params.maxblur !== undefined ? params.maxblur : 1.0; // render targets | ||
const maxblur = params.maxblur !== undefined ? params.maxblur : 1.0; | ||
const width = params.width || window.innerWidth || 1; | ||
const height = params.height || window.innerHeight || 1; | ||
this.renderTargetDepth = new THREE.WebGLRenderTarget( width, height, { | ||
// render targets | ||
this.renderTargetDepth = new THREE.WebGLRenderTarget( 1, 1, { | ||
// will be resized later | ||
minFilter: THREE.NearestFilter, | ||
magFilter: THREE.NearestFilter | ||
} ); | ||
this.renderTargetDepth.texture.name = 'BokehPass.depth'; // depth material | ||
this.renderTargetDepth.texture.name = 'BokehPass.depth'; | ||
// depth material | ||
this.materialDepth = new THREE.MeshDepthMaterial(); | ||
this.materialDepth.depthPacking = THREE.RGBADepthPacking; | ||
this.materialDepth.blending = THREE.NoBlending; // bokeh material | ||
this.materialDepth.blending = THREE.NoBlending; | ||
// bokeh material | ||
if ( THREE.BokehShader === undefined ) { | ||
@@ -59,8 +64,6 @@ | ||
} | ||
render( renderer, writeBuffer, readBuffer /*, deltaTime, maskActive*/ ) { | ||
render( renderer, writeBuffer, readBuffer | ||
/*, deltaTime, maskActive*/ | ||
) { | ||
// Render depth into texture | ||
// Render depth into texture | ||
this.scene.overrideMaterial = this.materialDepth; | ||
@@ -75,8 +78,9 @@ renderer.getClearColor( this._oldClearColor ); | ||
renderer.clear(); | ||
renderer.render( this.scene, this.camera ); // Render bokeh composite | ||
renderer.render( this.scene, this.camera ); | ||
// Render bokeh composite | ||
this.uniforms[ 'tColor' ].value = readBuffer.texture; | ||
this.uniforms[ 'nearClip' ].value = this.camera.near; | ||
this.uniforms[ 'farClip' ].value = this.camera.far; | ||
if ( this.renderToScreen ) { | ||
@@ -101,3 +105,16 @@ | ||
} | ||
setSize( width, height ) { | ||
this.renderTargetDepth.setSize( width, height ); | ||
} | ||
dispose() { | ||
this.renderTargetDepth.dispose(); | ||
this.materialDepth.dispose(); | ||
this.materialBokeh.dispose(); | ||
this.fsQuad.dispose(); | ||
} | ||
} | ||
@@ -104,0 +121,0 @@ |
@@ -14,9 +14,5 @@ ( function () { | ||
} | ||
render( renderer, writeBuffer, readBuffer /*, deltaTime, maskActive */ ) { | ||
render( renderer, writeBuffer, readBuffer | ||
/*, deltaTime, maskActive */ | ||
) { | ||
let oldClearAlpha; | ||
if ( this.clearColor ) { | ||
@@ -32,3 +28,2 @@ | ||
renderer.clear(); | ||
if ( this.clearColor ) { | ||
@@ -35,0 +30,0 @@ |
@@ -5,3 +5,3 @@ ( function () { | ||
constructor( camera, envMap, opacity = 1 ) { | ||
constructor( camera, tCube, opacity = 1 ) { | ||
@@ -23,7 +23,7 @@ super(); | ||
return this.uniforms.envMap.value; | ||
return this.uniforms.tCube.value; | ||
} | ||
} ); | ||
this.envMap = envMap; | ||
this.tCube = tCube; | ||
this.opacity = opacity; | ||
@@ -35,7 +35,4 @@ this.cubeScene = new THREE.Scene(); | ||
} | ||
render( renderer, writeBuffer, readBuffer /*, deltaTime, maskActive*/ ) { | ||
render( renderer, writeBuffer, readBuffer | ||
/*, deltaTime, maskActive*/ | ||
) { | ||
const oldAutoClear = renderer.autoClear; | ||
@@ -45,4 +42,4 @@ renderer.autoClear = false; | ||
this.cubeCamera.quaternion.setFromRotationMatrix( this.camera.matrixWorld ); | ||
this.cubeMesh.material.uniforms.envMap.value = this.envMap; | ||
this.cubeMesh.material.uniforms.flipEnvMap.value = this.envMap.isCubeTexture && this.envMap.isRenderTargetTexture === false ? - 1 : 1; | ||
this.cubeMesh.material.uniforms.tCube.value = this.tCube; | ||
this.cubeMesh.material.uniforms.tFlip.value = this.tCube.isCubeTexture && this.tCube.isRenderTargetTexture === false ? - 1 : 1; | ||
this.cubeMesh.material.uniforms.opacity.value = this.opacity; | ||
@@ -56,3 +53,9 @@ this.cubeMesh.material.transparent = this.opacity < 1.0; | ||
} | ||
dispose() { | ||
this.cubeMesh.geometry.dispose(); | ||
this.cubeMesh.material.dispose(); | ||
} | ||
} | ||
@@ -59,0 +62,0 @@ |
@@ -22,10 +22,6 @@ ( function () { | ||
} | ||
render( renderer, writeBuffer, readBuffer /*, deltaTime, maskActive */ ) { | ||
render( renderer, writeBuffer, readBuffer | ||
/*, deltaTime, maskActive */ | ||
) { | ||
this.uniforms[ 'tDiffuse' ].value = readBuffer.texture; | ||
this.uniforms[ 'tSize' ].value.set( readBuffer.width, readBuffer.height ); | ||
if ( this.renderToScreen ) { | ||
@@ -45,3 +41,9 @@ | ||
} | ||
dispose() { | ||
this.material.dispose(); | ||
this.fsQuad.dispose(); | ||
} | ||
} | ||
@@ -48,0 +50,0 @@ |
@@ -8,3 +8,2 @@ ( function () { | ||
this.renderer = renderer; | ||
if ( renderTarget === undefined ) { | ||
@@ -33,4 +32,6 @@ | ||
this.renderToScreen = true; | ||
this.passes = []; // dependencies | ||
this.passes = []; | ||
// dependencies | ||
if ( THREE.CopyShader === undefined ) { | ||
@@ -52,3 +53,2 @@ | ||
} | ||
swapBuffers() { | ||
@@ -61,3 +61,2 @@ | ||
} | ||
addPass( pass ) { | ||
@@ -69,3 +68,2 @@ | ||
} | ||
insertPass( pass, index ) { | ||
@@ -77,7 +75,5 @@ | ||
} | ||
removePass( pass ) { | ||
const index = this.passes.indexOf( pass ); | ||
if ( index !== - 1 ) { | ||
@@ -90,3 +86,2 @@ | ||
} | ||
isLastEnabledPass( passIndex ) { | ||
@@ -107,6 +102,6 @@ | ||
} | ||
render( deltaTime ) { | ||
// deltaTime value is in seconds | ||
if ( deltaTime === undefined ) { | ||
@@ -120,3 +115,2 @@ | ||
let maskActive = false; | ||
for ( let i = 0, il = this.passes.length; i < il; i ++ ) { | ||
@@ -128,3 +122,2 @@ | ||
pass.render( this.renderer, this.writeBuffer, this.readBuffer, deltaTime, maskActive ); | ||
if ( pass.needsSwap ) { | ||
@@ -135,7 +128,9 @@ | ||
const context = this.renderer.getContext(); | ||
const stencil = this.renderer.state.buffers.stencil; //context.stencilFunc( context.NOTEQUAL, 1, 0xffffffff ); | ||
const stencil = this.renderer.state.buffers.stencil; | ||
//context.stencilFunc( context.NOTEQUAL, 1, 0xffffffff ); | ||
stencil.setFunc( context.NOTEQUAL, 1, 0xffffffff ); | ||
this.copyPass.render( this.renderer, this.writeBuffer, this.readBuffer, deltaTime ); //context.stencilFunc( context.EQUAL, 1, 0xffffffff ); | ||
this.copyPass.render( this.renderer, this.writeBuffer, this.readBuffer, deltaTime ); | ||
//context.stencilFunc( context.EQUAL, 1, 0xffffffff ); | ||
stencil.setFunc( context.EQUAL, 1, 0xffffffff ); | ||
@@ -168,3 +163,2 @@ | ||
} | ||
reset( renderTarget ) { | ||
@@ -191,3 +185,2 @@ | ||
} | ||
setSize( width, height ) { | ||
@@ -201,3 +194,2 @@ | ||
this.renderTarget2.setSize( effectiveWidth, effectiveHeight ); | ||
for ( let i = 0; i < this.passes.length; i ++ ) { | ||
@@ -210,3 +202,2 @@ | ||
} | ||
setPixelRatio( pixelRatio ) { | ||
@@ -218,5 +209,11 @@ | ||
} | ||
dispose() { | ||
this.renderTarget1.dispose(); | ||
this.renderTarget2.dispose(); | ||
this.copyPass.dispose(); | ||
} | ||
} | ||
class Pass { | ||
@@ -227,14 +224,15 @@ | ||
// if set to true, the pass is processed by the composer | ||
this.enabled = true; // if set to true, the pass indicates to swap read and write buffer after rendering | ||
this.enabled = true; | ||
this.needsSwap = true; // if set to true, the pass clears its buffer before rendering | ||
// if set to true, the pass indicates to swap read and write buffer after rendering | ||
this.needsSwap = true; | ||
this.clear = false; // if set to true, the result of the pass is rendered to screen. This is set automatically by EffectComposer. | ||
// if set to true, the pass clears its buffer before rendering | ||
this.clear = false; | ||
// if set to true, the result of the pass is rendered to screen. This is set automatically by EffectComposer. | ||
this.renderToScreen = false; | ||
} | ||
setSize() {} | ||
render() { | ||
@@ -246,14 +244,13 @@ | ||
} // Helper for passes that need to fill the viewport with a single quad. | ||
} | ||
// Helper for passes that need to fill the viewport with a single quad. | ||
const _camera = new THREE.OrthographicCamera( - 1, 1, 1, - 1, 0, 1 ); // https://github.com/mrdoob/three.js/pull/21358 | ||
const _camera = new THREE.OrthographicCamera( - 1, 1, 1, - 1, 0, 1 ); | ||
// https://github.com/mrdoob/three.js/pull/21358 | ||
const _geometry = new THREE.BufferGeometry(); | ||
_geometry.setAttribute( 'position', new THREE.Float32BufferAttribute( [ - 1, 3, 0, - 1, - 1, 0, 3, - 1, 0 ], 3 ) ); | ||
_geometry.setAttribute( 'uv', new THREE.Float32BufferAttribute( [ 0, 2, 0, 0, 2, 0 ], 2 ) ); | ||
class FullScreenQuad { | ||
@@ -266,3 +263,2 @@ | ||
} | ||
dispose() { | ||
@@ -273,3 +269,2 @@ | ||
} | ||
render( renderer ) { | ||
@@ -280,3 +275,2 @@ | ||
} | ||
get material() { | ||
@@ -287,3 +281,2 @@ | ||
} | ||
set material( value ) { | ||
@@ -290,0 +283,0 @@ |
@@ -23,10 +23,6 @@ ( function () { | ||
} | ||
render( renderer, writeBuffer, readBuffer, deltaTime /*, maskActive */ ) { | ||
render( renderer, writeBuffer, readBuffer, deltaTime | ||
/*, maskActive */ | ||
) { | ||
this.uniforms[ 'tDiffuse' ].value = readBuffer.texture; | ||
this.uniforms[ 'time' ].value += deltaTime; | ||
if ( this.renderToScreen ) { | ||
@@ -46,3 +42,9 @@ | ||
} | ||
dispose() { | ||
this.material.dispose(); | ||
this.fsQuad.dispose(); | ||
} | ||
} | ||
@@ -49,0 +51,0 @@ |
@@ -11,3 +11,4 @@ ( function () { | ||
this.uniforms = THREE.UniformsUtils.clone( shader.uniforms ); | ||
this.uniforms[ 'tDisp' ].value = this.generateHeightmap( dt_size ); | ||
this.heightMap = this.generateHeightmap( dt_size ); | ||
this.uniforms[ 'tDisp' ].value = this.heightMap; | ||
this.material = new THREE.ShaderMaterial( { | ||
@@ -24,13 +25,8 @@ uniforms: this.uniforms, | ||
} | ||
render( renderer, writeBuffer, readBuffer /*, deltaTime, maskActive */ ) { | ||
render( renderer, writeBuffer, readBuffer | ||
/*, deltaTime, maskActive */ | ||
) { | ||
if ( renderer.capabilities.isWebGL2 === false ) this.uniforms[ 'tDisp' ].value.format = THREE.LuminanceFormat; | ||
this.uniforms[ 'tDiffuse' ].value = readBuffer.texture; | ||
this.uniforms[ 'seed' ].value = Math.random(); //default seeding | ||
this.uniforms[ 'byp' ].value = 0; | ||
if ( this.curF % this.randX == 0 || this.goWild == true ) { | ||
@@ -63,3 +59,2 @@ | ||
this.curF ++; | ||
if ( this.renderToScreen ) { | ||
@@ -79,3 +74,2 @@ | ||
} | ||
generateTrigger() { | ||
@@ -86,3 +80,2 @@ | ||
} | ||
generateHeightmap( dt_size ) { | ||
@@ -92,3 +85,2 @@ | ||
const length = dt_size * dt_size; | ||
for ( let i = 0; i < length; i ++ ) { | ||
@@ -106,3 +98,10 @@ | ||
} | ||
dispose() { | ||
this.material.dispose(); | ||
this.heightMap.dispose(); | ||
this.fsQuad.dispose(); | ||
} | ||
} | ||
@@ -109,0 +108,0 @@ |
@@ -12,3 +12,2 @@ ( function () { | ||
super(); | ||
if ( THREE.HalftoneShader === undefined ) { | ||
@@ -25,7 +24,7 @@ | ||
vertexShader: THREE.HalftoneShader.vertexShader | ||
} ); // set params | ||
} ); | ||
// set params | ||
this.uniforms.width.value = width; | ||
this.uniforms.height.value = height; | ||
for ( const key in params ) { | ||
@@ -44,9 +43,5 @@ | ||
} | ||
render( renderer, writeBuffer, readBuffer /*, deltaTime, maskActive*/ ) { | ||
render( renderer, writeBuffer, readBuffer | ||
/*, deltaTime, maskActive*/ | ||
) { | ||
this.material.uniforms[ 'tDiffuse' ].value = readBuffer.texture; | ||
if ( this.renderToScreen ) { | ||
@@ -66,3 +61,2 @@ | ||
} | ||
setSize( width, height ) { | ||
@@ -74,3 +68,9 @@ | ||
} | ||
dispose() { | ||
this.material.dispose(); | ||
this.fsQuad.dispose(); | ||
} | ||
} | ||
@@ -77,0 +77,0 @@ |
@@ -24,5 +24,3 @@ ( function () { | ||
}, | ||
vertexShader: | ||
/* glsl */ | ||
` | ||
vertexShader: /* glsl */` | ||
@@ -39,5 +37,3 @@ varying vec2 vUv; | ||
`, | ||
fragmentShader: | ||
/* glsl */ | ||
` | ||
fragmentShader: /* glsl */` | ||
@@ -115,3 +111,2 @@ uniform float lutSize; | ||
}; | ||
class LUTPass extends THREE.ShaderPass { | ||
@@ -122,3 +117,2 @@ | ||
const material = this.material; | ||
if ( v !== this.lut ) { | ||
@@ -128,7 +122,5 @@ | ||
material.uniforms.lut.value = null; | ||
if ( v ) { | ||
const is3dTextureDefine = v.isData3DTexture ? 1 : 0; | ||
if ( is3dTextureDefine !== material.defines.USE_3DTEXTURE ) { | ||
@@ -142,3 +134,2 @@ | ||
material.uniforms.lutSize.value = v.image.width; | ||
if ( v.isData3DTexture ) { | ||
@@ -159,3 +150,2 @@ | ||
} | ||
get lut() { | ||
@@ -166,3 +156,2 @@ | ||
} | ||
set intensity( v ) { | ||
@@ -173,3 +162,2 @@ | ||
} | ||
get intensity() { | ||
@@ -180,3 +168,2 @@ | ||
} | ||
constructor( options = {} ) { | ||
@@ -183,0 +170,0 @@ |
@@ -15,18 +15,20 @@ ( function () { | ||
} | ||
render( renderer, writeBuffer, readBuffer /*, deltaTime, maskActive */ ) { | ||
render( renderer, writeBuffer, readBuffer | ||
/*, deltaTime, maskActive */ | ||
) { | ||
const context = renderer.getContext(); | ||
const state = renderer.state; // don't update color or depth | ||
const state = renderer.state; | ||
// don't update color or depth | ||
state.buffers.color.setMask( false ); | ||
state.buffers.depth.setMask( false ); // lock buffers | ||
state.buffers.depth.setMask( false ); | ||
// lock buffers | ||
state.buffers.color.setLocked( true ); | ||
state.buffers.depth.setLocked( true ); // set up stencil | ||
state.buffers.depth.setLocked( true ); | ||
// set up stencil | ||
let writeValue, clearValue; | ||
if ( this.inverse ) { | ||
@@ -48,4 +50,6 @@ | ||
state.buffers.stencil.setClear( clearValue ); | ||
state.buffers.stencil.setLocked( true ); // draw into the stencil buffer | ||
state.buffers.stencil.setLocked( true ); | ||
// draw into the stencil buffer | ||
renderer.setRenderTarget( readBuffer ); | ||
@@ -56,10 +60,13 @@ if ( this.clear ) renderer.clear(); | ||
if ( this.clear ) renderer.clear(); | ||
renderer.render( this.scene, this.camera ); // unlock color and depth buffer for subsequent rendering | ||
renderer.render( this.scene, this.camera ); | ||
// unlock color and depth buffer for subsequent rendering | ||
state.buffers.color.setLocked( false ); | ||
state.buffers.depth.setLocked( false ); // only render where stencil is set to 1 | ||
state.buffers.depth.setLocked( false ); | ||
// only render where stencil is set to 1 | ||
state.buffers.stencil.setLocked( false ); | ||
state.buffers.stencil.setFunc( context.EQUAL, 1, 0xffffffff ); // draw if == 1 | ||
state.buffers.stencil.setOp( context.KEEP, context.KEEP, context.KEEP ); | ||
@@ -71,3 +78,2 @@ state.buffers.stencil.setLocked( true ); | ||
} | ||
class ClearMaskPass extends THREE.Pass { | ||
@@ -81,7 +87,4 @@ | ||
} | ||
render( renderer /*, writeBuffer, readBuffer, deltaTime, maskActive */ ) { | ||
render( renderer | ||
/*, writeBuffer, readBuffer, deltaTime, maskActive */ | ||
) { | ||
renderer.state.buffers.stencil.setLocked( false ); | ||
@@ -88,0 +91,0 @@ renderer.state.buffers.stencil.setTest( false ); |
@@ -59,6 +59,8 @@ ( function () { | ||
this.separableBlurMaterial2.uniforms[ 'texSize' ].value.set( Math.round( resx / 2 ), Math.round( resy / 2 ) ); | ||
this.separableBlurMaterial2.uniforms[ 'kernelRadius' ].value = MAX_EDGE_GLOW; // Overlay material | ||
this.separableBlurMaterial2.uniforms[ 'kernelRadius' ].value = MAX_EDGE_GLOW; | ||
this.overlayMaterial = this.getOverlayMaterial(); // copy material | ||
// Overlay material | ||
this.overlayMaterial = this.getOverlayMaterial(); | ||
// copy material | ||
if ( THREE.CopyShader === undefined ) console.error( 'THREE.OutlinePass relies on THREE.CopyShader' ); | ||
@@ -85,3 +87,2 @@ const copyShader = THREE.CopyShader; | ||
this.textureMatrix = new THREE.Matrix4(); | ||
function replaceDepthToViewZ( string, camera ) { | ||
@@ -95,3 +96,2 @@ | ||
} | ||
dispose() { | ||
@@ -106,5 +106,12 @@ | ||
this.renderTargetEdgeBuffer2.dispose(); | ||
this.depthMaterial.dispose(); | ||
this.prepareMaskMaterial.dispose(); | ||
this.edgeDetectionMaterial.dispose(); | ||
this.separableBlurMaterial1.dispose(); | ||
this.separableBlurMaterial2.dispose(); | ||
this.overlayMaterial.dispose(); | ||
this.materialCopy.dispose(); | ||
this.fsQuad.dispose(); | ||
} | ||
setSize( width, height ) { | ||
@@ -127,7 +134,5 @@ | ||
} | ||
changeVisibilityOfSelectedObjects( bVisible ) { | ||
const cache = this._visibilityCache; | ||
function gatherSelectedMeshesCallBack( object ) { | ||
@@ -160,3 +165,2 @@ | ||
} | ||
changeVisibilityOfNonSelectedObjects( bVisible ) { | ||
@@ -166,3 +170,2 @@ | ||
const selectedMeshes = []; | ||
function gatherSelectedMeshesCallBack( object ) { | ||
@@ -186,8 +189,7 @@ | ||
// only meshes and sprites are supported by OutlinePass | ||
let bFound = false; | ||
for ( let i = 0; i < selectedMeshes.length; i ++ ) { | ||
const selectedObjectId = selectedMeshes[ i ].id; | ||
if ( selectedObjectId === object.id ) { | ||
@@ -205,3 +207,2 @@ | ||
const visibility = object.visible; | ||
if ( bVisible === false || cache.get( object ) === true ) { | ||
@@ -221,2 +222,3 @@ | ||
// not affect the outline computation | ||
if ( bVisible === true ) { | ||
@@ -240,3 +242,2 @@ | ||
} | ||
updateTextureMatrix() { | ||
@@ -249,3 +250,2 @@ | ||
} | ||
render( renderer, writeBuffer, readBuffer, deltaTime, maskActive ) { | ||
@@ -260,20 +260,23 @@ | ||
if ( maskActive ) renderer.state.buffers.stencil.setTest( false ); | ||
renderer.setClearColor( 0xffffff, 1 ); // Make selected objects invisible | ||
renderer.setClearColor( 0xffffff, 1 ); | ||
// Make selected objects invisible | ||
this.changeVisibilityOfSelectedObjects( false ); | ||
const currentBackground = this.renderScene.background; | ||
this.renderScene.background = null; // 1. Draw Non Selected objects in the depth buffer | ||
this.renderScene.background = null; | ||
// 1. Draw Non Selected objects in the depth buffer | ||
this.renderScene.overrideMaterial = this.depthMaterial; | ||
renderer.setRenderTarget( this.renderTargetDepthBuffer ); | ||
renderer.clear(); | ||
renderer.render( this.renderScene, this.renderCamera ); // Make selected objects visible | ||
renderer.render( this.renderScene, this.renderCamera ); | ||
// Make selected objects visible | ||
this.changeVisibilityOfSelectedObjects( true ); | ||
this._visibilityCache.clear(); | ||
this._visibilityCache.clear(); // Update Texture Matrix for Depth compare | ||
// Update Texture Matrix for Depth compare | ||
this.updateTextureMatrix(); | ||
this.updateTextureMatrix(); // Make non selected objects invisible, and draw only the selected objects, by comparing the depth buffer of non selected objects | ||
// Make non selected objects invisible, and draw only the selected objects, by comparing the depth buffer of non selected objects | ||
this.changeVisibilityOfNonSelectedObjects( false ); | ||
@@ -289,7 +292,6 @@ this.renderScene.overrideMaterial = this.prepareMaskMaterial; | ||
this.changeVisibilityOfNonSelectedObjects( true ); | ||
this._visibilityCache.clear(); | ||
this.renderScene.background = currentBackground; | ||
this.renderScene.background = currentBackground; // 2. Downsample to Half resolution | ||
// 2. Downsample to Half resolution | ||
this.fsQuad.material = this.materialCopy; | ||
@@ -302,3 +304,2 @@ this.copyUniforms[ 'tDiffuse' ].value = this.renderTargetMaskBuffer.texture; | ||
this.tempPulseColor2.copy( this.hiddenEdgeColor ); | ||
if ( this.pulsePeriod > 0 ) { | ||
@@ -310,5 +311,5 @@ | ||
} // 3. Apply Edge Detection THREE.Pass | ||
} | ||
// 3. Apply Edge Detection THREE.Pass | ||
this.fsQuad.material = this.edgeDetectionMaterial; | ||
@@ -321,4 +322,5 @@ this.edgeDetectionMaterial.uniforms[ 'maskTexture' ].value = this.renderTargetMaskDownSampleBuffer.texture; | ||
renderer.clear(); | ||
this.fsQuad.render( renderer ); // 4. Apply Blur on Half res | ||
this.fsQuad.render( renderer ); | ||
// 4. Apply Blur on Half res | ||
this.fsQuad.material = this.separableBlurMaterial1; | ||
@@ -335,4 +337,5 @@ this.separableBlurMaterial1.uniforms[ 'colorTexture' ].value = this.renderTargetEdgeBuffer1.texture; | ||
renderer.clear(); | ||
this.fsQuad.render( renderer ); // Apply Blur on quarter res | ||
this.fsQuad.render( renderer ); | ||
// Apply Blur on quarter res | ||
this.fsQuad.material = this.separableBlurMaterial2; | ||
@@ -348,4 +351,5 @@ this.separableBlurMaterial2.uniforms[ 'colorTexture' ].value = this.renderTargetEdgeBuffer1.texture; | ||
renderer.clear(); | ||
this.fsQuad.render( renderer ); // Blend it additively over the input texture | ||
this.fsQuad.render( renderer ); | ||
// Blend it additively over the input texture | ||
this.fsQuad.material = this.overlayMaterial; | ||
@@ -377,3 +381,2 @@ this.overlayMaterial.uniforms[ 'maskTexture' ].value = this.renderTargetMaskBuffer.texture; | ||
} | ||
getPrepareMaskMaterial() { | ||
@@ -407,5 +410,15 @@ | ||
#include <project_vertex> | ||
#include <worldpos_vertex> | ||
vPosition = mvPosition; | ||
vec4 worldPosition = vec4( transformed, 1.0 ); | ||
#ifdef USE_INSTANCING | ||
worldPosition = instanceMatrix * worldPosition; | ||
#endif | ||
worldPosition = modelMatrix * worldPosition; | ||
projTexCoord = textureMatrix * worldPosition; | ||
@@ -431,3 +444,2 @@ | ||
} | ||
getEdgeDetectionMaterial() { | ||
@@ -482,3 +494,2 @@ | ||
} | ||
getSeperableBlurMaterial( maxRadius ) { | ||
@@ -542,3 +553,2 @@ | ||
} | ||
getOverlayMaterial() { | ||
@@ -607,3 +617,2 @@ | ||
} | ||
OutlinePass.BlurDirectionX = new THREE.Vector2( 1.0, 0.0 ); | ||
@@ -610,0 +619,0 @@ OutlinePass.BlurDirectionY = new THREE.Vector2( 0.0, 1.0 ); |
@@ -8,14 +8,15 @@ ( function () { | ||
// if set to true, the pass is processed by the composer | ||
this.enabled = true; // if set to true, the pass indicates to swap read and write buffer after rendering | ||
this.enabled = true; | ||
this.needsSwap = true; // if set to true, the pass clears its buffer before rendering | ||
// if set to true, the pass indicates to swap read and write buffer after rendering | ||
this.needsSwap = true; | ||
this.clear = false; // if set to true, the result of the pass is rendered to screen. This is set automatically by EffectComposer. | ||
// if set to true, the pass clears its buffer before rendering | ||
this.clear = false; | ||
// if set to true, the result of the pass is rendered to screen. This is set automatically by EffectComposer. | ||
this.renderToScreen = false; | ||
} | ||
setSize() {} | ||
render() { | ||
@@ -26,15 +27,15 @@ | ||
} | ||
dispose() {} | ||
} // Helper for passes that need to fill the viewport with a single quad. | ||
} | ||
// Helper for passes that need to fill the viewport with a single quad. | ||
const _camera = new THREE.OrthographicCamera( - 1, 1, 1, - 1, 0, 1 ); // https://github.com/mrdoob/three.js/pull/21358 | ||
const _camera = new THREE.OrthographicCamera( - 1, 1, 1, - 1, 0, 1 ); | ||
// https://github.com/mrdoob/three.js/pull/21358 | ||
const _geometry = new THREE.BufferGeometry(); | ||
_geometry.setAttribute( 'position', new THREE.Float32BufferAttribute( [ - 1, 3, 0, - 1, - 1, 0, 3, - 1, 0 ], 3 ) ); | ||
_geometry.setAttribute( 'uv', new THREE.Float32BufferAttribute( [ 0, 2, 0, 0, 2, 0 ], 2 ) ); | ||
class FullScreenQuad { | ||
@@ -47,3 +48,2 @@ | ||
} | ||
dispose() { | ||
@@ -54,3 +54,2 @@ | ||
} | ||
render( renderer ) { | ||
@@ -61,3 +60,2 @@ | ||
} | ||
get material() { | ||
@@ -68,3 +66,2 @@ | ||
} | ||
set material( value ) { | ||
@@ -71,0 +68,0 @@ |
@@ -19,11 +19,7 @@ ( function () { | ||
} | ||
render( renderer, writeBuffer, readBuffer /*, deltaTime, maskActive */ ) { | ||
render( renderer, writeBuffer, readBuffer | ||
/*, deltaTime, maskActive */ | ||
) { | ||
const oldAutoClear = renderer.autoClear; | ||
renderer.autoClear = false; | ||
let oldClearAlpha, oldOverrideMaterial; | ||
if ( this.overrideMaterial !== undefined ) { | ||
@@ -50,7 +46,7 @@ | ||
renderer.setRenderTarget( this.renderToScreen ? null : readBuffer ); // TODO: Avoid using autoClear properties, see https://github.com/mrdoob/three.js/pull/15571#issuecomment-465669600 | ||
renderer.setRenderTarget( this.renderToScreen ? null : readBuffer ); | ||
// TODO: Avoid using autoClear properties, see https://github.com/mrdoob/three.js/pull/15571#issuecomment-465669600 | ||
if ( this.clear ) renderer.clear( renderer.autoClearColor, renderer.autoClearDepth, renderer.autoClearStencil ); | ||
renderer.render( this.scene, this.camera ); | ||
if ( this.clearColor ) { | ||
@@ -57,0 +53,0 @@ |
@@ -43,3 +43,2 @@ ( function () { | ||
let depthTexture; | ||
if ( this.supportsDepthTextureExtension ) { | ||
@@ -59,3 +58,2 @@ | ||
this.normalMaterial.blending = THREE.NoBlending; | ||
if ( THREE.SAOShader === undefined ) { | ||
@@ -83,3 +81,2 @@ | ||
this.saoMaterial.blending = THREE.NoBlending; | ||
if ( THREE.DepthLimitedBlurShader === undefined ) { | ||
@@ -115,3 +112,2 @@ | ||
this.hBlurMaterial.blending = THREE.NoBlending; | ||
if ( THREE.CopyShader === undefined ) { | ||
@@ -139,3 +135,2 @@ | ||
this.materialCopy.blendEquationAlpha = THREE.AddEquation; | ||
if ( THREE.UnpackDepthRGBAShader === undefined ) { | ||
@@ -156,7 +151,4 @@ | ||
} | ||
render( renderer, writeBuffer, readBuffer /*, deltaTime, maskActive*/ ) { | ||
render( renderer, writeBuffer, readBuffer | ||
/*, deltaTime, maskActive*/ | ||
) { | ||
// Rendering readBuffer first when rendering to screen | ||
@@ -190,3 +182,4 @@ if ( this.renderToScreen ) { | ||
this.saoMaterial.uniforms[ 'cameraNear' ].value = this.camera.near; | ||
this.saoMaterial.uniforms[ 'cameraFar' ].value = this.camera.far; // this.saoMaterial.uniforms['randomSeed'].value = Math.random(); | ||
this.saoMaterial.uniforms[ 'cameraFar' ].value = this.camera.far; | ||
// this.saoMaterial.uniforms['randomSeed'].value = Math.random(); | ||
@@ -201,3 +194,2 @@ const depthCutoff = this.params.saoBlurDepthCutoff * ( this.camera.far - this.camera.near ); | ||
this.params.saoBlurRadius = Math.floor( this.params.saoBlurRadius ); | ||
if ( this.prevStdDev !== this.params.saoBlurStdDev || this.prevNumSamples !== this.params.saoBlurRadius ) { | ||
@@ -210,10 +202,11 @@ | ||
} // Rendering scene to depth texture | ||
} | ||
// Rendering scene to depth texture | ||
renderer.setClearColor( 0x000000 ); | ||
renderer.setRenderTarget( this.beautyRenderTarget ); | ||
renderer.clear(); | ||
renderer.render( this.scene, this.camera ); // Re-render scene if depth texture extension is not supported | ||
renderer.render( this.scene, this.camera ); | ||
// Re-render scene if depth texture extension is not supported | ||
if ( ! this.supportsDepthTextureExtension ) { | ||
@@ -231,7 +224,8 @@ | ||
} // Rendering SAO texture | ||
} | ||
// Rendering SAO texture | ||
this.renderPass( renderer, this.saoMaterial, this.saoRenderTarget, 0xffffff, 1.0 ); | ||
this.renderPass( renderer, this.saoMaterial, this.saoRenderTarget, 0xffffff, 1.0 ); // Blurring SAO texture | ||
// Blurring SAO texture | ||
if ( this.params.saoBlur ) { | ||
@@ -244,4 +238,4 @@ | ||
let outputMaterial = this.materialCopy; // Setting up SAO rendering | ||
let outputMaterial = this.materialCopy; | ||
// Setting up SAO rendering | ||
if ( this.params.output === 3 ) { | ||
@@ -272,5 +266,5 @@ | ||
} // Blending depends on output, only want a THREE.CustomBlending when showing SAO | ||
} | ||
// Blending depends on output, only want a THREE.CustomBlending when showing SAO | ||
if ( this.params.output === 0 ) { | ||
@@ -284,5 +278,5 @@ | ||
} // Rendering SAOPass result on top of previous pass | ||
} | ||
// Rendering SAOPass result on top of previous pass | ||
this.renderPass( renderer, outputMaterial, this.renderToScreen ? null : readBuffer ); | ||
@@ -293,3 +287,2 @@ renderer.setClearColor( this._oldClearColor, this.oldClearAlpha ); | ||
} | ||
renderPass( renderer, passMaterial, renderTarget, clearColor, clearAlpha ) { | ||
@@ -301,6 +294,6 @@ | ||
const originalAutoClear = renderer.autoClear; | ||
renderer.setRenderTarget( renderTarget ); // setup pass state | ||
renderer.setRenderTarget( renderTarget ); | ||
// setup pass state | ||
renderer.autoClear = false; | ||
if ( clearColor !== undefined && clearColor !== null ) { | ||
@@ -315,4 +308,5 @@ | ||
this.fsQuad.material = passMaterial; | ||
this.fsQuad.render( renderer ); // restore original state | ||
this.fsQuad.render( renderer ); | ||
// restore original state | ||
renderer.autoClear = originalAutoClear; | ||
@@ -323,3 +317,2 @@ renderer.setClearColor( this.originalClearColor ); | ||
} | ||
renderOverride( renderer, overrideMaterial, renderTarget, clearColor, clearAlpha ) { | ||
@@ -334,3 +327,2 @@ | ||
clearAlpha = overrideMaterial.clearAlpha || clearAlpha; | ||
if ( clearColor !== undefined && clearColor !== null ) { | ||
@@ -346,4 +338,5 @@ | ||
renderer.render( this.scene, this.camera ); | ||
this.scene.overrideMaterial = null; // restore original state | ||
this.scene.overrideMaterial = null; | ||
// restore original state | ||
renderer.autoClear = originalAutoClear; | ||
@@ -354,3 +347,2 @@ renderer.setClearColor( this.originalClearColor ); | ||
} | ||
setSize( width, height ) { | ||
@@ -373,5 +365,21 @@ | ||
} | ||
dispose() { | ||
this.saoRenderTarget.dispose(); | ||
this.blurIntermediateRenderTarget.dispose(); | ||
this.beautyRenderTarget.dispose(); | ||
this.normalRenderTarget.dispose(); | ||
this.depthRenderTarget.dispose(); | ||
this.depthMaterial.dispose(); | ||
this.normalMaterial.dispose(); | ||
this.saoMaterial.dispose(); | ||
this.vBlurMaterial.dispose(); | ||
this.hBlurMaterial.dispose(); | ||
this.materialCopy.dispose(); | ||
this.depthCopy.dispose(); | ||
this.fsQuad.dispose(); | ||
} | ||
} | ||
SAOPass.OUTPUT = { | ||
@@ -378,0 +386,0 @@ 'Beauty': 1, |
@@ -18,6 +18,5 @@ ( function () { | ||
this.renderTarget = renderTarget; | ||
if ( this.renderTarget === undefined ) { | ||
this.renderTarget = new THREE.WebGLRenderTarget( window.innerWidth, window.innerHeight ); | ||
this.renderTarget = new THREE.WebGLRenderTarget(); // will be resized later | ||
this.renderTarget.texture.name = 'SavePass.rt'; | ||
@@ -31,7 +30,4 @@ | ||
} | ||
render( renderer, writeBuffer, readBuffer /*, deltaTime, maskActive */ ) { | ||
render( renderer, writeBuffer, readBuffer | ||
/*, deltaTime, maskActive */ | ||
) { | ||
if ( this.uniforms[ this.textureID ] ) { | ||
@@ -48,3 +44,15 @@ | ||
} | ||
setSize( width, height ) { | ||
this.renderTarget.setSize( width, height ); | ||
} | ||
dispose() { | ||
this.renderTarget.dispose(); | ||
this.material.dispose(); | ||
this.fsQuad.dispose(); | ||
} | ||
} | ||
@@ -51,0 +59,0 @@ |
@@ -9,3 +9,2 @@ ( function () { | ||
this.textureID = textureID !== undefined ? textureID : 'tDiffuse'; | ||
if ( shader instanceof THREE.ShaderMaterial ) { | ||
@@ -31,7 +30,4 @@ | ||
} | ||
render( renderer, writeBuffer, readBuffer /*, deltaTime, maskActive */ ) { | ||
render( renderer, writeBuffer, readBuffer | ||
/*, deltaTime, maskActive */ | ||
) { | ||
if ( this.uniforms[ this.textureID ] ) { | ||
@@ -44,3 +40,2 @@ | ||
this.fsQuad.material = this.material; | ||
if ( this.renderToScreen ) { | ||
@@ -53,4 +48,4 @@ | ||
renderer.setRenderTarget( writeBuffer ); // TODO: Avoid using autoClear properties, see https://github.com/mrdoob/three.js/pull/15571#issuecomment-465669600 | ||
renderer.setRenderTarget( writeBuffer ); | ||
// TODO: Avoid using autoClear properties, see https://github.com/mrdoob/three.js/pull/15571#issuecomment-465669600 | ||
if ( this.clear ) renderer.clear( renderer.autoClearColor, renderer.autoClearDepth, renderer.autoClearStencil ); | ||
@@ -62,3 +57,9 @@ this.fsQuad.render( renderer ); | ||
} | ||
dispose() { | ||
this.material.dispose(); | ||
this.fsQuad.dispose(); | ||
} | ||
} | ||
@@ -65,0 +66,0 @@ |
@@ -7,4 +7,6 @@ ( function () { | ||
super(); // render targets | ||
super(); | ||
// render targets | ||
this.edgesRT = new THREE.WebGLRenderTarget( width, height, { | ||
@@ -17,8 +19,8 @@ depthBuffer: false | ||
} ); | ||
this.weightsRT.texture.name = 'SMAAPass.weights'; // textures | ||
this.weightsRT.texture.name = 'SMAAPass.weights'; | ||
// textures | ||
const scope = this; | ||
const areaTextureImage = new Image(); | ||
areaTextureImage.src = this.getAreaTexture(); | ||
areaTextureImage.onload = function () { | ||
@@ -39,3 +41,2 @@ | ||
searchTextureImage.src = this.getSearchTexture(); | ||
searchTextureImage.onload = function () { | ||
@@ -54,4 +55,6 @@ | ||
this.searchTexture.generateMipmaps = false; | ||
this.searchTexture.flipY = false; // materials - pass 1 | ||
this.searchTexture.flipY = false; | ||
// materials - pass 1 | ||
if ( THREE.SMAAEdgesShader === undefined ) { | ||
@@ -70,4 +73,6 @@ | ||
fragmentShader: THREE.SMAAEdgesShader.fragmentShader | ||
} ); // materials - pass 2 | ||
} ); | ||
// materials - pass 2 | ||
this.uniformsWeights = THREE.UniformsUtils.clone( THREE.SMAAWeightsShader.uniforms ); | ||
@@ -83,4 +88,6 @@ this.uniformsWeights[ 'resolution' ].value.set( 1 / width, 1 / height ); | ||
fragmentShader: THREE.SMAAWeightsShader.fragmentShader | ||
} ); // materials - pass 3 | ||
} ); | ||
// materials - pass 3 | ||
this.uniformsBlend = THREE.UniformsUtils.clone( THREE.SMAABlendShader.uniforms ); | ||
@@ -98,8 +105,6 @@ this.uniformsBlend[ 'resolution' ].value.set( 1 / width, 1 / height ); | ||
} | ||
render( renderer, writeBuffer, readBuffer /*, deltaTime, maskActive*/ ) { | ||
render( renderer, writeBuffer, readBuffer | ||
/*, deltaTime, maskActive*/ | ||
) { | ||
// pass 1 | ||
// pass 1 | ||
this.uniformsEdges[ 'tDiffuse' ].value = readBuffer.texture; | ||
@@ -109,12 +114,15 @@ this.fsQuad.material = this.materialEdges; | ||
if ( this.clear ) renderer.clear(); | ||
this.fsQuad.render( renderer ); // pass 2 | ||
this.fsQuad.render( renderer ); | ||
// pass 2 | ||
this.fsQuad.material = this.materialWeights; | ||
renderer.setRenderTarget( this.weightsRT ); | ||
if ( this.clear ) renderer.clear(); | ||
this.fsQuad.render( renderer ); // pass 3 | ||
this.fsQuad.render( renderer ); | ||
// pass 3 | ||
this.uniformsBlend[ 'tColor' ].value = readBuffer.texture; | ||
this.fsQuad.material = this.materialBlend; | ||
if ( this.renderToScreen ) { | ||
@@ -134,3 +142,2 @@ | ||
} | ||
setSize( width, height ) { | ||
@@ -145,3 +152,2 @@ | ||
} | ||
getAreaTexture() { | ||
@@ -152,3 +158,2 @@ | ||
} | ||
getSearchTexture() { | ||
@@ -159,3 +164,15 @@ | ||
} | ||
dispose() { | ||
this.edgesRT.dispose(); | ||
this.weightsRT.dispose(); | ||
this.areaTexture.dispose(); | ||
this.searchTexture.dispose(); | ||
this.materialEdges.dispose(); | ||
this.materialWeights.dispose(); | ||
this.materialBlend.dispose(); | ||
this.fsQuad.dispose(); | ||
} | ||
} | ||
@@ -162,0 +179,0 @@ |
@@ -21,5 +21,5 @@ ( function () { | ||
this.sampleLevel = 4; // specified as n, where the number of samples is 2^n, so sampleLevel = 4, is 2^4 samples, 16. | ||
this.unbiased = true; | ||
this.unbiased = true; // as we need to clear the buffer in this pass, clearColor must be set to something, defaults to black. | ||
// as we need to clear the buffer in this pass, clearColor must be set to something, defaults to black. | ||
this.clearColor = clearColor !== undefined ? clearColor : 0x000000; | ||
@@ -43,3 +43,2 @@ this.clearAlpha = clearAlpha !== undefined ? clearAlpha : 0; | ||
} | ||
dispose() { | ||
@@ -54,4 +53,6 @@ | ||
this.copyMaterial.dispose(); | ||
this.fsQuad.dispose(); | ||
} | ||
setSize( width, height ) { | ||
@@ -62,3 +63,2 @@ | ||
} | ||
render( renderer, writeBuffer, readBuffer ) { | ||
@@ -74,3 +74,2 @@ | ||
const jitterOffsets = _JitterVectors[ Math.max( 0, Math.min( this.sampleLevel, 5 ) ) ]; | ||
const autoClear = renderer.autoClear; | ||
@@ -92,11 +91,13 @@ renderer.autoClear = false; | ||
const originalViewOffset = Object.assign( {}, this.camera.view ); | ||
if ( originalViewOffset.enabled ) Object.assign( viewOffset, originalViewOffset ); // render the scene multiple times, each slightly jitter offset from the last and accumulate the results. | ||
if ( originalViewOffset.enabled ) Object.assign( viewOffset, originalViewOffset ); | ||
// render the scene multiple times, each slightly jitter offset from the last and accumulate the results. | ||
for ( let i = 0; i < jitterOffsets.length; i ++ ) { | ||
const jitterOffset = jitterOffsets[ i ]; | ||
if ( this.camera.setViewOffset ) { | ||
this.camera.setViewOffset( viewOffset.fullWidth, viewOffset.fullHeight, viewOffset.offsetX + jitterOffset[ 0 ] * 0.0625, viewOffset.offsetY + jitterOffset[ 1 ] * 0.0625, // 0.0625 = 1 / 16 | ||
this.camera.setViewOffset( viewOffset.fullWidth, viewOffset.fullHeight, viewOffset.offsetX + jitterOffset[ 0 ] * 0.0625, viewOffset.offsetY + jitterOffset[ 1 ] * 0.0625, | ||
// 0.0625 = 1 / 16 | ||
viewOffset.width, viewOffset.height ); | ||
@@ -107,3 +108,2 @@ | ||
let sampleWeight = baseSampleWeight; | ||
if ( this.unbiased ) { | ||
@@ -114,2 +114,3 @@ | ||
// across a range of values whose rounding errors cancel each other out. | ||
const uniformCenteredDistribution = - 0.5 + ( i + 0.5 ) / jitterOffsets.length; | ||
@@ -126,3 +127,2 @@ sampleWeight += roundingRange * uniformCenteredDistribution; | ||
renderer.setRenderTarget( this.renderToScreen ? null : writeBuffer ); | ||
if ( i === 0 ) { | ||
@@ -154,3 +154,5 @@ | ||
} // These jitter vectors are specified in integers because it is easier. | ||
} | ||
// These jitter vectors are specified in integers because it is easier. | ||
// I am assuming a [-8,8) integer grid, but it needs to be mapped onto [-0.5,0.5) | ||
@@ -160,4 +162,2 @@ // before being used, thus these integers need to be scaled by 1/16. | ||
// Sample patterns reference: https://msdn.microsoft.com/en-us/library/windows/desktop/ff476218%28v=vs.85%29.aspx?f=255&MSPPError=-2147217396 | ||
const _JitterVectors = [[[ 0, 0 ]], [[ 4, 4 ], [ - 4, - 4 ]], [[ - 2, - 6 ], [ 6, - 2 ], [ - 6, 2 ], [ 2, 6 ]], [[ 1, - 3 ], [ - 1, 3 ], [ 5, 1 ], [ - 3, - 5 ], [ - 5, 5 ], [ - 7, - 1 ], [ 3, 7 ], [ 7, - 7 ]], [[ 1, 1 ], [ - 1, - 3 ], [ - 3, 2 ], [ 4, - 1 ], [ - 5, - 2 ], [ 2, 5 ], [ 5, 3 ], [ 3, - 5 ], [ - 2, 6 ], [ 0, - 7 ], [ - 4, - 6 ], [ - 6, 4 ], [ - 8, 0 ], [ 7, - 4 ], [ 6, 7 ], [ - 7, - 8 ]], [[ - 4, - 7 ], [ - 7, - 5 ], [ - 3, - 5 ], [ - 5, - 4 ], [ - 1, - 4 ], [ - 2, - 2 ], [ - 6, - 1 ], [ - 4, 0 ], [ - 7, 1 ], [ - 1, 2 ], [ - 6, 3 ], [ - 3, 3 ], [ - 7, 6 ], [ - 3, 6 ], [ - 5, 7 ], [ - 1, 7 ], [ 5, - 7 ], [ 1, - 6 ], [ 6, - 5 ], [ 4, - 4 ], [ 2, - 3 ], [ 7, - 2 ], [ 1, - 1 ], [ 4, - 1 ], [ 2, 1 ], [ 6, 2 ], [ 0, 4 ], [ 4, 4 ], [ 2, 5 ], [ 7, 5 ], [ 5, 6 ], [ 3, 7 ]]]; | ||
@@ -164,0 +164,0 @@ |
@@ -20,12 +20,18 @@ ( function () { | ||
this.maxDistance = 0.1; | ||
this._visibilityCache = new Map(); // | ||
this._visibilityCache = new Map(); | ||
// | ||
this.generateSampleKernel(); | ||
this.generateRandomKernelRotations(); // beauty render target | ||
this.generateRandomKernelRotations(); | ||
// beauty render target | ||
const depthTexture = new THREE.DepthTexture(); | ||
depthTexture.format = THREE.DepthStencilFormat; | ||
depthTexture.type = THREE.UnsignedInt248Type; | ||
this.beautyRenderTarget = new THREE.WebGLRenderTarget( this.width, this.height ); // normal render target with depth buffer | ||
this.beautyRenderTarget = new THREE.WebGLRenderTarget( this.width, this.height ); | ||
// normal render target with depth buffer | ||
this.normalRenderTarget = new THREE.WebGLRenderTarget( this.width, this.height, { | ||
@@ -35,7 +41,11 @@ minFilter: THREE.NearestFilter, | ||
depthTexture: depthTexture | ||
} ); // ssao render target | ||
} ); | ||
// ssao render target | ||
this.ssaoRenderTarget = new THREE.WebGLRenderTarget( this.width, this.height ); | ||
this.blurRenderTarget = this.ssaoRenderTarget.clone(); // ssao material | ||
this.blurRenderTarget = this.ssaoRenderTarget.clone(); | ||
// ssao material | ||
if ( THREE.SSAOShader === undefined ) { | ||
@@ -63,7 +73,11 @@ | ||
this.ssaoMaterial.uniforms[ 'cameraProjectionMatrix' ].value.copy( this.camera.projectionMatrix ); | ||
this.ssaoMaterial.uniforms[ 'cameraInverseProjectionMatrix' ].value.copy( this.camera.projectionMatrixInverse ); // normal material | ||
this.ssaoMaterial.uniforms[ 'cameraInverseProjectionMatrix' ].value.copy( this.camera.projectionMatrixInverse ); | ||
// normal material | ||
this.normalMaterial = new THREE.MeshNormalMaterial(); | ||
this.normalMaterial.blending = THREE.NoBlending; // blur material | ||
this.normalMaterial.blending = THREE.NoBlending; | ||
// blur material | ||
this.blurMaterial = new THREE.ShaderMaterial( { | ||
@@ -76,4 +90,6 @@ defines: Object.assign( {}, THREE.SSAOBlurShader.defines ), | ||
this.blurMaterial.uniforms[ 'tDiffuse' ].value = this.ssaoRenderTarget.texture; | ||
this.blurMaterial.uniforms[ 'resolution' ].value.set( this.width, this.height ); // material for rendering the depth | ||
this.blurMaterial.uniforms[ 'resolution' ].value.set( this.width, this.height ); | ||
// material for rendering the depth | ||
this.depthRenderMaterial = new THREE.ShaderMaterial( { | ||
@@ -88,4 +104,6 @@ defines: Object.assign( {}, THREE.SSAODepthShader.defines ), | ||
this.depthRenderMaterial.uniforms[ 'cameraNear' ].value = this.camera.near; | ||
this.depthRenderMaterial.uniforms[ 'cameraFar' ].value = this.camera.far; // material for rendering the content of a render target | ||
this.depthRenderMaterial.uniforms[ 'cameraFar' ].value = this.camera.far; | ||
// material for rendering the content of a render target | ||
this.copyMaterial = new THREE.ShaderMaterial( { | ||
@@ -109,41 +127,52 @@ uniforms: THREE.UniformsUtils.clone( THREE.CopyShader.uniforms ), | ||
} | ||
dispose() { | ||
// dispose render targets | ||
this.beautyRenderTarget.dispose(); | ||
this.normalRenderTarget.dispose(); | ||
this.ssaoRenderTarget.dispose(); | ||
this.blurRenderTarget.dispose(); // dispose materials | ||
this.blurRenderTarget.dispose(); | ||
// dispose materials | ||
this.normalMaterial.dispose(); | ||
this.blurMaterial.dispose(); | ||
this.copyMaterial.dispose(); | ||
this.depthRenderMaterial.dispose(); // dipsose full screen quad | ||
this.depthRenderMaterial.dispose(); | ||
// dipsose full screen quad | ||
this.fsQuad.dispose(); | ||
} | ||
render( renderer, writeBuffer /*, readBuffer, deltaTime, maskActive */ ) { | ||
render( renderer, writeBuffer | ||
/*, readBuffer, deltaTime, maskActive */ | ||
) { | ||
if ( renderer.capabilities.isWebGL2 === false ) this.noiseTexture.format = THREE.LuminanceFormat; | ||
if ( renderer.capabilities.isWebGL2 === false ) this.noiseTexture.format = THREE.LuminanceFormat; // render beauty | ||
// render beauty | ||
renderer.setRenderTarget( this.beautyRenderTarget ); | ||
renderer.clear(); | ||
renderer.render( this.scene, this.camera ); // render normals and depth (honor only meshes, points and lines do not contribute to SSAO) | ||
renderer.render( this.scene, this.camera ); | ||
// render normals and depth (honor only meshes, points and lines do not contribute to SSAO) | ||
this.overrideVisibility(); | ||
this.renderOverride( renderer, this.normalMaterial, this.normalRenderTarget, 0x7777ff, 1.0 ); | ||
this.restoreVisibility(); // render SSAO | ||
this.restoreVisibility(); | ||
// render SSAO | ||
this.ssaoMaterial.uniforms[ 'kernelRadius' ].value = this.kernelRadius; | ||
this.ssaoMaterial.uniforms[ 'minDistance' ].value = this.minDistance; | ||
this.ssaoMaterial.uniforms[ 'maxDistance' ].value = this.maxDistance; | ||
this.renderPass( renderer, this.ssaoMaterial, this.ssaoRenderTarget ); // render blur | ||
this.renderPass( renderer, this.ssaoMaterial, this.ssaoRenderTarget ); | ||
this.renderPass( renderer, this.blurMaterial, this.blurRenderTarget ); // output result to screen | ||
// render blur | ||
this.renderPass( renderer, this.blurMaterial, this.blurRenderTarget ); | ||
// output result to screen | ||
switch ( this.output ) { | ||
@@ -156,3 +185,2 @@ | ||
break; | ||
case SSAOPass.OUTPUT.Blur: | ||
@@ -163,3 +191,2 @@ this.copyMaterial.uniforms[ 'tDiffuse' ].value = this.blurRenderTarget.texture; | ||
break; | ||
case SSAOPass.OUTPUT.Beauty: | ||
@@ -170,7 +197,5 @@ this.copyMaterial.uniforms[ 'tDiffuse' ].value = this.beautyRenderTarget.texture; | ||
break; | ||
case SSAOPass.OUTPUT.Depth: | ||
this.renderPass( renderer, this.depthRenderMaterial, this.renderToScreen ? null : writeBuffer ); | ||
break; | ||
case SSAOPass.OUTPUT.Normal: | ||
@@ -181,3 +206,2 @@ this.copyMaterial.uniforms[ 'tDiffuse' ].value = this.normalRenderTarget.texture; | ||
break; | ||
case SSAOPass.OUTPUT.Default: | ||
@@ -191,3 +215,2 @@ this.copyMaterial.uniforms[ 'tDiffuse' ].value = this.beautyRenderTarget.texture; | ||
break; | ||
default: | ||
@@ -199,3 +222,2 @@ console.warn( 'THREE.SSAOPass: Unknown output type.' ); | ||
} | ||
renderPass( renderer, passMaterial, renderTarget, clearColor, clearAlpha ) { | ||
@@ -207,6 +229,6 @@ | ||
const originalAutoClear = renderer.autoClear; | ||
renderer.setRenderTarget( renderTarget ); // setup pass state | ||
renderer.setRenderTarget( renderTarget ); | ||
// setup pass state | ||
renderer.autoClear = false; | ||
if ( clearColor !== undefined && clearColor !== null ) { | ||
@@ -221,4 +243,5 @@ | ||
this.fsQuad.material = passMaterial; | ||
this.fsQuad.render( renderer ); // restore original state | ||
this.fsQuad.render( renderer ); | ||
// restore original state | ||
renderer.autoClear = originalAutoClear; | ||
@@ -229,3 +252,2 @@ renderer.setClearColor( this.originalClearColor ); | ||
} | ||
renderOverride( renderer, overrideMaterial, renderTarget, clearColor, clearAlpha ) { | ||
@@ -240,3 +262,2 @@ | ||
clearAlpha = overrideMaterial.clearAlpha || clearAlpha; | ||
if ( clearColor !== undefined && clearColor !== null ) { | ||
@@ -252,4 +273,6 @@ | ||
renderer.render( this.scene, this.camera ); | ||
this.scene.overrideMaterial = null; // restore original state | ||
this.scene.overrideMaterial = null; | ||
// restore original state | ||
renderer.autoClear = originalAutoClear; | ||
@@ -260,3 +283,2 @@ renderer.setClearColor( this.originalClearColor ); | ||
} | ||
setSize( width, height ) { | ||
@@ -276,3 +298,2 @@ | ||
} | ||
generateSampleKernel() { | ||
@@ -282,3 +303,2 @@ | ||
const kernel = this.kernel; | ||
for ( let i = 0; i < kernelSize; i ++ ) { | ||
@@ -299,3 +319,2 @@ | ||
} | ||
generateRandomKernelRotations() { | ||
@@ -305,3 +324,2 @@ | ||
height = 4; | ||
if ( THREE.SimplexNoise === undefined ) { | ||
@@ -316,3 +334,2 @@ | ||
const data = new Float32Array( size ); | ||
for ( let i = 0; i < size; i ++ ) { | ||
@@ -333,3 +350,2 @@ | ||
} | ||
overrideVisibility() { | ||
@@ -347,3 +363,2 @@ | ||
} | ||
restoreVisibility() { | ||
@@ -364,3 +379,2 @@ | ||
} | ||
SSAOPass.OUTPUT = { | ||
@@ -367,0 +381,0 @@ 'Default': 0, |
@@ -37,3 +37,2 @@ ( function () { | ||
}, | ||
set( val ) { | ||
@@ -43,3 +42,2 @@ | ||
this._selects = val; | ||
if ( Array.isArray( val ) ) { | ||
@@ -60,3 +58,2 @@ | ||
} | ||
} ); | ||
@@ -70,3 +67,2 @@ this._bouncing = bouncing; | ||
}, | ||
set( val ) { | ||
@@ -76,3 +72,2 @@ | ||
this._bouncing = val; | ||
if ( val ) { | ||
@@ -89,3 +84,2 @@ | ||
} | ||
} ); | ||
@@ -100,3 +94,2 @@ this.blur = true; | ||
}, | ||
set( val ) { | ||
@@ -110,3 +103,2 @@ | ||
} | ||
} ); | ||
@@ -120,3 +112,2 @@ this._fresnel = THREE.SSRShader.defines.FRESNEL; | ||
}, | ||
set( val ) { | ||
@@ -130,3 +121,2 @@ | ||
} | ||
} ); | ||
@@ -140,3 +130,2 @@ this._infiniteThick = THREE.SSRShader.defines.INFINITE_THICK; | ||
}, | ||
set( val ) { | ||
@@ -150,4 +139,5 @@ | ||
} | ||
} ); | ||
} ); // beauty render target with depth buffer | ||
// beauty render target with depth buffer | ||
@@ -163,9 +153,12 @@ const depthTexture = new THREE.DepthTexture(); | ||
depthBuffer: true | ||
} ); //for bouncing | ||
} ); | ||
//for bouncing | ||
this.prevRenderTarget = new THREE.WebGLRenderTarget( this.width, this.height, { | ||
minFilter: THREE.NearestFilter, | ||
magFilter: THREE.NearestFilter | ||
} ); // normal render target | ||
} ); | ||
// normal render target | ||
this.normalRenderTarget = new THREE.WebGLRenderTarget( this.width, this.height, { | ||
@@ -175,9 +168,13 @@ minFilter: THREE.NearestFilter, | ||
type: THREE.HalfFloatType | ||
} ); // metalness render target | ||
} ); | ||
// metalness render target | ||
this.metalnessRenderTarget = new THREE.WebGLRenderTarget( this.width, this.height, { | ||
minFilter: THREE.NearestFilter, | ||
magFilter: THREE.NearestFilter | ||
} ); // ssr render target | ||
} ); | ||
// ssr render target | ||
this.ssrRenderTarget = new THREE.WebGLRenderTarget( this.width, this.height, { | ||
@@ -188,3 +185,5 @@ minFilter: THREE.NearestFilter, | ||
this.blurRenderTarget = this.ssrRenderTarget.clone(); | ||
this.blurRenderTarget2 = this.ssrRenderTarget.clone(); // this.blurRenderTarget3 = this.ssrRenderTarget.clone(); | ||
this.blurRenderTarget2 = this.ssrRenderTarget.clone(); | ||
// this.blurRenderTarget3 = this.ssrRenderTarget.clone(); | ||
// ssr material | ||
@@ -218,15 +217,23 @@ | ||
this.ssrMaterial.uniforms[ 'cameraProjectionMatrix' ].value.copy( this.camera.projectionMatrix ); | ||
this.ssrMaterial.uniforms[ 'cameraInverseProjectionMatrix' ].value.copy( this.camera.projectionMatrixInverse ); // normal material | ||
this.ssrMaterial.uniforms[ 'cameraInverseProjectionMatrix' ].value.copy( this.camera.projectionMatrixInverse ); | ||
// normal material | ||
this.normalMaterial = new THREE.MeshNormalMaterial(); | ||
this.normalMaterial.blending = THREE.NoBlending; // metalnessOn material | ||
this.normalMaterial.blending = THREE.NoBlending; | ||
// metalnessOn material | ||
this.metalnessOnMaterial = new THREE.MeshBasicMaterial( { | ||
color: 'white' | ||
} ); // metalnessOff material | ||
} ); | ||
// metalnessOff material | ||
this.metalnessOffMaterial = new THREE.MeshBasicMaterial( { | ||
color: 'black' | ||
} ); // blur material | ||
} ); | ||
// blur material | ||
this.blurMaterial = new THREE.ShaderMaterial( { | ||
@@ -239,4 +246,6 @@ defines: Object.assign( {}, THREE.SSRBlurShader.defines ), | ||
this.blurMaterial.uniforms[ 'tDiffuse' ].value = this.ssrRenderTarget.texture; | ||
this.blurMaterial.uniforms[ 'resolution' ].value.set( this.width, this.height ); // blur material 2 | ||
this.blurMaterial.uniforms[ 'resolution' ].value.set( this.width, this.height ); | ||
// blur material 2 | ||
this.blurMaterial2 = new THREE.ShaderMaterial( { | ||
@@ -249,3 +258,6 @@ defines: Object.assign( {}, THREE.SSRBlurShader.defines ), | ||
this.blurMaterial2.uniforms[ 'tDiffuse' ].value = this.blurRenderTarget.texture; | ||
this.blurMaterial2.uniforms[ 'resolution' ].value.set( this.width, this.height ); // // blur material 3 | ||
this.blurMaterial2.uniforms[ 'resolution' ].value.set( this.width, this.height ); | ||
// // blur material 3 | ||
// this.blurMaterial3 = new THREE.ShaderMaterial({ | ||
@@ -259,2 +271,3 @@ // defines: Object.assign({}, THREE.SSRBlurShader.defines), | ||
// this.blurMaterial3.uniforms['resolution'].value.set(this.width, this.height); | ||
// material for rendering the depth | ||
@@ -271,4 +284,6 @@ | ||
this.depthRenderMaterial.uniforms[ 'cameraNear' ].value = this.camera.near; | ||
this.depthRenderMaterial.uniforms[ 'cameraFar' ].value = this.camera.far; // material for rendering the content of a render target | ||
this.depthRenderMaterial.uniforms[ 'cameraFar' ].value = this.camera.far; | ||
// material for rendering the content of a render target | ||
this.copyMaterial = new THREE.ShaderMaterial( { | ||
@@ -286,5 +301,6 @@ uniforms: THREE.UniformsUtils.clone( THREE.CopyShader.uniforms ), | ||
blendDstAlpha: THREE.OneMinusSrcAlphaFactor, | ||
blendEquationAlpha: THREE.AddEquation // premultipliedAlpha:true, | ||
blendEquationAlpha: THREE.AddEquation | ||
// premultipliedAlpha:true, | ||
} ); | ||
} ); | ||
this.fsQuad = new THREE.FullScreenQuad( null ); | ||
@@ -294,6 +310,6 @@ this.originalClearColor = new THREE.Color(); | ||
} | ||
dispose() { | ||
// dispose render targets | ||
this.beautyRenderTarget.dispose(); | ||
@@ -305,3 +321,5 @@ this.prevRenderTarget.dispose(); | ||
this.blurRenderTarget.dispose(); | ||
this.blurRenderTarget2.dispose(); // this.blurRenderTarget3.dispose(); | ||
this.blurRenderTarget2.dispose(); | ||
// this.blurRenderTarget3.dispose(); | ||
// dispose materials | ||
@@ -315,16 +333,15 @@ | ||
this.copyMaterial.dispose(); | ||
this.depthRenderMaterial.dispose(); // dipsose full screen quad | ||
this.depthRenderMaterial.dispose(); | ||
// dipsose full screen quad | ||
this.fsQuad.dispose(); | ||
} | ||
render( renderer, writeBuffer /*, readBuffer, deltaTime, maskActive */ ) { | ||
render( renderer, writeBuffer | ||
/*, readBuffer, deltaTime, maskActive */ | ||
) { | ||
// render beauty and depth | ||
// render beauty and depth | ||
renderer.setRenderTarget( this.beautyRenderTarget ); | ||
renderer.clear(); | ||
if ( this.groundReflector ) { | ||
@@ -339,6 +356,10 @@ | ||
renderer.render( this.scene, this.camera ); | ||
if ( this.groundReflector ) this.groundReflector.visible = false; // render normals | ||
if ( this.groundReflector ) this.groundReflector.visible = false; | ||
this.renderOverride( renderer, this.normalMaterial, this.normalRenderTarget, 0, 0 ); // render metalnesses | ||
// render normals | ||
this.renderOverride( renderer, this.normalMaterial, this.normalRenderTarget, 0, 0 ); | ||
// render metalnesses | ||
if ( this.selective ) { | ||
@@ -348,4 +369,5 @@ | ||
} // render SSR | ||
} | ||
// render SSR | ||
@@ -355,11 +377,15 @@ this.ssrMaterial.uniforms[ 'opacity' ].value = this.opacity; | ||
this.ssrMaterial.uniforms[ 'thickness' ].value = this.thickness; | ||
this.renderPass( renderer, this.ssrMaterial, this.ssrRenderTarget ); // render blur | ||
this.renderPass( renderer, this.ssrMaterial, this.ssrRenderTarget ); | ||
// render blur | ||
if ( this.blur ) { | ||
this.renderPass( renderer, this.blurMaterial, this.blurRenderTarget ); | ||
this.renderPass( renderer, this.blurMaterial2, this.blurRenderTarget2 ); // this.renderPass(renderer, this.blurMaterial3, this.blurRenderTarget3); | ||
this.renderPass( renderer, this.blurMaterial2, this.blurRenderTarget2 ); | ||
// this.renderPass(renderer, this.blurMaterial3, this.blurRenderTarget3); | ||
} // output result to screen | ||
} | ||
// output result to screen | ||
@@ -393,3 +419,2 @@ switch ( this.output ) { | ||
break; | ||
case SSRPass.OUTPUT.SSR: | ||
@@ -399,3 +424,2 @@ if ( this.blur ) this.copyMaterial.uniforms[ 'tDiffuse' ].value = this.blurRenderTarget2.texture; else this.copyMaterial.uniforms[ 'tDiffuse' ].value = this.ssrRenderTarget.texture; | ||
this.renderPass( renderer, this.copyMaterial, this.renderToScreen ? null : writeBuffer ); | ||
if ( this.bouncing ) { | ||
@@ -413,3 +437,2 @@ | ||
break; | ||
case SSRPass.OUTPUT.Beauty: | ||
@@ -420,7 +443,5 @@ this.copyMaterial.uniforms[ 'tDiffuse' ].value = this.beautyRenderTarget.texture; | ||
break; | ||
case SSRPass.OUTPUT.Depth: | ||
this.renderPass( renderer, this.depthRenderMaterial, this.renderToScreen ? null : writeBuffer ); | ||
break; | ||
case SSRPass.OUTPUT.Normal: | ||
@@ -431,3 +452,2 @@ this.copyMaterial.uniforms[ 'tDiffuse' ].value = this.normalRenderTarget.texture; | ||
break; | ||
case SSRPass.OUTPUT.Metalness: | ||
@@ -438,3 +458,2 @@ this.copyMaterial.uniforms[ 'tDiffuse' ].value = this.metalnessRenderTarget.texture; | ||
break; | ||
default: | ||
@@ -446,3 +465,2 @@ console.warn( 'THREE.SSRPass: Unknown output type.' ); | ||
} | ||
renderPass( renderer, passMaterial, renderTarget, clearColor, clearAlpha ) { | ||
@@ -454,6 +472,6 @@ | ||
const originalAutoClear = renderer.autoClear; | ||
renderer.setRenderTarget( renderTarget ); // setup pass state | ||
renderer.setRenderTarget( renderTarget ); | ||
// setup pass state | ||
renderer.autoClear = false; | ||
if ( clearColor !== undefined && clearColor !== null ) { | ||
@@ -468,4 +486,5 @@ | ||
this.fsQuad.material = passMaterial; | ||
this.fsQuad.render( renderer ); // restore original state | ||
this.fsQuad.render( renderer ); | ||
// restore original state | ||
renderer.autoClear = originalAutoClear; | ||
@@ -476,3 +495,2 @@ renderer.setClearColor( this.originalClearColor ); | ||
} | ||
renderOverride( renderer, overrideMaterial, renderTarget, clearColor, clearAlpha ) { | ||
@@ -487,3 +505,2 @@ | ||
clearAlpha = overrideMaterial.clearAlpha || clearAlpha; | ||
if ( clearColor !== undefined && clearColor !== null ) { | ||
@@ -499,4 +516,6 @@ | ||
renderer.render( this.scene, this.camera ); | ||
this.scene.overrideMaterial = null; // restore original state | ||
this.scene.overrideMaterial = null; | ||
// restore original state | ||
renderer.autoClear = originalAutoClear; | ||
@@ -507,3 +526,2 @@ renderer.setClearColor( this.originalClearColor ); | ||
} | ||
renderMetalness( renderer, overrideMaterial, renderTarget, clearColor, clearAlpha ) { | ||
@@ -518,3 +536,2 @@ | ||
clearAlpha = overrideMaterial.clearAlpha || clearAlpha; | ||
if ( clearColor !== undefined && clearColor !== null ) { | ||
@@ -531,3 +548,2 @@ | ||
child._SSRPassBackupMaterial = child.material; | ||
if ( this._selects.includes( child ) ) { | ||
@@ -549,4 +565,6 @@ | ||
} ); // restore original state | ||
} ); | ||
// restore original state | ||
renderer.autoClear = originalAutoClear; | ||
@@ -557,3 +575,2 @@ renderer.setClearColor( this.originalClearColor ); | ||
} | ||
setSize( width, height ) { | ||
@@ -571,3 +588,4 @@ | ||
this.blurRenderTarget.setSize( width, height ); | ||
this.blurRenderTarget2.setSize( width, height ); // this.blurRenderTarget3.setSize(width, height); | ||
this.blurRenderTarget2.setSize( width, height ); | ||
// this.blurRenderTarget3.setSize(width, height); | ||
@@ -583,3 +601,2 @@ this.ssrMaterial.uniforms[ 'resolution' ].value.set( width, height ); | ||
} | ||
SSRPass.OUTPUT = { | ||
@@ -586,0 +603,0 @@ 'Default': 0, |
@@ -24,3 +24,2 @@ ( function () { | ||
} | ||
render( renderer, writeBuffer, readBuffer, deltaTime ) { | ||
@@ -37,3 +36,2 @@ | ||
const jitterOffsets = _JitterVectors[ 5 ]; | ||
if ( this.sampleRenderTarget === undefined ) { | ||
@@ -63,10 +61,9 @@ | ||
const sampleWeight = 1.0 / jitterOffsets.length; | ||
if ( this.accumulateIndex >= 0 && this.accumulateIndex < jitterOffsets.length ) { | ||
this.copyUniforms[ 'opacity' ].value = sampleWeight; | ||
this.copyUniforms[ 'tDiffuse' ].value = writeBuffer.texture; // render the scene multiple times, each slightly jitter offset from the last and accumulate the results. | ||
this.copyUniforms[ 'tDiffuse' ].value = writeBuffer.texture; | ||
// render the scene multiple times, each slightly jitter offset from the last and accumulate the results. | ||
const numSamplesPerFrame = Math.pow( 2, this.sampleLevel ); | ||
for ( let i = 0; i < numSamplesPerFrame; i ++ ) { | ||
@@ -76,6 +73,6 @@ | ||
const jitterOffset = jitterOffsets[ j ]; | ||
if ( this.camera.setViewOffset ) { | ||
this.camera.setViewOffset( readBuffer.width, readBuffer.height, jitterOffset[ 0 ] * 0.0625, jitterOffset[ 1 ] * 0.0625, // 0.0625 = 1 / 16 | ||
this.camera.setViewOffset( readBuffer.width, readBuffer.height, jitterOffset[ 0 ] * 0.0625, jitterOffset[ 1 ] * 0.0625, | ||
// 0.0625 = 1 / 16 | ||
readBuffer.width, readBuffer.height ); | ||
@@ -101,3 +98,2 @@ | ||
const accumulationWeight = this.accumulateIndex * sampleWeight; | ||
if ( accumulationWeight > 0 ) { | ||
@@ -126,5 +122,11 @@ | ||
} | ||
dispose() { | ||
super.dispose(); | ||
if ( this.sampleRenderTarget !== undefined ) this.sampleRenderTarget.dispose(); | ||
if ( this.holdRenderTarget !== undefined ) this.holdRenderTarget.dispose(); | ||
} | ||
} | ||
const _JitterVectors = [[[ 0, 0 ]], [[ 4, 4 ], [ - 4, - 4 ]], [[ - 2, - 6 ], [ 6, - 2 ], [ - 6, 2 ], [ 2, 6 ]], [[ 1, - 3 ], [ - 1, 3 ], [ 5, 1 ], [ - 3, - 5 ], [ - 5, 5 ], [ - 7, - 1 ], [ 3, 7 ], [ 7, - 7 ]], [[ 1, 1 ], [ - 1, - 3 ], [ - 3, 2 ], [ 4, - 1 ], [ - 5, - 2 ], [ 2, 5 ], [ 5, 3 ], [ 3, - 5 ], [ - 2, 6 ], [ 0, - 7 ], [ - 4, - 6 ], [ - 6, 4 ], [ - 8, 0 ], [ 7, - 4 ], [ 6, 7 ], [ - 7, - 8 ]], [[ - 4, - 7 ], [ - 7, - 5 ], [ - 3, - 5 ], [ - 5, - 4 ], [ - 1, - 4 ], [ - 2, - 2 ], [ - 6, - 1 ], [ - 4, 0 ], [ - 7, 1 ], [ - 1, 2 ], [ - 6, 3 ], [ - 3, 3 ], [ - 7, 6 ], [ - 3, 6 ], [ - 5, 7 ], [ - 1, 7 ], [ 5, - 7 ], [ 1, - 6 ], [ 6, - 5 ], [ 4, - 4 ], [ 2, - 3 ], [ 7, - 2 ], [ 1, - 1 ], [ 4, - 1 ], [ 2, 1 ], [ 6, 2 ], [ 0, 4 ], [ 4, 4 ], [ 2, 5 ], [ 7, 5 ], [ 5, 6 ], [ 3, 7 ]]]; | ||
@@ -131,0 +133,0 @@ |
@@ -24,7 +24,4 @@ ( function () { | ||
} | ||
render( renderer, writeBuffer, readBuffer /*, deltaTime, maskActive */ ) { | ||
render( renderer, writeBuffer, readBuffer | ||
/*, deltaTime, maskActive */ | ||
) { | ||
const oldAutoClear = renderer.autoClear; | ||
@@ -42,3 +39,9 @@ renderer.autoClear = false; | ||
} | ||
dispose() { | ||
this.material.dispose(); | ||
this.fsQuad.dispose(); | ||
} | ||
} | ||
@@ -45,0 +48,0 @@ |
@@ -12,3 +12,2 @@ ( function () { | ||
*/ | ||
class UnrealBloomPass extends THREE.Pass { | ||
@@ -22,6 +21,8 @@ | ||
this.threshold = threshold; | ||
this.resolution = resolution !== undefined ? new THREE.Vector2( resolution.x, resolution.y ) : new THREE.Vector2( 256, 256 ); // create color only once here, reuse it later inside the render function | ||
this.resolution = resolution !== undefined ? new THREE.Vector2( resolution.x, resolution.y ) : new THREE.Vector2( 256, 256 ); | ||
this.clearColor = new THREE.Color( 0, 0, 0 ); // render targets | ||
// create color only once here, reuse it later inside the render function | ||
this.clearColor = new THREE.Color( 0, 0, 0 ); | ||
// render targets | ||
this.renderTargetsHorizontal = []; | ||
@@ -35,3 +36,2 @@ this.renderTargetsVertical = []; | ||
this.renderTargetBright.texture.generateMipmaps = false; | ||
for ( let i = 0; i < this.nMips; i ++ ) { | ||
@@ -50,4 +50,5 @@ | ||
} // luminosity high pass material | ||
} | ||
// luminosity high pass material | ||
@@ -64,4 +65,5 @@ if ( THREE.LuminosityHighPassShader === undefined ) console.error( 'THREE.UnrealBloomPass relies on THREE.LuminosityHighPassShader' ); | ||
defines: {} | ||
} ); // Gaussian Blur Materials | ||
} ); | ||
// Gaussian Blur Materials | ||
this.separableBlurMaterials = []; | ||
@@ -71,3 +73,2 @@ const kernelSizeArray = [ 3, 5, 7, 9, 11 ]; | ||
resy = Math.round( this.resolution.y / 2 ); | ||
for ( let i = 0; i < this.nMips; i ++ ) { | ||
@@ -80,5 +81,5 @@ | ||
} // Composite material | ||
} | ||
// Composite material | ||
this.compositeMaterial = this.getCompositeMaterial( this.nMips ); | ||
@@ -96,4 +97,5 @@ this.compositeMaterial.uniforms[ 'blurTexture1' ].value = this.renderTargetsVertical[ 0 ].texture; | ||
this.bloomTintColors = [ new THREE.Vector3( 1, 1, 1 ), new THREE.Vector3( 1, 1, 1 ), new THREE.Vector3( 1, 1, 1 ), new THREE.Vector3( 1, 1, 1 ), new THREE.Vector3( 1, 1, 1 ) ]; | ||
this.compositeMaterial.uniforms[ 'bloomTintColors' ].value = this.bloomTintColors; // copy material | ||
this.compositeMaterial.uniforms[ 'bloomTintColors' ].value = this.bloomTintColors; | ||
// copy material | ||
if ( THREE.CopyShader === undefined ) { | ||
@@ -125,3 +127,2 @@ | ||
} | ||
dispose() { | ||
@@ -143,4 +144,19 @@ | ||
// | ||
for ( let i = 0; i < this.separableBlurMaterials.length; i ++ ) { | ||
this.separableBlurMaterials[ i ].dispose(); | ||
} | ||
this.compositeMaterial.dispose(); | ||
this.materialCopy.dispose(); | ||
this.basic.dispose(); | ||
// | ||
this.fsQuad.dispose(); | ||
} | ||
setSize( width, height ) { | ||
@@ -151,3 +167,2 @@ | ||
this.renderTargetBright.setSize( resx, resy ); | ||
for ( let i = 0; i < this.nMips; i ++ ) { | ||
@@ -164,3 +179,2 @@ | ||
} | ||
render( renderer, writeBuffer, readBuffer, deltaTime, maskActive ) { | ||
@@ -173,4 +187,6 @@ | ||
renderer.setClearColor( this.clearColor, 0 ); | ||
if ( maskActive ) renderer.state.buffers.stencil.setTest( false ); // Render input to screen | ||
if ( maskActive ) renderer.state.buffers.stencil.setTest( false ); | ||
// Render input to screen | ||
if ( this.renderToScreen ) { | ||
@@ -184,4 +200,5 @@ | ||
} // 1. Extract Bright Areas | ||
} | ||
// 1. Extract Bright Areas | ||
@@ -193,6 +210,7 @@ this.highPassUniforms[ 'tDiffuse' ].value = readBuffer.texture; | ||
renderer.clear(); | ||
this.fsQuad.render( renderer ); // 2. Blur All the mips progressively | ||
this.fsQuad.render( renderer ); | ||
// 2. Blur All the mips progressively | ||
let inputRenderTarget = this.renderTargetBright; | ||
for ( let i = 0; i < this.nMips; i ++ ) { | ||
@@ -213,4 +231,5 @@ | ||
} // Composite All the mips | ||
} | ||
// Composite All the mips | ||
@@ -223,8 +242,9 @@ this.fsQuad.material = this.compositeMaterial; | ||
renderer.clear(); | ||
this.fsQuad.render( renderer ); // Blend it additively over the input texture | ||
this.fsQuad.render( renderer ); | ||
// Blend it additively over the input texture | ||
this.fsQuad.material = this.materialCopy; | ||
this.copyUniforms[ 'tDiffuse' ].value = this.renderTargetsHorizontal[ 0 ].texture; | ||
if ( maskActive ) renderer.state.buffers.stencil.setTest( true ); | ||
if ( this.renderToScreen ) { | ||
@@ -240,4 +260,5 @@ | ||
} // Restore renderer settings | ||
} | ||
// Restore renderer settings | ||
@@ -248,3 +269,2 @@ renderer.setClearColor( this._oldClearColor, this.oldClearAlpha ); | ||
} | ||
getSeperableBlurMaterial( kernelRadius ) { | ||
@@ -301,3 +321,2 @@ | ||
} | ||
getCompositeMaterial( nMips ) { | ||
@@ -371,3 +390,2 @@ | ||
} | ||
UnrealBloomPass.BlurDirectionX = new THREE.Vector2( 1.0, 0.0 ); | ||
@@ -374,0 +392,0 @@ UnrealBloomPass.BlurDirectionY = new THREE.Vector2( 0.0, 1.0 ); |
@@ -28,3 +28,2 @@ ( function () { | ||
} | ||
copy( source, recursive ) { | ||
@@ -38,15 +37,11 @@ | ||
} // | ||
} | ||
// | ||
const _vector = new THREE.Vector3(); | ||
const _viewMatrix = new THREE.Matrix4(); | ||
const _viewProjectionMatrix = new THREE.Matrix4(); | ||
const _a = new THREE.Vector3(); | ||
const _b = new THREE.Vector3(); | ||
class CSS2DRenderer { | ||
@@ -57,7 +52,4 @@ | ||
const _this = this; | ||
let _width, _height; | ||
let _widthHalf, _heightHalf; | ||
const cache = { | ||
@@ -69,3 +61,2 @@ objects: new WeakMap() | ||
this.domElement = domElement; | ||
this.getSize = function () { | ||
@@ -84,7 +75,4 @@ | ||
if ( camera.parent === null && camera.matrixWorldAutoUpdate === true ) camera.updateMatrixWorld(); | ||
_viewMatrix.copy( camera.matrixWorldInverse ); | ||
_viewProjectionMatrix.multiplyMatrices( camera.projectionMatrix, _viewMatrix ); | ||
renderObject( scene, scene, camera ); | ||
@@ -111,8 +99,5 @@ zOrder( scene ); | ||
_vector.setFromMatrixPosition( object.matrixWorld ); | ||
_vector.applyMatrix4( _viewProjectionMatrix ); | ||
const visible = object.visible === true && _vector.z >= - 1 && _vector.z <= 1 && object.layers.test( camera.layers ) === true; | ||
object.element.style.display = visible === true ? '' : 'none'; | ||
if ( visible === true ) { | ||
@@ -123,3 +108,2 @@ | ||
element.style.transform = 'translate(-50%,-50%) translate(' + ( _vector.x * _widthHalf + _widthHalf ) + 'px,' + ( - _vector.y * _heightHalf + _heightHalf ) + 'px)'; | ||
if ( element.parentNode !== domElement ) { | ||
@@ -153,5 +137,3 @@ | ||
_a.setFromMatrixPosition( object1.matrixWorld ); | ||
_b.setFromMatrixPosition( object2.matrixWorld ); | ||
return _a.distanceToSquared( _b ); | ||
@@ -189,3 +171,2 @@ | ||
const zMax = sorted.length; | ||
for ( let i = 0, l = sorted.length; i < l; i ++ ) { | ||
@@ -192,0 +173,0 @@ |
@@ -8,7 +8,4 @@ ( function () { | ||
const _position = new THREE.Vector3(); | ||
const _quaternion = new THREE.Quaternion(); | ||
const _scale = new THREE.Vector3(); | ||
class CSS3DObject extends THREE.Object3D { | ||
@@ -40,3 +37,2 @@ | ||
} | ||
copy( source, recursive ) { | ||
@@ -51,3 +47,2 @@ | ||
} | ||
class CSS3DSprite extends CSS3DObject { | ||
@@ -62,3 +57,2 @@ | ||
} | ||
copy( source, recursive ) { | ||
@@ -72,9 +66,8 @@ | ||
} // | ||
} | ||
// | ||
const _matrix = new THREE.Matrix4(); | ||
const _matrix2 = new THREE.Matrix4(); | ||
class CSS3DRenderer { | ||
@@ -85,7 +78,4 @@ | ||
const _this = this; | ||
let _width, _height; | ||
let _widthHalf, _heightHalf; | ||
const cache = { | ||
@@ -105,3 +95,2 @@ camera: { | ||
domElement.appendChild( cameraElement ); | ||
this.getSize = function () { | ||
@@ -119,3 +108,2 @@ | ||
const fov = camera.projectionMatrix.elements[ 5 ] * _heightHalf; | ||
if ( cache.camera.fov !== fov ) { | ||
@@ -131,3 +119,2 @@ | ||
let tx, ty; | ||
if ( camera.isOrthographicCamera ) { | ||
@@ -142,3 +129,2 @@ | ||
const style = cameraCSSMatrix + 'translate(' + _widthHalf + 'px,' + _heightHalf + 'px)'; | ||
if ( cache.camera.style !== style ) { | ||
@@ -195,3 +181,2 @@ | ||
object.element.style.display = visible === true ? '' : 'none'; | ||
if ( visible === true ) { | ||
@@ -201,17 +186,12 @@ | ||
let style; | ||
if ( object.isCSS3DSprite ) { | ||
// http://swiftcoder.wordpress.com/2008/11/25/constructing-a-billboard-matrix/ | ||
_matrix.copy( camera.matrixWorldInverse ); | ||
_matrix.transpose(); | ||
if ( object.rotation2D !== 0 ) _matrix.multiply( _matrix2.makeRotationZ( object.rotation2D ) ); | ||
object.matrixWorld.decompose( _position, _quaternion, _scale ); | ||
_matrix.setPosition( _position ); | ||
_matrix.scale( _scale ); | ||
_matrix.elements[ 3 ] = 0; | ||
@@ -231,3 +211,2 @@ _matrix.elements[ 7 ] = 0; | ||
const cachedObject = cache.objects.get( object ); | ||
if ( cachedObject === undefined || cachedObject.style !== style ) { | ||
@@ -234,0 +213,0 @@ |
@@ -14,4 +14,5 @@ ( function () { | ||
} // | ||
} | ||
// | ||
@@ -37,4 +38,5 @@ class RenderableFace { | ||
} // | ||
} | ||
// | ||
@@ -51,3 +53,2 @@ class RenderableVertex { | ||
} | ||
copy( vertex ) { | ||
@@ -60,4 +61,5 @@ | ||
} // | ||
} | ||
// | ||
@@ -78,4 +80,5 @@ class RenderableLine { | ||
} // | ||
} | ||
// | ||
@@ -98,4 +101,5 @@ class RenderableSprite { | ||
} // | ||
} | ||
// | ||
@@ -122,3 +126,2 @@ class Projector { | ||
_modelMatrix; | ||
const _renderData = { | ||
@@ -142,4 +145,5 @@ objects: [], | ||
_linePool = [], | ||
_spritePool = []; // | ||
_spritePool = []; | ||
// | ||
@@ -153,3 +157,2 @@ function RenderList() { | ||
const normalMatrix = new THREE.Matrix3(); | ||
function setObject( value ) { | ||
@@ -183,5 +186,3 @@ | ||
_vertex = getNextVertexInPool(); | ||
_vertex.position.set( x, y, z ); | ||
projectVertex( _vertex ); | ||
@@ -228,7 +229,8 @@ | ||
const v1 = _vertexPool[ a ]; | ||
const v2 = _vertexPool[ b ]; // Clip | ||
const v2 = _vertexPool[ b ]; | ||
// Clip | ||
v1.positionScreen.copy( v1.position ).applyMatrix4( _modelViewProjectionMatrix ); | ||
v2.positionScreen.copy( v2.position ).applyMatrix4( _modelViewProjectionMatrix ); | ||
if ( clipLine( v1.positionScreen, v2.positionScreen ) === true ) { | ||
@@ -241,15 +243,10 @@ | ||
_line.id = object.id; | ||
_line.v1.copy( v1 ); | ||
_line.v2.copy( v2 ); | ||
_line.z = Math.max( v1.positionScreen.z, v2.positionScreen.z ); | ||
_line.renderOrder = object.renderOrder; | ||
_line.material = object.material; | ||
if ( object.material.vertexColors ) { | ||
_line.vertexColors[ 0 ].fromArray( colors, a * 3 ); | ||
_line.vertexColors[ 1 ].fromArray( colors, b * 3 ); | ||
@@ -271,3 +268,2 @@ | ||
if ( checkTriangleVisibility( v1, v2, v3 ) === false ) return; | ||
if ( material.side === THREE.DoubleSide || checkBackfaceCulling( v1, v2, v3 ) === true ) { | ||
@@ -277,22 +273,14 @@ | ||
_face.id = object.id; | ||
_face.v1.copy( v1 ); | ||
_face.v2.copy( v2 ); | ||
_face.v3.copy( v3 ); | ||
_face.z = ( v1.positionScreen.z + v2.positionScreen.z + v3.positionScreen.z ) / 3; | ||
_face.renderOrder = object.renderOrder; // face normal | ||
_face.renderOrder = object.renderOrder; | ||
// face normal | ||
_vector3.subVectors( v3.position, v2.position ); | ||
_vector4.subVectors( v1.position, v2.position ); | ||
_vector3.cross( _vector4 ); | ||
_face.normalModel.copy( _vector3 ); | ||
_face.normalModel.applyMatrix3( normalMatrix ).normalize(); | ||
for ( let i = 0; i < 3; i ++ ) { | ||
@@ -310,3 +298,2 @@ | ||
_face.material = material; | ||
if ( material.vertexColors ) { | ||
@@ -340,7 +327,5 @@ | ||
const renderList = new RenderList(); | ||
function projectObject( object ) { | ||
if ( object.visible === false ) return; | ||
if ( object.isLight ) { | ||
@@ -365,3 +350,2 @@ | ||
const children = object.children; | ||
for ( let i = 0, l = children.length; i < l; i ++ ) { | ||
@@ -380,10 +364,6 @@ | ||
_object.object = object; | ||
_vector3.setFromMatrixPosition( object.matrixWorld ); | ||
_vector3.applyMatrix4( _viewProjectionMatrix ); | ||
_object.z = _vector3.z; | ||
_object.renderOrder = object.renderOrder; | ||
_renderData.objects.push( _object ); | ||
@@ -401,10 +381,8 @@ | ||
if ( camera.parent === null && camera.matrixWorldAutoUpdate === true ) camera.updateMatrixWorld(); | ||
_viewMatrix.copy( camera.matrixWorldInverse ); | ||
_viewProjectionMatrix.multiplyMatrices( camera.projectionMatrix, _viewMatrix ); | ||
_frustum.setFromProjectionMatrix( _viewProjectionMatrix ); | ||
_frustum.setFromProjectionMatrix( _viewProjectionMatrix ); // | ||
// | ||
_objectCount = 0; | ||
@@ -414,3 +392,2 @@ _renderData.objects.length = 0; | ||
projectObject( scene ); | ||
if ( sortObjects === true ) { | ||
@@ -420,7 +397,7 @@ | ||
} // | ||
} | ||
// | ||
const objects = _renderData.objects; | ||
for ( let o = 0, ol = objects.length; o < ol; o ++ ) { | ||
@@ -433,3 +410,2 @@ | ||
_vertexCount = 0; | ||
if ( object.isMesh ) { | ||
@@ -443,3 +419,2 @@ | ||
const positions = attributes.position.array; | ||
for ( let i = 0, l = positions.length; i < l; i += 3 ) { | ||
@@ -451,3 +426,2 @@ | ||
const morphTargets = geometry.morphAttributes.position; | ||
if ( morphTargets !== undefined ) { | ||
@@ -457,3 +431,2 @@ | ||
const morphInfluences = object.morphTargetInfluences; | ||
for ( let t = 0, tl = morphTargets.length; t < tl; t ++ ) { | ||
@@ -464,3 +437,2 @@ | ||
const target = morphTargets[ t ]; | ||
if ( morphTargetsRelative ) { | ||
@@ -491,3 +463,2 @@ | ||
const normals = attributes.normal.array; | ||
for ( let i = 0, l = normals.length; i < l; i += 3 ) { | ||
@@ -504,3 +475,2 @@ | ||
const colors = attributes.color.array; | ||
for ( let i = 0, l = colors.length; i < l; i += 3 ) { | ||
@@ -517,3 +487,2 @@ | ||
const uvs = attributes.uv.array; | ||
for ( let i = 0, l = uvs.length; i < l; i += 2 ) { | ||
@@ -530,3 +499,2 @@ | ||
const indices = geometry.index.array; | ||
if ( groups.length > 0 ) { | ||
@@ -539,3 +507,2 @@ | ||
if ( material === undefined ) continue; | ||
for ( let i = group.start, l = group.start + group.count; i < l; i += 3 ) { | ||
@@ -568,3 +535,2 @@ | ||
if ( material === undefined ) continue; | ||
for ( let i = group.start, l = group.start + group.count; i < l; i += 3 ) { | ||
@@ -593,9 +559,6 @@ | ||
_modelViewProjectionMatrix.multiplyMatrices( _viewProjectionMatrix, _modelMatrix ); | ||
const attributes = geometry.attributes; | ||
if ( attributes.position !== undefined ) { | ||
const positions = attributes.position.array; | ||
for ( let i = 0, l = positions.length; i < l; i += 3 ) { | ||
@@ -610,3 +573,2 @@ | ||
const colors = attributes.color.array; | ||
for ( let i = 0, l = colors.length; i < l; i += 3 ) { | ||
@@ -623,3 +585,2 @@ | ||
const indices = geometry.index.array; | ||
for ( let i = 0, l = indices.length; i < l; i += 2 ) { | ||
@@ -634,3 +595,2 @@ | ||
const step = object.isLineSegments ? 2 : 1; | ||
for ( let i = 0, l = positions.length / 3 - 1; i < l; i += step ) { | ||
@@ -649,15 +609,10 @@ | ||
_modelViewProjectionMatrix.multiplyMatrices( _viewProjectionMatrix, _modelMatrix ); | ||
const attributes = geometry.attributes; | ||
if ( attributes.position !== undefined ) { | ||
const positions = attributes.position.array; | ||
for ( let i = 0, l = positions.length; i < l; i += 3 ) { | ||
_vector4.set( positions[ i ], positions[ i + 1 ], positions[ i + 2 ], 1 ); | ||
_vector4.applyMatrix4( _modelViewProjectionMatrix ); | ||
pushPoint( _vector4, object, camera ); | ||
@@ -672,7 +627,4 @@ | ||
object.modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, object.matrixWorld ); | ||
_vector4.set( _modelMatrix.elements[ 12 ], _modelMatrix.elements[ 13 ], _modelMatrix.elements[ 14 ], 1 ); | ||
_vector4.applyMatrix4( _viewProjectionMatrix ); | ||
pushPoint( _vector4, object, camera ); | ||
@@ -698,3 +650,2 @@ | ||
_vector4.z *= invW; | ||
if ( _vector4.z >= - 1 && _vector4.z <= 1 ) { | ||
@@ -713,3 +664,2 @@ | ||
_sprite.material = object.material; | ||
_renderData.elements.push( _sprite ); | ||
@@ -719,4 +669,5 @@ | ||
} // Pools | ||
} | ||
// Pools | ||
@@ -728,5 +679,3 @@ function getNextObjectInPool() { | ||
const object = new RenderableObject(); | ||
_objectPool.push( object ); | ||
_objectPoolLength ++; | ||
@@ -747,5 +696,3 @@ _objectCount ++; | ||
const vertex = new RenderableVertex(); | ||
_vertexPool.push( vertex ); | ||
_vertexPoolLength ++; | ||
@@ -766,5 +713,3 @@ _vertexCount ++; | ||
const face = new RenderableFace(); | ||
_facePool.push( face ); | ||
_facePoolLength ++; | ||
@@ -785,5 +730,3 @@ _faceCount ++; | ||
const line = new RenderableLine(); | ||
_linePool.push( line ); | ||
_linePoolLength ++; | ||
@@ -804,5 +747,3 @@ _lineCount ++; | ||
const sprite = new RenderableSprite(); | ||
_spritePool.push( sprite ); | ||
_spritePoolLength ++; | ||
@@ -816,4 +757,5 @@ _spriteCount ++; | ||
} // | ||
} | ||
// | ||
@@ -845,3 +787,5 @@ function painterSort( a, b ) { | ||
let alpha1 = 0, | ||
alpha2 = 1; // Calculate the boundary coordinate of each vertex for the near and far clip planes, | ||
alpha2 = 1; | ||
// Calculate the boundary coordinate of each vertex for the near and far clip planes, | ||
// Z = -1 and Z = +1, respectively. | ||
@@ -853,3 +797,2 @@ | ||
bc2far = - s2.z + s2.w; | ||
if ( bc1near >= 0 && bc2near >= 0 && bc1far >= 0 && bc2far >= 0 ) { | ||
@@ -868,2 +811,3 @@ | ||
// The line segment spans at least one clip plane. | ||
if ( bc1near < 0 ) { | ||
@@ -870,0 +814,0 @@ |
@@ -14,3 +14,2 @@ ( function () { | ||
} | ||
class SVGRenderer { | ||
@@ -36,3 +35,2 @@ | ||
_currentStyle; | ||
const _this = this, | ||
@@ -57,3 +55,2 @@ _clipBox = new THREE.Box2(), | ||
_svg = document.createElementNS( 'http://www.w3.org/2000/svg', 'svg' ); | ||
this.domElement = _svg; | ||
@@ -70,3 +67,2 @@ this.autoClear = true; | ||
}; | ||
this.setQuality = function ( quality ) { | ||
@@ -79,3 +75,2 @@ | ||
break; | ||
case 'low': | ||
@@ -103,11 +98,6 @@ _quality = 0; | ||
_svgHeightHalf = _svgHeight / 2; | ||
_svg.setAttribute( 'viewBox', - _svgWidthHalf + ' ' + - _svgHeightHalf + ' ' + _svgWidth + ' ' + _svgHeight ); | ||
_svg.setAttribute( 'width', _svgWidth ); | ||
_svg.setAttribute( 'height', _svgHeight ); | ||
_clipBox.min.set( - _svgWidthHalf, - _svgHeightHalf ); | ||
_clipBox.max.set( _svgWidthHalf, _svgHeightHalf ); | ||
@@ -135,3 +125,2 @@ | ||
_pathCount = 0; | ||
while ( _svg.childNodes.length > 0 ) { | ||
@@ -168,3 +157,2 @@ | ||
const background = scene.background; | ||
if ( background && background.isColor ) { | ||
@@ -183,18 +171,14 @@ | ||
_this.info.render.faces = 0; | ||
_viewMatrix.copy( camera.matrixWorldInverse ); | ||
_viewProjectionMatrix.multiplyMatrices( camera.projectionMatrix, _viewMatrix ); | ||
_renderData = _projector.projectScene( scene, camera, this.sortObjects, this.sortElements ); | ||
_elements = _renderData.elements; | ||
_lights = _renderData.lights; | ||
_normalViewMatrix.getNormalMatrix( camera.matrixWorldInverse ); | ||
calculateLights( _lights ); | ||
calculateLights( _lights ); // reset accumulated path | ||
// reset accumulated path | ||
_currentPath = ''; | ||
_currentStyle = ''; | ||
for ( let e = 0, el = _elements.length; e < el; e ++ ) { | ||
@@ -205,5 +189,3 @@ | ||
if ( material === undefined || material.opacity === 0 ) continue; | ||
_elemBox.makeEmpty(); | ||
if ( element instanceof THREE.RenderableSprite ) { | ||
@@ -224,5 +206,3 @@ | ||
_v2.positionScreen.y *= - _svgHeightHalf; | ||
_elemBox.setFromPoints( [ _v1.positionScreen, _v2.positionScreen ] ); | ||
if ( _clipBox.intersectsBox( _elemBox ) === true ) { | ||
@@ -248,3 +228,2 @@ | ||
_v3.positionScreen.y *= - _svgHeightHalf; | ||
if ( this.overdraw > 0 ) { | ||
@@ -259,3 +238,2 @@ | ||
_elemBox.setFromPoints( [ _v1.positionScreen, _v2.positionScreen, _v3.positionScreen ] ); | ||
if ( _clipBox.intersectsBox( _elemBox ) === true ) { | ||
@@ -278,5 +256,3 @@ | ||
_vector3.setFromMatrixPosition( object.matrixWorld ); | ||
_vector3.applyMatrix4( _viewProjectionMatrix ); | ||
if ( _vector3.z < - 1 || _vector3.z > 1 ) return; | ||
@@ -287,3 +263,2 @@ const x = _vector3.x * _svgWidthHalf; | ||
node.setAttribute( 'transform', 'translate(' + x + ',' + y + ')' ); | ||
_svg.appendChild( node ); | ||
@@ -300,7 +275,4 @@ | ||
_ambientLight.setRGB( 0, 0, 0 ); | ||
_directionalLights.setRGB( 0, 0, 0 ); | ||
_pointLights.setRGB( 0, 0, 0 ); | ||
for ( let l = 0, ll = lights.length; l < ll; l ++ ) { | ||
@@ -310,3 +282,2 @@ | ||
const lightColor = light.color; | ||
if ( light.isAmbientLight ) { | ||
@@ -342,7 +313,5 @@ | ||
const lightColor = light.color; | ||
if ( light.isDirectionalLight ) { | ||
const lightPosition = _vector3.setFromMatrixPosition( light.matrixWorld ).normalize(); | ||
let amount = normal.dot( lightPosition ); | ||
@@ -358,3 +327,2 @@ if ( amount <= 0 ) continue; | ||
const lightPosition = _vector3.setFromMatrixPosition( light.matrixWorld ); | ||
let amount = normal.dot( _vector3.subVectors( lightPosition, position ).normalize() ); | ||
@@ -379,3 +347,2 @@ if ( amount <= 0 ) continue; | ||
let scaleY = element.scale.y * _svgHeightHalf; | ||
if ( material.isPointsMaterial ) { | ||
@@ -390,3 +357,2 @@ | ||
let style = ''; | ||
if ( material.isSpriteMaterial || material.isPointsMaterial ) { | ||
@@ -405,7 +371,5 @@ | ||
const path = 'M' + convert( v1.positionScreen.x ) + ',' + convert( v1.positionScreen.y ) + 'L' + convert( v2.positionScreen.x ) + ',' + convert( v2.positionScreen.y ); | ||
if ( material.isLineBasicMaterial ) { | ||
let style = 'fill:none;stroke:' + material.color.getStyle() + ';stroke-opacity:' + material.opacity + ';stroke-width:' + material.linewidth + ';stroke-linecap:' + material.linecap; | ||
if ( material.isLineDashedMaterial ) { | ||
@@ -429,7 +393,5 @@ | ||
let style = ''; | ||
if ( material.isMeshBasicMaterial ) { | ||
_color.copy( material.color ); | ||
if ( material.vertexColors ) { | ||
@@ -444,3 +406,2 @@ | ||
_diffuseColor.copy( material.color ); | ||
if ( material.vertexColors ) { | ||
@@ -453,7 +414,4 @@ | ||
_color.copy( _ambientLight ); | ||
_centroid.copy( v1.positionWorld ).add( v2.positionWorld ).add( v3.positionWorld ).divideScalar( 3 ); | ||
calculateLight( _lights, _centroid, element.normalModel, _color ); | ||
_color.multiply( _diffuseColor ).add( material.emissive ); | ||
@@ -464,3 +422,2 @@ | ||
_normal.copy( element.normalModel ).applyMatrix3( _normalViewMatrix ).normalize(); | ||
_color.setRGB( _normal.x, _normal.y, _normal.z ).multiplyScalar( 0.5 ).addScalar( 0.5 ); | ||
@@ -482,4 +439,5 @@ | ||
} // Hide anti-alias gaps | ||
} | ||
// Hide anti-alias gaps | ||
@@ -523,7 +481,4 @@ function expand( v1, v2, pixels ) { | ||
_svgNode = getPathNode( _pathCount ++ ); | ||
_svgNode.setAttribute( 'd', _currentPath ); | ||
_svgNode.setAttribute( 'style', _currentStyle ); | ||
_svg.appendChild( _svgNode ); | ||
@@ -543,3 +498,2 @@ | ||
_svgPathPool[ id ] = document.createElementNS( 'http://www.w3.org/2000/svg', 'path' ); | ||
if ( _quality == 0 ) { | ||
@@ -546,0 +500,0 @@ |
@@ -10,2 +10,3 @@ ( function () { | ||
*/ | ||
const ACESFilmicToneMappingShader = { | ||
@@ -20,5 +21,3 @@ uniforms: { | ||
}, | ||
vertexShader: | ||
/* glsl */ | ||
` | ||
vertexShader: /* glsl */` | ||
@@ -33,5 +32,3 @@ varying vec2 vUv; | ||
}`, | ||
fragmentShader: | ||
/* glsl */ | ||
` | ||
fragmentShader: /* glsl */` | ||
@@ -38,0 +35,0 @@ #define saturate(a) clamp( a, 0.0, 1.0 ) |
@@ -8,2 +8,3 @@ ( function () { | ||
*/ | ||
const AfterimageShader = { | ||
@@ -21,5 +22,3 @@ uniforms: { | ||
}, | ||
vertexShader: | ||
/* glsl */ | ||
` | ||
vertexShader: /* glsl */` | ||
@@ -34,5 +33,3 @@ varying vec2 vUv; | ||
}`, | ||
fragmentShader: | ||
/* glsl */ | ||
` | ||
fragmentShader: /* glsl */` | ||
@@ -39,0 +36,0 @@ uniform float damp; |
@@ -6,7 +6,6 @@ ( function () { | ||
*/ | ||
const BasicShader = { | ||
uniforms: {}, | ||
vertexShader: | ||
/* glsl */ | ||
` | ||
vertexShader: /* glsl */` | ||
@@ -18,5 +17,3 @@ void main() { | ||
}`, | ||
fragmentShader: | ||
/* glsl */ | ||
` | ||
fragmentShader: /* glsl */` | ||
@@ -23,0 +20,0 @@ void main() { |
@@ -8,2 +8,3 @@ ( function () { | ||
*/ | ||
const BleachBypassShader = { | ||
@@ -18,5 +19,3 @@ uniforms: { | ||
}, | ||
vertexShader: | ||
/* glsl */ | ||
` | ||
vertexShader: /* glsl */` | ||
@@ -31,5 +30,3 @@ varying vec2 vUv; | ||
}`, | ||
fragmentShader: | ||
/* glsl */ | ||
` | ||
fragmentShader: /* glsl */` | ||
@@ -36,0 +33,0 @@ uniform float opacity; |
@@ -6,2 +6,3 @@ ( function () { | ||
*/ | ||
const BlendShader = { | ||
@@ -22,5 +23,3 @@ uniforms: { | ||
}, | ||
vertexShader: | ||
/* glsl */ | ||
` | ||
vertexShader: /* glsl */` | ||
@@ -35,5 +34,3 @@ varying vec2 vUv; | ||
}`, | ||
fragmentShader: | ||
/* glsl */ | ||
` | ||
fragmentShader: /* glsl */` | ||
@@ -40,0 +37,0 @@ uniform float opacity; |
@@ -8,2 +8,3 @@ ( function () { | ||
*/ | ||
const BokehShader = { | ||
@@ -40,5 +41,3 @@ defines: { | ||
}, | ||
vertexShader: | ||
/* glsl */ | ||
` | ||
vertexShader: /* glsl */` | ||
@@ -53,5 +52,3 @@ varying vec2 vUv; | ||
}`, | ||
fragmentShader: | ||
/* glsl */ | ||
` | ||
fragmentShader: /* glsl */` | ||
@@ -58,0 +55,0 @@ #include <common> |
@@ -10,3 +10,2 @@ ( function () { | ||
*/ | ||
const BokehShader = { | ||
@@ -84,5 +83,3 @@ uniforms: { | ||
}, | ||
vertexShader: | ||
/* glsl */ | ||
` | ||
vertexShader: /* glsl */` | ||
@@ -97,5 +94,3 @@ varying vec2 vUv; | ||
}`, | ||
fragmentShader: | ||
/* glsl */ | ||
` | ||
fragmentShader: /* glsl */` | ||
@@ -397,5 +392,3 @@ #include <common> | ||
}, | ||
vertexShader: | ||
/* glsl */ | ||
` | ||
vertexShader: /* glsl */` | ||
@@ -412,5 +405,3 @@ varying float vViewZDepth; | ||
}`, | ||
fragmentShader: | ||
/* glsl */ | ||
` | ||
fragmentShader: /* glsl */` | ||
@@ -417,0 +408,0 @@ uniform float mNear; |
@@ -9,2 +9,3 @@ ( function () { | ||
*/ | ||
const BrightnessContrastShader = { | ||
@@ -22,5 +23,3 @@ uniforms: { | ||
}, | ||
vertexShader: | ||
/* glsl */ | ||
` | ||
vertexShader: /* glsl */` | ||
@@ -36,5 +35,3 @@ varying vec2 vUv; | ||
}`, | ||
fragmentShader: | ||
/* glsl */ | ||
` | ||
fragmentShader: /* glsl */` | ||
@@ -41,0 +38,0 @@ uniform sampler2D tDiffuse; |
@@ -22,5 +22,3 @@ ( function () { | ||
}, | ||
vertexShader: | ||
/* glsl */ | ||
` | ||
vertexShader: /* glsl */` | ||
@@ -36,5 +34,3 @@ varying vec2 vUv; | ||
}`, | ||
fragmentShader: | ||
/* glsl */ | ||
` | ||
fragmentShader: /* glsl */` | ||
@@ -41,0 +37,0 @@ uniform sampler2D tDiffuse; |
@@ -16,5 +16,3 @@ ( function () { | ||
}, | ||
vertexShader: | ||
/* glsl */ | ||
` | ||
vertexShader: /* glsl */` | ||
@@ -29,5 +27,3 @@ varying vec2 vUv; | ||
}`, | ||
fragmentShader: | ||
/* glsl */ | ||
` | ||
fragmentShader: /* glsl */` | ||
@@ -34,0 +30,0 @@ uniform vec3 color; |
@@ -24,5 +24,3 @@ ( function () { | ||
}, | ||
vertexShader: | ||
/* glsl */ | ||
` | ||
vertexShader: /* glsl */` | ||
@@ -39,5 +37,3 @@ uniform vec2 uImageIncrement; | ||
}`, | ||
fragmentShader: | ||
/* glsl */ | ||
` | ||
fragmentShader: /* glsl */` | ||
@@ -69,2 +65,3 @@ uniform float cKernel[ KERNEL_SIZE_INT ]; | ||
// We lop off the sqrt(2 * pi) * sigma term, since we're going to normalize anyway. | ||
const kMaxKernelSize = 25; | ||
@@ -76,3 +73,2 @@ let kernelSize = 2 * Math.ceil( sigma * 3.0 ) + 1; | ||
let sum = 0.0; | ||
for ( let i = 0; i < kernelSize; ++ i ) { | ||
@@ -83,7 +79,7 @@ | ||
} // normalize the kernel | ||
} | ||
// normalize the kernel | ||
for ( let i = 0; i < kernelSize; ++ i ) values[ i ] /= sum; | ||
return values; | ||
@@ -93,3 +89,2 @@ | ||
}; | ||
function gauss( x, sigma ) { | ||
@@ -96,0 +91,0 @@ |
@@ -6,2 +6,3 @@ ( function () { | ||
*/ | ||
const CopyShader = { | ||
@@ -16,5 +17,3 @@ uniforms: { | ||
}, | ||
vertexShader: | ||
/* glsl */ | ||
` | ||
vertexShader: /* glsl */` | ||
@@ -29,5 +28,3 @@ varying vec2 vUv; | ||
}`, | ||
fragmentShader: | ||
/* glsl */ | ||
` | ||
fragmentShader: /* glsl */` | ||
@@ -34,0 +31,0 @@ uniform float opacity; |
@@ -39,5 +39,3 @@ ( function () { | ||
}, | ||
vertexShader: | ||
/* glsl */ | ||
` | ||
vertexShader: /* glsl */` | ||
@@ -57,5 +55,3 @@ #include <common> | ||
}`, | ||
fragmentShader: | ||
/* glsl */ | ||
` | ||
fragmentShader: /* glsl */` | ||
@@ -140,3 +136,2 @@ #include <common> | ||
const weights = []; | ||
for ( let i = 0; i <= kernelRadius; i ++ ) { | ||
@@ -154,3 +149,2 @@ | ||
const offsets = []; | ||
for ( let i = 0; i <= kernelRadius; i ++ ) { | ||
@@ -174,3 +168,2 @@ | ||
}; | ||
function gaussian( x, stdDev ) { | ||
@@ -177,0 +170,0 @@ |
@@ -12,2 +12,3 @@ ( function () { | ||
*/ | ||
const DigitalGlitch = { | ||
@@ -54,5 +55,3 @@ uniforms: { | ||
}, | ||
vertexShader: | ||
/* glsl */ | ||
` | ||
vertexShader: /* glsl */` | ||
@@ -64,5 +63,3 @@ varying vec2 vUv; | ||
}`, | ||
fragmentShader: | ||
/* glsl */ | ||
` | ||
fragmentShader: /* glsl */` | ||
@@ -69,0 +66,0 @@ uniform int byp; //should we apply the glitch ? |
@@ -8,2 +8,3 @@ ( function () { | ||
*/ | ||
const DOFMipMapShader = { | ||
@@ -24,5 +25,3 @@ uniforms: { | ||
}, | ||
vertexShader: | ||
/* glsl */ | ||
` | ||
vertexShader: /* glsl */` | ||
@@ -37,5 +36,3 @@ varying vec2 vUv; | ||
}`, | ||
fragmentShader: | ||
/* glsl */ | ||
` | ||
fragmentShader: /* glsl */` | ||
@@ -42,0 +39,0 @@ uniform float focus; |
@@ -27,5 +27,3 @@ ( function () { | ||
}, | ||
vertexShader: | ||
/* glsl */ | ||
` | ||
vertexShader: /* glsl */` | ||
@@ -40,5 +38,3 @@ varying vec2 vUv; | ||
}`, | ||
fragmentShader: | ||
/* glsl */ | ||
` | ||
fragmentShader: /* glsl */` | ||
@@ -45,0 +41,0 @@ uniform vec2 center; |
@@ -22,2 +22,3 @@ ( function () { | ||
*/ | ||
const FilmShader = { | ||
@@ -44,5 +45,3 @@ uniforms: { | ||
}, | ||
vertexShader: | ||
/* glsl */ | ||
` | ||
vertexShader: /* glsl */` | ||
@@ -57,5 +56,3 @@ varying vec2 vUv; | ||
}`, | ||
fragmentShader: | ||
/* glsl */ | ||
` | ||
fragmentShader: /* glsl */` | ||
@@ -62,0 +59,0 @@ #include <common> |
@@ -8,2 +8,3 @@ ( function () { | ||
*/ | ||
const FocusShader = { | ||
@@ -27,5 +28,3 @@ uniforms: { | ||
}, | ||
vertexShader: | ||
/* glsl */ | ||
` | ||
vertexShader: /* glsl */` | ||
@@ -40,5 +39,3 @@ varying vec2 vUv; | ||
}`, | ||
fragmentShader: | ||
/* glsl */ | ||
` | ||
fragmentShader: /* glsl */` | ||
@@ -45,0 +42,0 @@ uniform float screenWidth; |
@@ -19,5 +19,3 @@ ( function () { | ||
}, | ||
vertexShader: | ||
/* glsl */ | ||
` | ||
vertexShader: /* glsl */` | ||
@@ -32,5 +30,3 @@ varying vec2 vUv; | ||
}`, | ||
fragmentShader: | ||
/* glsl */ | ||
` | ||
fragmentShader: /* glsl */` | ||
@@ -37,0 +33,0 @@ uniform sampler2D tDiffuse; |
@@ -20,5 +20,3 @@ ( function () { | ||
}, | ||
vertexShader: | ||
/* glsl */ | ||
` | ||
vertexShader: /* glsl */` | ||
@@ -25,0 +23,0 @@ varying vec2 vUv; |
@@ -7,2 +7,3 @@ ( function () { | ||
*/ | ||
const GammaCorrectionShader = { | ||
@@ -14,5 +15,3 @@ uniforms: { | ||
}, | ||
vertexShader: | ||
/* glsl */ | ||
` | ||
vertexShader: /* glsl */` | ||
@@ -27,5 +26,3 @@ varying vec2 vUv; | ||
}`, | ||
fragmentShader: | ||
/* glsl */ | ||
` | ||
fragmentShader: /* glsl */` | ||
@@ -32,0 +29,0 @@ uniform sampler2D tDiffuse; |
@@ -27,5 +27,3 @@ ( function () { | ||
}, | ||
vertexShader: | ||
/* glsl */ | ||
` | ||
vertexShader: /* glsl */` | ||
@@ -40,5 +38,3 @@ varying vec2 vUv; | ||
}`, | ||
fragmentShader: | ||
/* glsl */ | ||
` | ||
fragmentShader: /* glsl */` | ||
@@ -55,2 +51,3 @@ varying vec2 vUv; | ||
}; | ||
/** | ||
@@ -83,5 +80,3 @@ * The god-ray generation shader. | ||
}, | ||
vertexShader: | ||
/* glsl */ | ||
` | ||
vertexShader: /* glsl */` | ||
@@ -96,5 +91,3 @@ varying vec2 vUv; | ||
}`, | ||
fragmentShader: | ||
/* glsl */ | ||
` | ||
fragmentShader: /* glsl */` | ||
@@ -185,2 +178,3 @@ #define TAPS_PER_PASS 6.0 | ||
}; | ||
/** | ||
@@ -203,5 +197,3 @@ * Additively applies god rays from texture tGodRays to a background (tColors). | ||
}, | ||
vertexShader: | ||
/* glsl */ | ||
` | ||
vertexShader: /* glsl */` | ||
@@ -216,5 +208,3 @@ varying vec2 vUv; | ||
}`, | ||
fragmentShader: | ||
/* glsl */ | ||
` | ||
fragmentShader: /* glsl */` | ||
@@ -239,2 +229,3 @@ varying vec2 vUv; | ||
}; | ||
/** | ||
@@ -260,5 +251,3 @@ * A dodgy sun/sky shader. Makes a bright spot at the sun location. Would be | ||
}, | ||
vertexShader: | ||
/* glsl */ | ||
` | ||
vertexShader: /* glsl */` | ||
@@ -273,5 +262,3 @@ varying vec2 vUv; | ||
}`, | ||
fragmentShader: | ||
/* glsl */ | ||
` | ||
fragmentShader: /* glsl */` | ||
@@ -278,0 +265,0 @@ varying vec2 vUv; |
@@ -9,2 +9,3 @@ ( function () { | ||
*/ | ||
const HalftoneShader = { | ||
@@ -52,5 +53,3 @@ uniforms: { | ||
}, | ||
vertexShader: | ||
/* glsl */ | ||
` | ||
vertexShader: /* glsl */` | ||
@@ -65,5 +64,3 @@ varying vec2 vUV; | ||
}`, | ||
fragmentShader: | ||
/* glsl */ | ||
` | ||
fragmentShader: /* glsl */` | ||
@@ -70,0 +67,0 @@ #define SQRT2_MINUS_ONE 0.41421356 |
@@ -11,2 +11,3 @@ ( function () { | ||
*/ | ||
const HorizontalBlurShader = { | ||
@@ -21,5 +22,3 @@ uniforms: { | ||
}, | ||
vertexShader: | ||
/* glsl */ | ||
` | ||
vertexShader: /* glsl */` | ||
@@ -34,5 +33,3 @@ varying vec2 vUv; | ||
}`, | ||
fragmentShader: | ||
/* glsl */ | ||
` | ||
fragmentShader: /* glsl */` | ||
@@ -39,0 +36,0 @@ uniform sampler2D tDiffuse; |
@@ -11,2 +11,3 @@ ( function () { | ||
*/ | ||
const HorizontalTiltShiftShader = { | ||
@@ -24,5 +25,3 @@ uniforms: { | ||
}, | ||
vertexShader: | ||
/* glsl */ | ||
` | ||
vertexShader: /* glsl */` | ||
@@ -37,5 +36,3 @@ varying vec2 vUv; | ||
}`, | ||
fragmentShader: | ||
/* glsl */ | ||
` | ||
fragmentShader: /* glsl */` | ||
@@ -42,0 +39,0 @@ uniform sampler2D tDiffuse; |
@@ -9,2 +9,3 @@ ( function () { | ||
*/ | ||
const HueSaturationShader = { | ||
@@ -22,5 +23,3 @@ uniforms: { | ||
}, | ||
vertexShader: | ||
/* glsl */ | ||
` | ||
vertexShader: /* glsl */` | ||
@@ -36,5 +35,3 @@ varying vec2 vUv; | ||
}`, | ||
fragmentShader: | ||
/* glsl */ | ||
` | ||
fragmentShader: /* glsl */` | ||
@@ -41,0 +38,0 @@ uniform sampler2D tDiffuse; |
@@ -12,2 +12,3 @@ ( function () { | ||
*/ | ||
const KaleidoShader = { | ||
@@ -25,5 +26,3 @@ uniforms: { | ||
}, | ||
vertexShader: | ||
/* glsl */ | ||
` | ||
vertexShader: /* glsl */` | ||
@@ -38,5 +37,3 @@ varying vec2 vUv; | ||
}`, | ||
fragmentShader: | ||
/* glsl */ | ||
` | ||
fragmentShader: /* glsl */` | ||
@@ -43,0 +40,0 @@ uniform sampler2D tDiffuse; |
@@ -27,5 +27,3 @@ ( function () { | ||
}, | ||
vertexShader: | ||
/* glsl */ | ||
` | ||
vertexShader: /* glsl */` | ||
@@ -41,5 +39,3 @@ varying vec2 vUv; | ||
}`, | ||
fragmentShader: | ||
/* glsl */ | ||
` | ||
fragmentShader: /* glsl */` | ||
@@ -46,0 +42,0 @@ uniform sampler2D tDiffuse; |
@@ -7,2 +7,3 @@ ( function () { | ||
*/ | ||
const LuminosityShader = { | ||
@@ -14,5 +15,3 @@ uniforms: { | ||
}, | ||
vertexShader: | ||
/* glsl */ | ||
` | ||
vertexShader: /* glsl */` | ||
@@ -28,5 +27,3 @@ varying vec2 vUv; | ||
}`, | ||
fragmentShader: | ||
/* glsl */ | ||
` | ||
fragmentShader: /* glsl */` | ||
@@ -33,0 +30,0 @@ #include <common> |
@@ -9,2 +9,3 @@ ( function () { | ||
*/ | ||
const MirrorShader = { | ||
@@ -19,5 +20,3 @@ uniforms: { | ||
}, | ||
vertexShader: | ||
/* glsl */ | ||
` | ||
vertexShader: /* glsl */` | ||
@@ -32,5 +31,3 @@ varying vec2 vUv; | ||
}`, | ||
fragmentShader: | ||
/* glsl */ | ||
` | ||
fragmentShader: /* glsl */` | ||
@@ -37,0 +34,0 @@ uniform sampler2D tDiffuse; |
@@ -17,5 +17,3 @@ ( function () { | ||
*/ | ||
const lights_mmd_toon_pars_fragment = | ||
/* glsl */ | ||
` | ||
const lights_mmd_toon_pars_fragment = /* glsl */` | ||
varying vec3 vViewPosition; | ||
@@ -53,5 +51,3 @@ | ||
`; | ||
const mmd_toon_matcap_fragment = | ||
/* glsl */ | ||
` | ||
const mmd_toon_matcap_fragment = /* glsl */` | ||
#ifdef USE_MATCAP | ||
@@ -58,0 +54,0 @@ |
@@ -23,5 +23,3 @@ ( function () { | ||
}, | ||
vertexShader: | ||
/* glsl */ | ||
` | ||
vertexShader: /* glsl */` | ||
@@ -36,5 +34,3 @@ varying vec2 vUv; | ||
}`, | ||
fragmentShader: | ||
/* glsl */ | ||
` | ||
fragmentShader: /* glsl */` | ||
@@ -41,0 +37,0 @@ uniform float height; |
@@ -6,2 +6,3 @@ ( function () { | ||
*/ | ||
const PixelShader = { | ||
@@ -19,5 +20,3 @@ uniforms: { | ||
}, | ||
vertexShader: | ||
/* glsl */ | ||
` | ||
vertexShader: /* glsl */` | ||
@@ -32,5 +31,3 @@ varying highp vec2 vUv; | ||
}`, | ||
fragmentShader: | ||
/* glsl */ | ||
` | ||
fragmentShader: /* glsl */` | ||
@@ -37,0 +34,0 @@ uniform sampler2D tDiffuse; |
@@ -12,2 +12,3 @@ ( function () { | ||
*/ | ||
const RGBShiftShader = { | ||
@@ -25,5 +26,3 @@ uniforms: { | ||
}, | ||
vertexShader: | ||
/* glsl */ | ||
` | ||
vertexShader: /* glsl */` | ||
@@ -38,5 +37,3 @@ varying vec2 vUv; | ||
}`, | ||
fragmentShader: | ||
/* glsl */ | ||
` | ||
fragmentShader: /* glsl */` | ||
@@ -43,0 +40,0 @@ uniform sampler2D tDiffuse; |
@@ -60,5 +60,3 @@ ( function () { | ||
}, | ||
vertexShader: | ||
/* glsl */ | ||
` | ||
vertexShader: /* glsl */` | ||
@@ -71,5 +69,3 @@ varying vec2 vUv; | ||
}`, | ||
fragmentShader: | ||
/* glsl */ | ||
` | ||
fragmentShader: /* glsl */` | ||
@@ -76,0 +72,0 @@ #include <common> |
@@ -8,2 +8,3 @@ ( function () { | ||
*/ | ||
const SepiaShader = { | ||
@@ -18,5 +19,3 @@ uniforms: { | ||
}, | ||
vertexShader: | ||
/* glsl */ | ||
` | ||
vertexShader: /* glsl */` | ||
@@ -31,5 +30,3 @@ varying vec2 vUv; | ||
}`, | ||
fragmentShader: | ||
/* glsl */ | ||
` | ||
fragmentShader: /* glsl */` | ||
@@ -36,0 +33,0 @@ uniform float amount; |
@@ -21,5 +21,3 @@ ( function () { | ||
}, | ||
vertexShader: | ||
/* glsl */ | ||
` | ||
vertexShader: /* glsl */` | ||
@@ -46,5 +44,3 @@ uniform vec2 resolution; | ||
}`, | ||
fragmentShader: | ||
/* glsl */ | ||
` | ||
fragmentShader: /* glsl */` | ||
@@ -135,5 +131,3 @@ uniform sampler2D tDiffuse; | ||
}, | ||
vertexShader: | ||
/* glsl */ | ||
` | ||
vertexShader: /* glsl */` | ||
@@ -167,5 +161,3 @@ uniform vec2 resolution; | ||
}`, | ||
fragmentShader: | ||
/* glsl */ | ||
` | ||
fragmentShader: /* glsl */` | ||
@@ -384,5 +376,3 @@ #define SMAASampleLevelZeroOffset( tex, coord, offset ) texture2D( tex, coord + float( offset ) * resolution, 0.0 ) | ||
}, | ||
vertexShader: | ||
/* glsl */ | ||
` | ||
vertexShader: /* glsl */` | ||
@@ -408,5 +398,3 @@ uniform vec2 resolution; | ||
}`, | ||
fragmentShader: | ||
/* glsl */ | ||
` | ||
fragmentShader: /* glsl */` | ||
@@ -413,0 +401,0 @@ uniform sampler2D tDiffuse; |
@@ -19,5 +19,3 @@ ( function () { | ||
}, | ||
vertexShader: | ||
/* glsl */ | ||
` | ||
vertexShader: /* glsl */` | ||
@@ -33,5 +31,3 @@ varying vec2 vUv; | ||
}`, | ||
fragmentShader: | ||
/* glsl */ | ||
` | ||
fragmentShader: /* glsl */` | ||
@@ -38,0 +34,0 @@ uniform sampler2D tDiffuse; |
@@ -56,5 +56,3 @@ ( function () { | ||
}, | ||
vertexShader: | ||
/* glsl */ | ||
` | ||
vertexShader: /* glsl */` | ||
@@ -70,5 +68,3 @@ varying vec2 vUv; | ||
}`, | ||
fragmentShader: | ||
/* glsl */ | ||
` | ||
fragmentShader: /* glsl */` | ||
@@ -75,0 +71,0 @@ uniform sampler2D tDiffuse; |
@@ -58,5 +58,3 @@ ( function () { | ||
}, | ||
vertexShader: | ||
/* glsl */ | ||
` | ||
vertexShader: /* glsl */` | ||
@@ -74,5 +72,3 @@ varying vec2 vUv; | ||
`, | ||
fragmentShader: | ||
/* glsl */ | ||
` | ||
fragmentShader: /* glsl */` | ||
// precision highp float; | ||
@@ -271,5 +267,3 @@ precision highp sampler2D; | ||
}, | ||
vertexShader: | ||
/* glsl */ | ||
` | ||
vertexShader: /* glsl */` | ||
@@ -286,5 +280,3 @@ varying vec2 vUv; | ||
`, | ||
fragmentShader: | ||
/* glsl */ | ||
` | ||
fragmentShader: /* glsl */` | ||
@@ -339,5 +331,3 @@ uniform sampler2D tDepth; | ||
}, | ||
vertexShader: | ||
/* glsl */ | ||
` | ||
vertexShader: /* glsl */` | ||
@@ -354,5 +344,3 @@ varying vec2 vUv; | ||
`, | ||
fragmentShader: | ||
/* glsl */ | ||
` | ||
fragmentShader: /* glsl */` | ||
@@ -359,0 +347,0 @@ uniform sampler2D tDiffuse; |
@@ -9,2 +9,3 @@ ( function () { | ||
*/ | ||
const TechnicolorShader = { | ||
@@ -16,5 +17,3 @@ uniforms: { | ||
}, | ||
vertexShader: | ||
/* glsl */ | ||
` | ||
vertexShader: /* glsl */` | ||
@@ -29,5 +28,3 @@ varying vec2 vUv; | ||
}`, | ||
fragmentShader: | ||
/* glsl */ | ||
` | ||
fragmentShader: /* glsl */` | ||
@@ -34,0 +31,0 @@ uniform sampler2D tDiffuse; |
@@ -6,2 +6,3 @@ ( function () { | ||
*/ | ||
const ToneMapShader = { | ||
@@ -28,5 +29,3 @@ uniforms: { | ||
}, | ||
vertexShader: | ||
/* glsl */ | ||
` | ||
vertexShader: /* glsl */` | ||
@@ -41,5 +40,3 @@ varying vec2 vUv; | ||
}`, | ||
fragmentShader: | ||
/* glsl */ | ||
` | ||
fragmentShader: /* glsl */` | ||
@@ -46,0 +43,0 @@ #include <common> |
@@ -27,5 +27,3 @@ ( function () { | ||
}, | ||
vertexShader: | ||
/* glsl */ | ||
` | ||
vertexShader: /* glsl */` | ||
@@ -49,5 +47,3 @@ varying vec3 vNormal; | ||
}`, | ||
fragmentShader: | ||
/* glsl */ | ||
` | ||
fragmentShader: /* glsl */` | ||
@@ -116,5 +112,3 @@ uniform vec3 uBaseColor; | ||
}, | ||
vertexShader: | ||
/* glsl */ | ||
` | ||
vertexShader: /* glsl */` | ||
@@ -129,5 +123,3 @@ varying vec3 vNormal; | ||
}`, | ||
fragmentShader: | ||
/* glsl */ | ||
` | ||
fragmentShader: /* glsl */` | ||
@@ -195,5 +187,3 @@ uniform vec3 uBaseColor; | ||
}, | ||
vertexShader: | ||
/* glsl */ | ||
` | ||
vertexShader: /* glsl */` | ||
@@ -208,5 +198,3 @@ varying vec3 vNormal; | ||
}`, | ||
fragmentShader: | ||
/* glsl */ | ||
` | ||
fragmentShader: /* glsl */` | ||
@@ -293,5 +281,3 @@ uniform vec3 uBaseColor; | ||
}, | ||
vertexShader: | ||
/* glsl */ | ||
` | ||
vertexShader: /* glsl */` | ||
@@ -306,5 +292,3 @@ varying vec3 vNormal; | ||
}`, | ||
fragmentShader: | ||
/* glsl */ | ||
` | ||
fragmentShader: /* glsl */` | ||
@@ -311,0 +295,0 @@ uniform vec3 uBaseColor; |
@@ -22,5 +22,3 @@ ( function () { | ||
}, | ||
vertexShader: | ||
/* glsl */ | ||
` | ||
vertexShader: /* glsl */` | ||
@@ -35,5 +33,3 @@ varying vec2 vUv; | ||
}`, | ||
fragmentShader: | ||
/* glsl */ | ||
` | ||
fragmentShader: /* glsl */` | ||
@@ -40,0 +36,0 @@ #include <common> |
@@ -7,2 +7,3 @@ ( function () { | ||
*/ | ||
const UnpackDepthRGBAShader = { | ||
@@ -17,5 +18,3 @@ uniforms: { | ||
}, | ||
vertexShader: | ||
/* glsl */ | ||
` | ||
vertexShader: /* glsl */` | ||
@@ -30,5 +29,3 @@ varying vec2 vUv; | ||
}`, | ||
fragmentShader: | ||
/* glsl */ | ||
` | ||
fragmentShader: /* glsl */` | ||
@@ -35,0 +32,0 @@ uniform float opacity; |
@@ -11,2 +11,3 @@ ( function () { | ||
*/ | ||
const VerticalBlurShader = { | ||
@@ -21,5 +22,3 @@ uniforms: { | ||
}, | ||
vertexShader: | ||
/* glsl */ | ||
` | ||
vertexShader: /* glsl */` | ||
@@ -34,5 +33,3 @@ varying vec2 vUv; | ||
}`, | ||
fragmentShader: | ||
/* glsl */ | ||
` | ||
fragmentShader: /* glsl */` | ||
@@ -39,0 +36,0 @@ uniform sampler2D tDiffuse; |
@@ -11,2 +11,3 @@ ( function () { | ||
*/ | ||
const VerticalTiltShiftShader = { | ||
@@ -24,5 +25,3 @@ uniforms: { | ||
}, | ||
vertexShader: | ||
/* glsl */ | ||
` | ||
vertexShader: /* glsl */` | ||
@@ -37,5 +36,3 @@ varying vec2 vUv; | ||
}`, | ||
fragmentShader: | ||
/* glsl */ | ||
` | ||
fragmentShader: /* glsl */` | ||
@@ -42,0 +39,0 @@ uniform sampler2D tDiffuse; |
@@ -8,2 +8,3 @@ ( function () { | ||
*/ | ||
const VignetteShader = { | ||
@@ -21,5 +22,3 @@ uniforms: { | ||
}, | ||
vertexShader: | ||
/* glsl */ | ||
` | ||
vertexShader: /* glsl */` | ||
@@ -34,5 +33,3 @@ varying vec2 vUv; | ||
}`, | ||
fragmentShader: | ||
/* glsl */ | ||
` | ||
fragmentShader: /* glsl */` | ||
@@ -39,0 +36,0 @@ uniform float offset; |
@@ -30,5 +30,3 @@ ( function () { | ||
}, | ||
vertexShader: | ||
/* glsl */ | ||
` | ||
vertexShader: /* glsl */` | ||
@@ -64,5 +62,3 @@ varying vec4 v_nearpos; | ||
}`, | ||
fragmentShader: | ||
/* glsl */ | ||
` | ||
fragmentShader: /* glsl */` | ||
@@ -69,0 +65,0 @@ precision highp float; |
@@ -21,5 +21,3 @@ ( function () { | ||
}, | ||
vertexShader: | ||
/* glsl */ | ||
` | ||
vertexShader: /* glsl */` | ||
@@ -40,5 +38,3 @@ uniform mat4 textureMatrix; | ||
}`, | ||
fragmentShader: | ||
/* glsl */ | ||
` | ||
fragmentShader: /* glsl */` | ||
@@ -45,0 +41,0 @@ uniform vec3 color; |
@@ -13,3 +13,2 @@ ( function () { | ||
context.fillRect( 0, 0, width, height ); | ||
for ( let i = 0; i < 4000; i ++ ) { | ||
@@ -16,0 +15,0 @@ |
@@ -27,13 +27,10 @@ ( function () { | ||
const srcArray = attribute.isInterleavedBufferAttribute ? attribute.data.array : attribute.array; | ||
const dstArray = new Float32Array( attribute.getCount() * attribute.itemSize ); | ||
for ( let i = 0, j = 0; i < attribute.getCount(); i ++ ) { | ||
dstArray[ j ++ ] = THREE.MathUtils.denormalize( attribute.getX( i ), srcArray ); | ||
dstArray[ j ++ ] = THREE.MathUtils.denormalize( attribute.getY( i ), srcArray ); | ||
dstArray[ j ++ ] = attribute.getX( i ); | ||
dstArray[ j ++ ] = attribute.getY( i ); | ||
if ( attribute.itemSize > 2 ) { | ||
dstArray[ j ++ ] = THREE.MathUtils.denormalize( attribute.getZ( i ), srcArray ); | ||
dstArray[ j ++ ] = attribute.getZ( i ); | ||
@@ -56,9 +53,13 @@ } | ||
} // MikkTSpace algorithm requires non-indexed input. | ||
} | ||
// MikkTSpace algorithm requires non-indexed input. | ||
const _geometry = geometry.index ? geometry.toNonIndexed() : geometry; // Compute vertex tangents. | ||
const _geometry = geometry.index ? geometry.toNonIndexed() : geometry; | ||
// Compute vertex tangents. | ||
const tangents = MikkTSpace.generateTangents( getAttributeArray( _geometry.attributes.position ), getAttributeArray( _geometry.attributes.normal ), getAttributeArray( _geometry.attributes.uv ) ); // Texture coordinate convention of glTF differs from the apparent | ||
const tangents = MikkTSpace.generateTangents( getAttributeArray( _geometry.attributes.position ), getAttributeArray( _geometry.attributes.normal ), getAttributeArray( _geometry.attributes.uv ) ); | ||
// Texture coordinate convention of glTF differs from the apparent | ||
// default of the MikkTSpace library; .w component must be flipped. | ||
@@ -74,7 +75,7 @@ | ||
} // | ||
} | ||
// | ||
_geometry.setAttribute( 'tangent', new THREE.BufferAttribute( tangents, 4 ) ); | ||
if ( geometry !== _geometry ) { | ||
@@ -89,2 +90,3 @@ | ||
} | ||
/** | ||
@@ -95,4 +97,2 @@ * @param {Array<BufferGeometry>} geometries | ||
*/ | ||
function mergeBufferGeometries( geometries, useGroups = false ) { | ||
@@ -108,8 +108,9 @@ | ||
let offset = 0; | ||
for ( let i = 0; i < geometries.length; ++ i ) { | ||
const geometry = geometries[ i ]; | ||
let attributesCount = 0; // ensure that all geometries are indexed, or none | ||
let attributesCount = 0; | ||
// ensure that all geometries are indexed, or none | ||
if ( isIndexed !== ( geometry.index !== null ) ) { | ||
@@ -120,4 +121,5 @@ | ||
} // gather attributes, exit early if they're different | ||
} | ||
// gather attributes, exit early if they're different | ||
@@ -137,4 +139,5 @@ for ( const name in geometry.attributes ) { | ||
} // ensure geometries have the same number of attributes | ||
} | ||
// ensure geometries have the same number of attributes | ||
@@ -146,4 +149,5 @@ if ( attributesCount !== attributesUsed.size ) { | ||
} // gather morph attributes, exit early if they're different | ||
} | ||
// gather morph attributes, exit early if they're different | ||
@@ -169,12 +173,7 @@ if ( morphTargetsRelative !== geometry.morphTargetsRelative ) { | ||
} // gather .userData | ||
} | ||
mergedGeometry.userData.mergedUserData = mergedGeometry.userData.mergedUserData || []; | ||
mergedGeometry.userData.mergedUserData.push( geometry.userData ); | ||
if ( useGroups ) { | ||
let count; | ||
if ( isIndexed ) { | ||
@@ -200,4 +199,5 @@ | ||
} // merge indices | ||
} | ||
// merge indices | ||
@@ -208,7 +208,5 @@ if ( isIndexed ) { | ||
const mergedIndex = []; | ||
for ( let i = 0; i < geometries.length; ++ i ) { | ||
const index = geometries[ i ].index; | ||
for ( let j = 0; j < index.count; ++ j ) { | ||
@@ -226,4 +224,5 @@ | ||
} // merge attributes | ||
} | ||
// merge attributes | ||
@@ -233,3 +232,2 @@ for ( const name in attributes ) { | ||
const mergedAttribute = mergeBufferAttributes( attributes[ name ] ); | ||
if ( ! mergedAttribute ) { | ||
@@ -244,4 +242,5 @@ | ||
} // merge morph attributes | ||
} | ||
// merge morph attributes | ||
@@ -254,7 +253,5 @@ for ( const name in morphAttributes ) { | ||
mergedGeometry.morphAttributes[ name ] = []; | ||
for ( let i = 0; i < numMorphTargets; ++ i ) { | ||
const morphAttributesToMerge = []; | ||
for ( let j = 0; j < morphAttributes[ name ].length; ++ j ) { | ||
@@ -267,3 +264,2 @@ | ||
const mergedMorphAttribute = mergeBufferAttributes( morphAttributesToMerge ); | ||
if ( ! mergedMorphAttribute ) { | ||
@@ -285,2 +281,3 @@ | ||
} | ||
/** | ||
@@ -290,4 +287,2 @@ * @param {Array<BufferAttribute>} attributes | ||
*/ | ||
function mergeBufferAttributes( attributes ) { | ||
@@ -299,7 +294,5 @@ | ||
let arrayLength = 0; | ||
for ( let i = 0; i < attributes.length; ++ i ) { | ||
const attribute = attributes[ i ]; | ||
if ( attribute.isInterleavedBufferAttribute ) { | ||
@@ -313,3 +306,2 @@ | ||
if ( TypedArray === undefined ) TypedArray = attribute.array.constructor; | ||
if ( TypedArray !== attribute.array.constructor ) { | ||
@@ -323,3 +315,2 @@ | ||
if ( itemSize === undefined ) itemSize = attribute.itemSize; | ||
if ( itemSize !== attribute.itemSize ) { | ||
@@ -333,3 +324,2 @@ | ||
if ( normalized === undefined ) normalized = attribute.normalized; | ||
if ( normalized !== attribute.normalized ) { | ||
@@ -348,3 +338,2 @@ | ||
let offset = 0; | ||
for ( let i = 0; i < attributes.length; ++ i ) { | ||
@@ -360,8 +349,29 @@ | ||
} | ||
/** | ||
* @param {BufferAttribute} | ||
* @return {BufferAttribute} | ||
*/ | ||
function deepCloneAttribute( attribute ) { | ||
if ( attribute.isInstancedInterleavedBufferAttribute || attribute.isInterleavedBufferAttribute ) { | ||
return deinterleaveAttribute( attribute ); | ||
} | ||
if ( attribute.isInstancedBufferAttribute ) { | ||
return new THREE.InstancedBufferAttribute().copy( attribute ); | ||
} | ||
return new THREE.BufferAttribute().copy( attribute ); | ||
} | ||
/** | ||
* @param {Array<BufferAttribute>} attributes | ||
* @return {Array<InterleavedBufferAttribute>} | ||
*/ | ||
function interleaveAttributes( attributes ) { | ||
@@ -373,4 +383,5 @@ | ||
let arrayLength = 0; | ||
let stride = 0; // calculate the length and type of the interleavedBuffer | ||
let stride = 0; | ||
// calculate the length and type of the interleavedBuffer | ||
for ( let i = 0, l = attributes.length; i < l; ++ i ) { | ||
@@ -380,3 +391,2 @@ | ||
if ( TypedArray === undefined ) TypedArray = attribute.array.constructor; | ||
if ( TypedArray !== attribute.array.constructor ) { | ||
@@ -392,5 +402,5 @@ | ||
} // Create the set of buffer attributes | ||
} | ||
// Create the set of buffer attributes | ||
const interleavedBuffer = new THREE.InterleavedBuffer( new TypedArray( arrayLength ), stride ); | ||
@@ -401,3 +411,2 @@ let offset = 0; | ||
const setters = [ 'setX', 'setY', 'setZ', 'setW' ]; | ||
for ( let j = 0, l = attributes.length; j < l; j ++ ) { | ||
@@ -410,5 +419,6 @@ | ||
res.push( iba ); | ||
offset += itemSize; // Move the data for each attribute into the new interleavedBuffer | ||
offset += itemSize; | ||
// Move the data for each attribute into the new interleavedBuffer | ||
// at the appropriate offset | ||
for ( let c = 0; c < count; c ++ ) { | ||
@@ -428,5 +438,5 @@ | ||
} // returns a new, non-interleaved version of the provided attribute | ||
} | ||
// returns a new, non-interleaved version of the provided attribute | ||
function deinterleaveAttribute( attribute ) { | ||
@@ -440,3 +450,2 @@ | ||
let newAttribute; | ||
if ( attribute.isInstancedInterleavedBufferAttribute ) { | ||
@@ -455,3 +464,2 @@ | ||
newAttribute.setX( i, attribute.getX( i ) ); | ||
if ( itemSize >= 2 ) { | ||
@@ -479,4 +487,5 @@ | ||
} // deinterleaves all attributes on the geometry | ||
} | ||
// deinterleaves all attributes on the geometry | ||
function deinterleaveGeometry( geometry ) { | ||
@@ -487,7 +496,5 @@ | ||
const attrMap = new Map(); | ||
for ( const key in attributes ) { | ||
const attr = attributes[ key ]; | ||
if ( attr.isInterleavedBufferAttribute ) { | ||
@@ -510,3 +517,2 @@ | ||
const attr = morphTargets[ key ]; | ||
if ( attr.isInterleavedBufferAttribute ) { | ||
@@ -527,2 +533,3 @@ | ||
} | ||
/** | ||
@@ -532,3 +539,2 @@ * @param {Array<BufferGeometry>} geometry | ||
*/ | ||
function estimateBytesUsed( geometry ) { | ||
@@ -540,3 +546,2 @@ | ||
let mem = 0; | ||
for ( const name in geometry.attributes ) { | ||
@@ -554,2 +559,3 @@ | ||
} | ||
/** | ||
@@ -560,46 +566,49 @@ * @param {BufferGeometry} geometry | ||
*/ | ||
function mergeVertices( geometry, tolerance = 1e-4 ) { | ||
tolerance = Math.max( tolerance, Number.EPSILON ); | ||
function mergeVertices( geometry, tolerance = 1e-4 ) { | ||
tolerance = Math.max( tolerance, Number.EPSILON ); // Generate an index buffer if the geometry doesn't have one, or optimize it | ||
// Generate an index buffer if the geometry doesn't have one, or optimize it | ||
// if it's already available. | ||
const hashToIndex = {}; | ||
const indices = geometry.getIndex(); | ||
const positions = geometry.getAttribute( 'position' ); | ||
const vertexCount = indices ? indices.count : positions.count; // next value for triangle indices | ||
const vertexCount = indices ? indices.count : positions.count; | ||
let nextIndex = 0; // attributes and new attribute arrays | ||
// next value for triangle indices | ||
let nextIndex = 0; | ||
// attributes and new attribute arrays | ||
const attributeNames = Object.keys( geometry.attributes ); | ||
const attrArrays = {}; | ||
const morphAttrsArrays = {}; | ||
const tmpAttributes = {}; | ||
const tmpMorphAttributes = {}; | ||
const newIndices = []; | ||
const getters = [ 'getX', 'getY', 'getZ', 'getW' ]; // initialize the arrays | ||
const getters = [ 'getX', 'getY', 'getZ', 'getW' ]; | ||
const setters = [ 'setX', 'setY', 'setZ', 'setW' ]; | ||
// Initialize the arrays, allocating space conservatively. Extra | ||
// space will be trimmed in the last step. | ||
for ( let i = 0, l = attributeNames.length; i < l; i ++ ) { | ||
const name = attributeNames[ i ]; | ||
attrArrays[ name ] = []; | ||
const attr = geometry.attributes[ name ]; | ||
tmpAttributes[ name ] = new THREE.BufferAttribute( new attr.array.constructor( attr.count * attr.itemSize ), attr.itemSize, attr.normalized ); | ||
const morphAttr = geometry.morphAttributes[ name ]; | ||
if ( morphAttr ) { | ||
morphAttrsArrays[ name ] = new Array( morphAttr.length ).fill().map( () => [] ); | ||
tmpMorphAttributes[ name ] = new THREE.BufferAttribute( new morphAttr.array.constructor( morphAttr.count * morphAttr.itemSize ), morphAttr.itemSize, morphAttr.normalized ); | ||
} | ||
} // convert the error tolerance to an amount of decimal places to truncate to | ||
} | ||
// convert the error tolerance to an amount of decimal places to truncate to | ||
const decimalShift = Math.log10( 1 / tolerance ); | ||
const shiftMultiplier = Math.pow( 10, decimalShift ); | ||
for ( let i = 0; i < vertexCount; i ++ ) { | ||
const index = indices ? indices.getX( i ) : i; // Generate a hash for the vertex attributes at the current index 'i' | ||
const index = indices ? indices.getX( i ) : i; | ||
// Generate a hash for the vertex attributes at the current index 'i' | ||
let hash = ''; | ||
for ( let j = 0, l = attributeNames.length; j < l; j ++ ) { | ||
@@ -610,3 +619,2 @@ | ||
const itemSize = attribute.itemSize; | ||
for ( let k = 0; k < itemSize; k ++ ) { | ||
@@ -619,6 +627,6 @@ | ||
} // Add another reference to the vertex if it's already | ||
} | ||
// Add another reference to the vertex if it's already | ||
// used by another index | ||
if ( hash in hashToIndex ) { | ||
@@ -630,3 +638,3 @@ | ||
// copy data to the new index in the attribute arrays | ||
// copy data to the new index in the temporary attributes | ||
for ( let j = 0, l = attributeNames.length; j < l; j ++ ) { | ||
@@ -638,10 +646,9 @@ | ||
const itemSize = attribute.itemSize; | ||
const newarray = attrArrays[ name ]; | ||
const newMorphArrays = morphAttrsArrays[ name ]; | ||
const newarray = tmpAttributes[ name ]; | ||
const newMorphArrays = tmpMorphAttributes[ name ]; | ||
for ( let k = 0; k < itemSize; k ++ ) { | ||
const getterFunc = getters[ k ]; | ||
newarray.push( attribute[ getterFunc ]( index ) ); | ||
const setterFunc = setters[ k ]; | ||
newarray[ setterFunc ]( nextIndex, attribute[ getterFunc ]( index ) ); | ||
if ( morphAttr ) { | ||
@@ -651,3 +658,3 @@ | ||
newMorphArrays[ m ].push( morphAttr[ m ][ getterFunc ]( index ) ); | ||
newMorphArrays[ m ][ setterFunc ]( nextIndex, morphAttr[ m ][ getterFunc ]( index ) ); | ||
@@ -668,31 +675,21 @@ } | ||
} // Generate typed arrays from new attribute arrays and update | ||
// the attributeBuffers | ||
} | ||
// generate result THREE.BufferGeometry | ||
const result = geometry.clone(); | ||
for ( const name in geometry.attributes ) { | ||
for ( let i = 0, l = attributeNames.length; i < l; i ++ ) { | ||
const tmpAttribute = tmpAttributes[ name ]; | ||
result.setAttribute( name, new THREE.BufferAttribute( tmpAttribute.array.slice( 0, nextIndex * tmpAttribute.itemSize ), tmpAttribute.itemSize, tmpAttribute.normalized ) ); | ||
if ( ! ( name in tmpMorphAttributes ) ) continue; | ||
for ( let j = 0; j < tmpMorphAttributes[ name ].length; j ++ ) { | ||
const name = attributeNames[ i ]; | ||
const oldAttribute = geometry.getAttribute( name ); | ||
const buffer = new oldAttribute.array.constructor( attrArrays[ name ] ); | ||
const attribute = new THREE.BufferAttribute( buffer, oldAttribute.itemSize, oldAttribute.normalized ); | ||
result.setAttribute( name, attribute ); // Update the attribute arrays | ||
const tmpMorphAttribute = tmpMorphAttributes[ name ][ j ]; | ||
result.morphAttributes[ name ][ j ] = new THREE.BufferAttribute( tmpMorphAttribute.array.slice( 0, nextIndex * tmpMorphAttribute.itemSize ), tmpMorphAttribute.itemSize, tmpMorphAttribute.normalized ); | ||
if ( name in morphAttrsArrays ) { | ||
for ( let j = 0; j < morphAttrsArrays[ name ].length; j ++ ) { | ||
const oldMorphAttribute = geometry.morphAttributes[ name ][ j ]; | ||
const buffer = new oldMorphAttribute.array.constructor( morphAttrsArrays[ name ][ j ] ); | ||
const morphAttribute = new THREE.BufferAttribute( buffer, oldMorphAttribute.itemSize, oldMorphAttribute.normalized ); | ||
result.morphAttributes[ name ][ j ] = morphAttribute; | ||
} | ||
} | ||
} // indices | ||
} | ||
// indices | ||
@@ -703,2 +700,3 @@ result.setIndex( newIndices ); | ||
} | ||
/** | ||
@@ -709,4 +707,2 @@ * @param {BufferGeometry} geometry | ||
*/ | ||
function toTrianglesDrawMode( geometry, drawMode ) { | ||
@@ -723,4 +719,6 @@ | ||
let index = geometry.getIndex(); // generate index if not present | ||
let index = geometry.getIndex(); | ||
// generate index if not present | ||
if ( index === null ) { | ||
@@ -730,3 +728,2 @@ | ||
const position = geometry.getAttribute( 'position' ); | ||
if ( position !== undefined ) { | ||
@@ -750,11 +747,12 @@ | ||
} // | ||
} | ||
// | ||
const numberOfTriangles = index.count - 2; | ||
const newIndices = []; | ||
if ( drawMode === THREE.TriangleFanDrawMode ) { | ||
// gl.TRIANGLE_FAN | ||
for ( let i = 1; i <= numberOfTriangles; i ++ ) { | ||
@@ -771,2 +769,3 @@ | ||
// gl.TRIANGLE_STRIP | ||
for ( let i = 0; i < numberOfTriangles; i ++ ) { | ||
@@ -796,4 +795,5 @@ | ||
} // build final geometry | ||
} | ||
// build final geometry | ||
@@ -813,2 +813,3 @@ const newGeometry = geometry.clone(); | ||
} | ||
/** | ||
@@ -820,4 +821,2 @@ * Calculates the morphed attributes of a morphed/skinned THREE.BufferGeometry. | ||
*/ | ||
function computeMorphedAttributes( object ) { | ||
@@ -833,37 +832,21 @@ | ||
const _vA = new THREE.Vector3(); | ||
const _vB = new THREE.Vector3(); | ||
const _vC = new THREE.Vector3(); | ||
const _tempA = new THREE.Vector3(); | ||
const _tempB = new THREE.Vector3(); | ||
const _tempC = new THREE.Vector3(); | ||
const _morphA = new THREE.Vector3(); | ||
const _morphB = new THREE.Vector3(); | ||
const _morphC = new THREE.Vector3(); | ||
function _calculateMorphedAttributeData( object, attribute, morphAttribute, morphTargetsRelative, a, b, c, modifiedAttributeArray ) { | ||
_vA.fromBufferAttribute( attribute, a ); | ||
_vB.fromBufferAttribute( attribute, b ); | ||
_vC.fromBufferAttribute( attribute, c ); | ||
const morphInfluences = object.morphTargetInfluences; | ||
if ( morphAttribute && morphInfluences ) { | ||
_morphA.set( 0, 0, 0 ); | ||
_morphB.set( 0, 0, 0 ); | ||
_morphC.set( 0, 0, 0 ); | ||
for ( let i = 0, il = morphAttribute.length; i < il; i ++ ) { | ||
@@ -874,15 +857,9 @@ | ||
if ( influence === 0 ) continue; | ||
_tempA.fromBufferAttribute( morph, a ); | ||
_tempB.fromBufferAttribute( morph, b ); | ||
_tempC.fromBufferAttribute( morph, c ); | ||
if ( morphTargetsRelative ) { | ||
_morphA.addScaledVector( _tempA, influence ); | ||
_morphB.addScaledVector( _tempB, influence ); | ||
_morphC.addScaledVector( _tempC, influence ); | ||
@@ -893,5 +870,3 @@ | ||
_morphA.addScaledVector( _tempA.sub( _vA ), influence ); | ||
_morphB.addScaledVector( _tempB.sub( _vB ), influence ); | ||
_morphC.addScaledVector( _tempC.sub( _vC ), influence ); | ||
@@ -904,5 +879,3 @@ | ||
_vA.add( _morphA ); | ||
_vB.add( _morphB ); | ||
_vC.add( _morphC ); | ||
@@ -948,6 +921,6 @@ | ||
const modifiedNormal = new Float32Array( normalAttribute.count * normalAttribute.itemSize ); | ||
if ( index !== null ) { | ||
// indexed buffer geometry | ||
if ( Array.isArray( material ) ) { | ||
@@ -960,3 +933,2 @@ | ||
end = Math.min( group.start + group.count, drawRange.start + drawRange.count ); | ||
for ( j = start, jl = end; j < jl; j += 3 ) { | ||
@@ -967,5 +939,3 @@ | ||
c = index.getX( j + 2 ); | ||
_calculateMorphedAttributeData( object, positionAttribute, morphPosition, morphTargetsRelative, a, b, c, modifiedPosition ); | ||
_calculateMorphedAttributeData( object, normalAttribute, morphNormal, morphTargetsRelative, a, b, c, modifiedNormal ); | ||
@@ -981,3 +951,2 @@ | ||
end = Math.min( index.count, drawRange.start + drawRange.count ); | ||
for ( i = start, il = end; i < il; i += 3 ) { | ||
@@ -988,5 +957,3 @@ | ||
c = index.getX( i + 2 ); | ||
_calculateMorphedAttributeData( object, positionAttribute, morphPosition, morphTargetsRelative, a, b, c, modifiedPosition ); | ||
_calculateMorphedAttributeData( object, normalAttribute, morphNormal, morphTargetsRelative, a, b, c, modifiedNormal ); | ||
@@ -1001,2 +968,3 @@ | ||
// non-indexed buffer geometry | ||
if ( Array.isArray( material ) ) { | ||
@@ -1009,3 +977,2 @@ | ||
end = Math.min( group.start + group.count, drawRange.start + drawRange.count ); | ||
for ( j = start, jl = end; j < jl; j += 3 ) { | ||
@@ -1016,5 +983,3 @@ | ||
c = j + 2; | ||
_calculateMorphedAttributeData( object, positionAttribute, morphPosition, morphTargetsRelative, a, b, c, modifiedPosition ); | ||
_calculateMorphedAttributeData( object, normalAttribute, morphNormal, morphTargetsRelative, a, b, c, modifiedNormal ); | ||
@@ -1030,3 +995,2 @@ | ||
end = Math.min( positionAttribute.count, drawRange.start + drawRange.count ); | ||
for ( i = start, il = end; i < il; i += 3 ) { | ||
@@ -1037,5 +1001,3 @@ | ||
c = i + 2; | ||
_calculateMorphedAttributeData( object, positionAttribute, morphPosition, morphTargetsRelative, a, b, c, modifiedPosition ); | ||
_calculateMorphedAttributeData( object, normalAttribute, morphNormal, morphTargetsRelative, a, b, c, modifiedNormal ); | ||
@@ -1069,4 +1031,6 @@ | ||
let groups = geometry.groups; // sort groups by material index | ||
let groups = geometry.groups; | ||
// sort groups by material index | ||
groups = groups.sort( ( a, b ) => { | ||
@@ -1077,4 +1041,6 @@ | ||
} ); // create index for non-indexed geometries | ||
} ); | ||
// create index for non-indexed geometries | ||
if ( geometry.getIndex() === null ) { | ||
@@ -1084,3 +1050,2 @@ | ||
const indices = []; | ||
for ( let i = 0; i < positionAttribute.count; i += 3 ) { | ||
@@ -1094,8 +1059,8 @@ | ||
} // sort index | ||
} | ||
// sort index | ||
const index = geometry.getIndex(); | ||
const newIndices = []; | ||
for ( let i = 0; i < groups.length; i ++ ) { | ||
@@ -1106,3 +1071,2 @@ | ||
const groupLength = groupStart + group.count; | ||
for ( let j = groupStart; j < groupLength; j ++ ) { | ||
@@ -1117,7 +1081,7 @@ | ||
geometry.dispose(); // Required to force buffer recreation | ||
geometry.setIndex( newIndices ); | ||
geometry.setIndex( newIndices ); // update groups indices | ||
// update groups indices | ||
let start = 0; | ||
for ( let i = 0; i < groups.length; i ++ ) { | ||
@@ -1129,12 +1093,11 @@ | ||
} // merge groups | ||
} | ||
// merge groups | ||
let currentGroup = groups[ 0 ]; | ||
geometry.groups = [ currentGroup ]; | ||
for ( let i = 1; i < groups.length; i ++ ) { | ||
const group = groups[ i ]; | ||
if ( currentGroup.materialIndex === group.materialIndex ) { | ||
@@ -1161,2 +1124,3 @@ | ||
THREE.BufferGeometryUtils.computeTangents = computeTangents; | ||
THREE.BufferGeometryUtils.deepCloneAttribute = deepCloneAttribute; | ||
THREE.BufferGeometryUtils.deinterleaveAttribute = deinterleaveAttribute; | ||
@@ -1163,0 +1127,0 @@ THREE.BufferGeometryUtils.deinterleaveGeometry = deinterleaveGeometry; |
@@ -27,4 +27,2 @@ ( function () { | ||
* @param {boolean} estimateViewFrustum */ | ||
function frameCorners( camera, bottomLeftCorner, bottomRightCorner, topLeftCorner, estimateViewFrustum = false ) { | ||
@@ -36,40 +34,27 @@ | ||
const pe = camera.position; // eye position | ||
const n = camera.near; // distance of near clipping plane | ||
const f = camera.far; //distance of far clipping plane | ||
_vr.copy( pb ).sub( pa ).normalize(); | ||
_vu.copy( pc ).sub( pa ).normalize(); | ||
_vn.crossVectors( _vr, _vu ).normalize(); | ||
_va.copy( pa ).sub( pe ); // from pe to pa | ||
_vb.copy( pb ).sub( pe ); // from pe to pb | ||
_vc.copy( pc ).sub( pe ); // from pe to pc | ||
const d = - _va.dot( _vn ); // distance from eye to screen | ||
const l = _vr.dot( _va ) * n / d; // distance to left screen edge | ||
const r = _vr.dot( _vb ) * n / d; // distance to right screen edge | ||
const b = _vu.dot( _va ) * n / d; // distance to bottom screen edge | ||
const t = _vu.dot( _vc ) * n / d; // distance to top screen edge | ||
const t = _vu.dot( _vc ) * n / d; // distance to top screen edge | ||
// Set the camera rotation to match the focal plane to the corners' plane | ||
_quat.setFromUnitVectors( _vec.set( 0, 1, 0 ), _vu ); | ||
camera.quaternion.setFromUnitVectors( _vec.set( 0, 0, 1 ).applyQuaternion( _quat ), _vn ).multiply( _quat ); | ||
camera.quaternion.setFromUnitVectors( _vec.set( 0, 0, 1 ).applyQuaternion( _quat ), _vn ).multiply( _quat ); // Set the off-axis projection matrix to match the corners | ||
// Set the off-axis projection matrix to match the corners | ||
camera.projectionMatrix.set( 2.0 * n / ( r - l ), 0.0, ( r + l ) / ( r - l ), 0.0, 0.0, 2.0 * n / ( t - b ), ( t + b ) / ( t - b ), 0.0, 0.0, 0.0, ( f + n ) / ( n - f ), 2.0 * f * n / ( n - f ), 0.0, 0.0, - 1.0, 0.0 ); | ||
camera.projectionMatrixInverse.copy( camera.projectionMatrix ).invert(); // FoV estimation to fix frustum culling | ||
camera.projectionMatrixInverse.copy( camera.projectionMatrix ).invert(); | ||
// FoV estimation to fix frustum culling | ||
if ( estimateViewFrustum ) { | ||
@@ -76,0 +61,0 @@ |
@@ -9,2 +9,3 @@ ( function () { | ||
*/ | ||
/** | ||
@@ -18,3 +19,2 @@ * Make the input mesh.geometry's normal attribute encoded and compressed by 3 different methods. | ||
*/ | ||
function compressNormals( mesh, encodeMethod ) { | ||
@@ -29,3 +29,2 @@ | ||
const normal = mesh.geometry.attributes.normal; | ||
if ( ! normal ) { | ||
@@ -38,3 +37,2 @@ | ||
if ( normal.isPacked ) return; | ||
if ( normal.itemSize != 3 ) { | ||
@@ -49,3 +47,2 @@ | ||
let result; | ||
if ( encodeMethod == 'DEFAULT' ) { | ||
@@ -55,3 +52,2 @@ | ||
result = new Uint8Array( count * 3 ); | ||
for ( let idx = 0; idx < array.length; idx += 3 ) { | ||
@@ -76,4 +72,4 @@ | ||
*/ | ||
result = new Int8Array( count * 2 ); | ||
for ( let idx = 0; idx < array.length; idx += 3 ) { | ||
@@ -93,3 +89,2 @@ | ||
result = new Int16Array( count * 2 ); | ||
for ( let idx = 0; idx < array.length; idx += 3 ) { | ||
@@ -109,3 +104,2 @@ | ||
result = new Uint16Array( count * 2 ); | ||
for ( let idx = 0; idx < array.length; idx += 3 ) { | ||
@@ -130,4 +124,5 @@ | ||
mesh.geometry.attributes.normal.isPacked = true; | ||
mesh.geometry.attributes.normal.packingMethod = encodeMethod; // modify material | ||
mesh.geometry.attributes.normal.packingMethod = encodeMethod; | ||
// modify material | ||
if ( ! ( mesh.material instanceof THREE.PackedPhongMaterial ) ) { | ||
@@ -164,2 +159,3 @@ | ||
} | ||
/** | ||
@@ -172,4 +168,2 @@ * Make the input mesh.geometry's position attribute encoded and compressed. | ||
*/ | ||
function compressPositions( mesh ) { | ||
@@ -184,3 +178,2 @@ | ||
const position = mesh.geometry.attributes.position; | ||
if ( ! position ) { | ||
@@ -193,3 +186,2 @@ | ||
if ( position.isPacked ) return; | ||
if ( position.itemSize != 3 ) { | ||
@@ -205,4 +197,5 @@ | ||
const quantized = result.quantized; | ||
const decodeMat = result.decodeMat; // IMPORTANT: calculate original geometry bounding info first, before updating packed positions | ||
const decodeMat = result.decodeMat; | ||
// IMPORTANT: calculate original geometry bounding info first, before updating packed positions | ||
if ( mesh.geometry.boundingBox == null ) mesh.geometry.computeBoundingBox(); | ||
@@ -213,4 +206,5 @@ if ( mesh.geometry.boundingSphere == null ) mesh.geometry.computeBoundingSphere(); | ||
mesh.geometry.attributes.position.needsUpdate = true; | ||
mesh.geometry.attributes.position.bytes = quantized.length * encodingBytes; // modify material | ||
mesh.geometry.attributes.position.bytes = quantized.length * encodingBytes; | ||
// modify material | ||
if ( ! ( mesh.material instanceof THREE.PackedPhongMaterial ) ) { | ||
@@ -227,2 +221,3 @@ | ||
} | ||
/** | ||
@@ -235,4 +230,2 @@ * Make the input mesh.geometry's uv attribute encoded and compressed. | ||
*/ | ||
function compressUvs( mesh ) { | ||
@@ -247,3 +240,2 @@ | ||
const uvs = mesh.geometry.attributes.uv; | ||
if ( ! uvs ) { | ||
@@ -261,3 +253,2 @@ | ||
const array = uvs.array; | ||
for ( let i = 0; i < array.length; i ++ ) { | ||
@@ -271,3 +262,2 @@ | ||
let result; | ||
if ( range.min >= - 1.0 && range.max <= 1.0 ) { | ||
@@ -277,3 +267,2 @@ | ||
result = new Uint16Array( array.length ); | ||
for ( let i = 0; i < array.length; i += 2 ) { | ||
@@ -291,3 +280,2 @@ | ||
mesh.geometry.attributes.uv.bytes = result.length * 2; | ||
if ( ! ( mesh.material instanceof THREE.PackedPhongMaterial ) ) { | ||
@@ -309,3 +297,2 @@ | ||
mesh.geometry.attributes.uv.bytes = result.quantized.length * 2; | ||
if ( ! ( mesh.material instanceof THREE.PackedPhongMaterial ) ) { | ||
@@ -323,4 +310,5 @@ | ||
} // Encoding functions | ||
} | ||
// Encoding functions | ||
@@ -349,5 +337,5 @@ function defaultEncode( x, y, z, bytes ) { | ||
} // for `Angles` encoding | ||
} | ||
// for `Angles` encoding | ||
function anglesEncode( x, y, z ) { | ||
@@ -359,10 +347,11 @@ | ||
} // for `Octahedron` encoding | ||
} | ||
// for `Octahedron` encoding | ||
function octEncodeBest( x, y, z, bytes ) { | ||
let oct, dec, best, currentCos, bestCos; // Test various combinations of ceil and floor | ||
let oct, dec, best, currentCos, bestCos; | ||
// Test various combinations of ceil and floor | ||
// to minimize rounding errors | ||
best = oct = octEncodeVec3( x, y, z, 'floor', 'floor' ); | ||
@@ -374,3 +363,2 @@ dec = octDecodeVec2( oct ); | ||
currentCos = dot( x, y, z, dec ); | ||
if ( currentCos > bestCos ) { | ||
@@ -386,3 +374,2 @@ | ||
currentCos = dot( x, y, z, dec ); | ||
if ( currentCos > bestCos ) { | ||
@@ -398,3 +385,2 @@ | ||
currentCos = dot( x, y, z, dec ); | ||
if ( currentCos > bestCos ) { | ||
@@ -407,3 +393,2 @@ | ||
return best; | ||
function octEncodeVec3( x0, y0, z0, xfunc, yfunc ) { | ||
@@ -413,3 +398,2 @@ | ||
let y = y0 / ( Math.abs( x0 ) + Math.abs( y0 ) + Math.abs( z0 ) ); | ||
if ( z < 0 ) { | ||
@@ -422,3 +406,2 @@ | ||
let diff = 1 - Math.abs( x ) - Math.abs( y ); | ||
if ( diff > 0 ) { | ||
@@ -452,3 +435,2 @@ | ||
let y = oct[ 1 ]; | ||
if ( bytes == 1 ) { | ||
@@ -467,3 +449,2 @@ | ||
const z = 1 - Math.abs( x ) - Math.abs( y ); | ||
if ( z < 0 ) { | ||
@@ -493,3 +474,2 @@ | ||
let quantized, segments; | ||
if ( bytes == 1 ) { | ||
@@ -516,3 +496,2 @@ | ||
max[ 0 ] = max[ 1 ] = max[ 2 ] = - Number.MAX_VALUE; | ||
for ( let i = 0; i < array.length; i += 3 ) { | ||
@@ -535,3 +514,2 @@ | ||
const multiplier = new Float32Array( [ max[ 0 ] !== min[ 0 ] ? segments / ( max[ 0 ] - min[ 0 ] ) : 0, max[ 1 ] !== min[ 1 ] ? segments / ( max[ 1 ] - min[ 1 ] ) : 0, max[ 2 ] !== min[ 2 ] ? segments / ( max[ 2 ] - min[ 2 ] ) : 0 ] ); | ||
for ( let i = 0; i < array.length; i += 3 ) { | ||
@@ -555,3 +533,2 @@ | ||
let quantized, segments; | ||
if ( bytes == 1 ) { | ||
@@ -578,3 +555,2 @@ | ||
max[ 0 ] = max[ 1 ] = - Number.MAX_VALUE; | ||
for ( let i = 0; i < array.length; i += 2 ) { | ||
@@ -594,3 +570,2 @@ | ||
const multiplier = new Float32Array( [ max[ 0 ] !== min[ 0 ] ? segments / ( max[ 0 ] - min[ 0 ] ) : 0, max[ 1 ] !== min[ 1 ] ? segments / ( max[ 1 ] - min[ 1 ] ) : 0 ] ); | ||
for ( let i = 0; i < array.length; i += 2 ) { | ||
@@ -597,0 +572,0 @@ |
@@ -17,3 +17,2 @@ ( function () { | ||
*/ | ||
function hilbert2D( center = new THREE.Vector3( 0, 0, 0 ), size = 10, iterations = 1, v0 = 0, v1 = 1, v2 = 2, v3 = 3 ) { | ||
@@ -23,4 +22,5 @@ | ||
const 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 ) ]; | ||
const vec = [ vec_s[ v0 ], vec_s[ v1 ], vec_s[ v2 ], vec_s[ v3 ] ]; // Recurse iterations | ||
const vec = [ vec_s[ v0 ], vec_s[ v1 ], vec_s[ v2 ], vec_s[ v3 ] ]; | ||
// Recurse iterations | ||
if ( 0 <= -- iterations ) { | ||
@@ -30,8 +30,9 @@ | ||
} // Return complete Hilbert Curve. | ||
} | ||
// Return complete Hilbert Curve. | ||
return vec; | ||
} | ||
/** | ||
@@ -55,4 +56,2 @@ * Generates 3D-Coordinates in a very fast way. | ||
*/ | ||
function hilbert3D( center = new THREE.Vector3( 0, 0, 0 ), size = 10, iterations = 1, v0 = 0, v1 = 1, v2 = 2, v3 = 3, v4 = 4, v5 = 5, v6 = 6, v7 = 7 ) { | ||
@@ -63,4 +62,5 @@ | ||
const 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 ) ]; | ||
const 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 | ||
const 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 ) { | ||
@@ -70,8 +70,9 @@ | ||
} // Return complete Hilbert Curve. | ||
} | ||
// Return complete Hilbert Curve. | ||
return vec; | ||
} | ||
/** | ||
@@ -84,4 +85,2 @@ * Generates a Gosper curve (lying in the XY plane) | ||
*/ | ||
function gosper( size = 1 ) { | ||
@@ -93,11 +92,8 @@ | ||
let input = config.axiom; | ||
for ( let i = 0, il = config.steps; 0 <= il ? i < il : i > il; 0 <= il ? i ++ : i -- ) { | ||
output = ''; | ||
for ( let j = 0, jl = input.length; j < jl; j ++ ) { | ||
const char = input[ j ]; | ||
if ( char in config.rules ) { | ||
@@ -130,7 +126,5 @@ | ||
const fractal = config.fractal; | ||
for ( let i = 0, l = fractal.length; i < l; i ++ ) { | ||
const char = fractal[ i ]; | ||
if ( char === '+' ) { | ||
@@ -156,4 +150,5 @@ | ||
} // | ||
} | ||
// | ||
@@ -172,4 +167,4 @@ const gosper = fractalize( { | ||
angle: Math.PI / 3 // 60 degrees | ||
} ); | ||
} ); | ||
return points; | ||
@@ -176,0 +171,0 @@ |
( function () { | ||
// https://www.khronos.org/registry/webgl/extensions/EXT_disjoint_timer_query/ | ||
// https://www.khronos.org/registry/webgl/extensions/EXT_disjoint_timer_query_webgl2/ | ||
class GPUStatsPanel extends Stats.Panel { | ||
@@ -12,3 +12,2 @@ | ||
let extension = context.getExtension( 'EXT_disjoint_timer_query_webgl2' ); | ||
if ( extension === null ) { | ||
@@ -18,3 +17,2 @@ | ||
extension = context.getExtension( 'EXT_disjoint_timer_query' ); | ||
if ( extension === null ) { | ||
@@ -32,3 +30,2 @@ | ||
this.activeQueries = 0; | ||
this.startQuery = function () { | ||
@@ -38,3 +35,2 @@ | ||
const ext = this.extension; | ||
if ( ext === null ) { | ||
@@ -44,7 +40,6 @@ | ||
} // create the query object | ||
} | ||
// create the query object | ||
let query; | ||
if ( isWebGL2 ) { | ||
@@ -63,3 +58,2 @@ | ||
this.activeQueries ++; | ||
const checkQuery = () => { | ||
@@ -69,3 +63,2 @@ | ||
let available, disjoint, ns; | ||
if ( isWebGL2 ) { | ||
@@ -86,3 +79,2 @@ | ||
const ms = ns * 1e-6; | ||
if ( available ) { | ||
@@ -117,3 +109,2 @@ | ||
const gl = this.context; | ||
if ( ext === null ) { | ||
@@ -120,0 +111,0 @@ |
@@ -10,5 +10,7 @@ ( function () { | ||
// Special treatment is done to the conditional lines generated by LDrawLoader. | ||
function extractGroup( geometry, group, elementSize, isConditionalLine ) { | ||
// Extracts a group from a geometry as a new geometry (with attribute buffers referencing original buffers) | ||
const newGeometry = new THREE.BufferGeometry(); | ||
@@ -24,3 +26,2 @@ const originalPositions = geometry.getAttribute( 'position' ).array; | ||
if ( normals !== null ) newGeometry.setAttribute( 'normal', new THREE.BufferAttribute( normals, 3 ) ); | ||
if ( isConditionalLine ) { | ||
@@ -44,3 +45,2 @@ | ||
const geoms = geometries[ mat.uuid ]; | ||
if ( ! geoms ) { | ||
@@ -64,2 +64,3 @@ | ||
// Permutes first two vertices of each attribute element | ||
if ( ! attribute ) return; | ||
@@ -69,3 +70,2 @@ const verts = attribute.array; | ||
let offset = 0; | ||
for ( let i = 0; i < numVerts; i ++ ) { | ||
@@ -86,4 +86,5 @@ | ||
} // Traverse the object hierarchy collecting geometries and transforming them to world space | ||
} | ||
// Traverse the object hierarchy collecting geometries and transforming them to world space | ||
@@ -102,3 +103,2 @@ const meshGeometries = {}; | ||
const matrixIsInverted = c.matrixWorld.determinant() < 0; | ||
if ( matrixIsInverted ) { | ||
@@ -112,3 +112,2 @@ | ||
geometry.applyMatrix4( c.matrixWorld ); | ||
if ( c.isConditionalLine ) { | ||
@@ -124,3 +123,2 @@ | ||
const geometries = c.isMesh ? meshGeometries : c.isConditionalLine ? condLinesGeometries : linesGeometries; | ||
if ( Array.isArray( c.material ) ) { | ||
@@ -145,7 +143,8 @@ | ||
} ); // Create object with merged geometries | ||
} ); | ||
// Create object with merged geometries | ||
const mergedObject = new THREE.Group(); | ||
const meshMaterialsIds = Object.keys( meshGeometries ); | ||
for ( const meshMaterialsId of meshMaterialsIds ) { | ||
@@ -160,3 +159,2 @@ | ||
const linesMaterialsIds = Object.keys( linesGeometries ); | ||
for ( const linesMaterialsId of linesMaterialsIds ) { | ||
@@ -171,3 +169,2 @@ | ||
const condLinesMaterialsIds = Object.keys( condLinesGeometries ); | ||
for ( const condLinesMaterialsId of condLinesMaterialsIds ) { | ||
@@ -174,0 +171,0 @@ |
@@ -8,3 +8,2 @@ ( function () { | ||
*/ | ||
class PackedPhongMaterial extends THREE.MeshPhongMaterial { | ||
@@ -95,6 +94,9 @@ | ||
#endif | ||
#endif`, THREE.ShaderChunk.morphtarget_vertex, THREE.ShaderChunk.skinning_vertex, THREE.ShaderChunk.displacementmap_vertex, THREE.ShaderChunk.project_vertex, THREE.ShaderChunk.logdepthbuf_vertex, THREE.ShaderChunk.clipping_planes_vertex, 'vViewPosition = - mvPosition.xyz;', THREE.ShaderChunk.worldpos_vertex, THREE.ShaderChunk.envmap_vertex, THREE.ShaderChunk.shadowmap_vertex, THREE.ShaderChunk.fog_vertex, '}' ].join( '\n' ); // Use the original THREE.MeshPhongMaterial's fragmentShader. | ||
#endif`, THREE.ShaderChunk.morphtarget_vertex, THREE.ShaderChunk.skinning_vertex, THREE.ShaderChunk.displacementmap_vertex, THREE.ShaderChunk.project_vertex, THREE.ShaderChunk.logdepthbuf_vertex, THREE.ShaderChunk.clipping_planes_vertex, 'vViewPosition = - mvPosition.xyz;', THREE.ShaderChunk.worldpos_vertex, THREE.ShaderChunk.envmap_vertex, THREE.ShaderChunk.shadowmap_vertex, THREE.ShaderChunk.fog_vertex, '}' ].join( '\n' ); | ||
this.fragmentShader = [ '#define PHONG', 'uniform vec3 diffuse;', 'uniform vec3 emissive;', 'uniform vec3 specular;', 'uniform float shininess;', 'uniform float opacity;', THREE.ShaderChunk.common, THREE.ShaderChunk.packing, THREE.ShaderChunk.dithering_pars_fragment, THREE.ShaderChunk.color_pars_fragment, THREE.ShaderChunk.uv_pars_fragment, THREE.ShaderChunk.uv2_pars_fragment, THREE.ShaderChunk.map_pars_fragment, THREE.ShaderChunk.alphamap_pars_fragment, THREE.ShaderChunk.aomap_pars_fragment, THREE.ShaderChunk.lightmap_pars_fragment, THREE.ShaderChunk.emissivemap_pars_fragment, THREE.ShaderChunk.envmap_common_pars_fragment, THREE.ShaderChunk.envmap_pars_fragment, THREE.ShaderChunk.fog_pars_fragment, THREE.ShaderChunk.bsdfs, THREE.ShaderChunk.lights_pars_begin, THREE.ShaderChunk.normal_pars_fragment, THREE.ShaderChunk.lights_phong_pars_fragment, THREE.ShaderChunk.shadowmap_pars_fragment, THREE.ShaderChunk.bumpmap_pars_fragment, THREE.ShaderChunk.normalmap_pars_fragment, THREE.ShaderChunk.specularmap_pars_fragment, THREE.ShaderChunk.logdepthbuf_pars_fragment, THREE.ShaderChunk.clipping_planes_pars_fragment, 'void main() {', THREE.ShaderChunk.clipping_planes_fragment, 'vec4 diffuseColor = vec4( diffuse, opacity );', 'ReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );', 'vec3 totalEmissiveRadiance = emissive;', THREE.ShaderChunk.logdepthbuf_fragment, THREE.ShaderChunk.map_fragment, THREE.ShaderChunk.color_fragment, THREE.ShaderChunk.alphamap_fragment, THREE.ShaderChunk.alphatest_fragment, THREE.ShaderChunk.specularmap_fragment, THREE.ShaderChunk.normal_fragment_begin, THREE.ShaderChunk.normal_fragment_maps, THREE.ShaderChunk.emissivemap_fragment, // accumulation | ||
THREE.ShaderChunk.lights_phong_fragment, THREE.ShaderChunk.lights_fragment_begin, THREE.ShaderChunk.lights_fragment_maps, THREE.ShaderChunk.lights_fragment_end, // modulation | ||
// Use the original THREE.MeshPhongMaterial's fragmentShader. | ||
this.fragmentShader = [ '#define PHONG', 'uniform vec3 diffuse;', 'uniform vec3 emissive;', 'uniform vec3 specular;', 'uniform float shininess;', 'uniform float opacity;', THREE.ShaderChunk.common, THREE.ShaderChunk.packing, THREE.ShaderChunk.dithering_pars_fragment, THREE.ShaderChunk.color_pars_fragment, THREE.ShaderChunk.uv_pars_fragment, THREE.ShaderChunk.uv2_pars_fragment, THREE.ShaderChunk.map_pars_fragment, THREE.ShaderChunk.alphamap_pars_fragment, THREE.ShaderChunk.aomap_pars_fragment, THREE.ShaderChunk.lightmap_pars_fragment, THREE.ShaderChunk.emissivemap_pars_fragment, THREE.ShaderChunk.envmap_common_pars_fragment, THREE.ShaderChunk.envmap_pars_fragment, THREE.ShaderChunk.fog_pars_fragment, THREE.ShaderChunk.bsdfs, THREE.ShaderChunk.lights_pars_begin, THREE.ShaderChunk.normal_pars_fragment, THREE.ShaderChunk.lights_phong_pars_fragment, THREE.ShaderChunk.shadowmap_pars_fragment, THREE.ShaderChunk.bumpmap_pars_fragment, THREE.ShaderChunk.normalmap_pars_fragment, THREE.ShaderChunk.specularmap_pars_fragment, THREE.ShaderChunk.logdepthbuf_pars_fragment, THREE.ShaderChunk.clipping_planes_pars_fragment, 'void main() {', THREE.ShaderChunk.clipping_planes_fragment, 'vec4 diffuseColor = vec4( diffuse, opacity );', 'ReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );', 'vec3 totalEmissiveRadiance = emissive;', THREE.ShaderChunk.logdepthbuf_fragment, THREE.ShaderChunk.map_fragment, THREE.ShaderChunk.color_fragment, THREE.ShaderChunk.alphamap_fragment, THREE.ShaderChunk.alphatest_fragment, THREE.ShaderChunk.specularmap_fragment, THREE.ShaderChunk.normal_fragment_begin, THREE.ShaderChunk.normal_fragment_maps, THREE.ShaderChunk.emissivemap_fragment, | ||
// accumulation | ||
THREE.ShaderChunk.lights_phong_fragment, THREE.ShaderChunk.lights_fragment_begin, THREE.ShaderChunk.lights_fragment_maps, THREE.ShaderChunk.lights_fragment_end, | ||
// modulation | ||
THREE.ShaderChunk.aomap_fragment, 'vec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;', THREE.ShaderChunk.envmap_fragment, 'gl_FragColor = vec4( outgoingLight, diffuseColor.a );', THREE.ShaderChunk.tonemapping_fragment, THREE.ShaderChunk.encodings_fragment, THREE.ShaderChunk.fog_fragment, THREE.ShaderChunk.premultiplied_alpha_fragment, THREE.ShaderChunk.dithering_fragment, '}' ].join( '\n' ); | ||
@@ -101,0 +103,0 @@ this.setValues( parameters ); |
( function () { | ||
const _color = /*@__PURE__*/new THREE.Color(); | ||
const _matrix = /*@__PURE__*/new THREE.Matrix4(); | ||
function createMeshesFromInstancedMesh( instancedMesh ) { | ||
@@ -9,3 +11,2 @@ | ||
const material = instancedMesh.material; | ||
for ( let i = 0; i < count; i ++ ) { | ||
@@ -37,9 +38,13 @@ | ||
const object = new THREE.Group(); | ||
object.copy( mesh ); // merge groups (which automatically sorts them) | ||
object.copy( mesh ); | ||
// merge groups (which automatically sorts them) | ||
const geometry = THREE.mergeGroups( mesh.geometry ); | ||
const index = geometry.index; | ||
const groups = geometry.groups; | ||
const attributeNames = Object.keys( geometry.attributes ); // create a mesh for each group by extracting the buffer data into a new geometry | ||
const attributeNames = Object.keys( geometry.attributes ); | ||
// create a mesh for each group by extracting the buffer data into a new geometry | ||
for ( let i = 0; i < groups.length; i ++ ) { | ||
@@ -51,4 +56,6 @@ | ||
const newGeometry = new THREE.BufferGeometry(); | ||
const newMaterial = mesh.material[ group.materialIndex ]; // process all buffer attributes | ||
const newMaterial = mesh.material[ group.materialIndex ]; | ||
// process all buffer attributes | ||
for ( let j = 0; j < attributeNames.length; j ++ ) { | ||
@@ -63,3 +70,2 @@ | ||
const newAttribute = new THREE.BufferAttribute( newArray, itemSize ); | ||
for ( let k = start, n = 0; k < end; k ++, n ++ ) { | ||
@@ -91,3 +97,2 @@ | ||
const group = new THREE.Group(); | ||
for ( let i = 0, l = materials.length; i < l; i ++ ) { | ||
@@ -103,2 +108,106 @@ | ||
function reduceVertices( object, func, initialValue ) { | ||
let value = initialValue; | ||
const vertex = new THREE.Vector3(); | ||
object.updateWorldMatrix( true, true ); | ||
object.traverseVisible( child => { | ||
const { | ||
geometry | ||
} = child; | ||
if ( geometry !== undefined ) { | ||
const { | ||
position | ||
} = geometry.attributes; | ||
if ( position !== undefined ) { | ||
for ( let i = 0, l = position.count; i < l; i ++ ) { | ||
vertex.fromBufferAttribute( position, i ); | ||
if ( child.isSkinnedMesh ) { | ||
child.boneTransform( i, vertex ); | ||
} else { | ||
vertex.applyMatrix4( child.matrixWorld ); | ||
} | ||
value = func( value, vertex ); | ||
} | ||
} | ||
} | ||
} ); | ||
return value; | ||
} | ||
/** | ||
* @param {InstancedMesh} | ||
* @param {function(int, int):int} | ||
*/ | ||
function sortInstancedMesh( mesh, compareFn ) { | ||
// store copy of instanced attributes for lookups | ||
const instanceMatrixRef = THREE.deepCloneAttribute( mesh.instanceMatrix ); | ||
const instanceColorRef = mesh.instanceColor ? THREE.deepCloneAttribute( mesh.instanceColor ) : null; | ||
const attributeRefs = new Map(); | ||
for ( const name in mesh.geometry.attributes ) { | ||
const attribute = mesh.geometry.attributes[ name ]; | ||
if ( attribute.isInstancedBufferAttribute ) { | ||
attributeRefs.set( attribute, THREE.deepCloneAttribute( attribute ) ); | ||
} | ||
} | ||
// compute sort order | ||
const tokens = []; | ||
for ( let i = 0; i < mesh.count; i ++ ) tokens.push( i ); | ||
tokens.sort( compareFn ); | ||
// apply sort order | ||
for ( let i = 0; i < tokens.length; i ++ ) { | ||
const refIndex = tokens[ i ]; | ||
_matrix.fromArray( instanceMatrixRef.array, refIndex * mesh.instanceMatrix.itemSize ); | ||
_matrix.toArray( mesh.instanceMatrix.array, i * mesh.instanceMatrix.itemSize ); | ||
if ( mesh.instanceColor ) { | ||
_color.fromArray( instanceColorRef.array, refIndex * mesh.instanceColor.itemSize ); | ||
_color.toArray( mesh.instanceColor.array, i * mesh.instanceColor.itemSize ); | ||
} | ||
for ( const name in mesh.geometry.attributes ) { | ||
const attribute = mesh.geometry.attributes[ name ]; | ||
if ( attribute.isInstancedBufferAttribute ) { | ||
const attributeRef = attributeRefs.get( attribute ); | ||
attribute.setX( i, attributeRef.getX( refIndex ) ); | ||
if ( attribute.itemSize > 1 ) attribute.setY( i, attributeRef.getY( refIndex ) ); | ||
if ( attribute.itemSize > 2 ) attribute.setZ( i, attributeRef.getZ( refIndex ) ); | ||
if ( attribute.itemSize > 3 ) attribute.setW( i, attributeRef.getW( refIndex ) ); | ||
} | ||
} | ||
} | ||
} | ||
THREE.SceneUtils = {}; | ||
@@ -108,3 +217,5 @@ THREE.SceneUtils.createMeshesFromInstancedMesh = createMeshesFromInstancedMesh; | ||
THREE.SceneUtils.createMultiMaterialObject = createMultiMaterialObject; | ||
THREE.SceneUtils.reduceVertices = reduceVertices; | ||
THREE.SceneUtils.sortInstancedMesh = sortInstancedMesh; | ||
} )(); |
@@ -37,4 +37,5 @@ ( function () { | ||
const doRenderLabel = light.name !== undefined && light.name !== ''; | ||
let userAutoClearSetting; //Holds the initial position and dimension of the HUD | ||
let userAutoClearSetting; | ||
//Holds the initial position and dimension of the HUD | ||
const frame = { | ||
@@ -48,4 +49,5 @@ x: 10, | ||
camera.position.set( 0, 0, 2 ); | ||
const scene = new THREE.Scene(); //HUD for shadow map | ||
const scene = new THREE.Scene(); | ||
//HUD for shadow map | ||
const shader = THREE.UnpackDepthRGBAShader; | ||
@@ -60,6 +62,6 @@ const uniforms = THREE.UniformsUtils.clone( shader.uniforms ); | ||
const mesh = new THREE.Mesh( plane, material ); | ||
scene.add( mesh ); //Label for light's name | ||
scene.add( mesh ); | ||
//Label for light's name | ||
let labelCanvas, labelMesh; | ||
if ( doRenderLabel ) { | ||
@@ -96,8 +98,9 @@ | ||
} //- API | ||
} | ||
//- API | ||
// Set to false to disable displaying this shadow map | ||
this.enabled = true; | ||
this.enabled = true; // Set the size of the displayed shadow map on the HUD | ||
// Set the size of the displayed shadow map on the HUD | ||
this.size = { | ||
@@ -110,9 +113,11 @@ width: frame.width, | ||
this.height = height; | ||
mesh.scale.set( this.width / frame.width, this.height / frame.height, 1 ); //Reset the position as it is off when we scale stuff | ||
mesh.scale.set( this.width / frame.width, this.height / frame.height, 1 ); | ||
//Reset the position as it is off when we scale stuff | ||
resetPosition(); | ||
} | ||
}; // Set the position of the displayed shadow map on the HUD | ||
}; | ||
// Set the position of the displayed shadow map on the HUD | ||
this.position = { | ||
@@ -132,3 +137,2 @@ x: frame.x, | ||
}; | ||
this.render = function ( renderer ) { | ||
@@ -146,3 +150,2 @@ | ||
renderer.autoClear = false; // To allow render overlay | ||
renderer.clearDepth(); | ||
@@ -176,5 +179,5 @@ renderer.render( scene, camera ); | ||
}; //Force an update to set position/size | ||
}; | ||
//Force an update to set position/size | ||
this.update(); | ||
@@ -181,0 +184,0 @@ |
@@ -19,4 +19,6 @@ ( function () { | ||
bones = target.isObject3D ? target.skeleton.bones : getBones( target ); | ||
let bindBones, bone, name, boneTo, bonesPosition; // reset bones | ||
let bindBones, bone, name, boneTo, bonesPosition; | ||
// reset bones | ||
if ( target.isObject3D ) { | ||
@@ -36,3 +38,2 @@ | ||
bonesPosition = []; | ||
for ( let i = 0; i < bones.length; i ++ ) { | ||
@@ -49,5 +50,8 @@ | ||
// reset matrix | ||
target.updateMatrixWorld(); | ||
target.matrixWorld.identity(); // reset children matrix | ||
target.matrixWorld.identity(); | ||
// reset children matrix | ||
for ( let i = 0; i < target.children.length; ++ i ) { | ||
@@ -64,3 +68,2 @@ | ||
bindBones = []; | ||
for ( let i = 0; i < bones.length; ++ i ) { | ||
@@ -70,3 +73,2 @@ | ||
name = options.names[ bone.name ] || bone.name; | ||
if ( options.offsets[ name ] ) { | ||
@@ -92,7 +94,5 @@ | ||
globalMatrix.copy( bone.matrixWorld ); | ||
if ( boneTo ) { | ||
boneTo.updateMatrixWorld(); | ||
if ( options.useTargetMatrix ) { | ||
@@ -107,10 +107,12 @@ | ||
} // ignore scale to extract rotation | ||
} | ||
// ignore scale to extract rotation | ||
scale.setFromMatrixScale( relativeMatrix ); | ||
relativeMatrix.scale( scale.set( 1 / scale.x, 1 / scale.y, 1 / scale.z ) ); // apply to global matrix | ||
relativeMatrix.scale( scale.set( 1 / scale.x, 1 / scale.y, 1 / scale.z ) ); | ||
// apply to global matrix | ||
globalMatrix.makeRotationFromQuaternion( quat.setFromRotationMatrix( relativeMatrix ) ); | ||
if ( target.isObject3D ) { | ||
@@ -156,3 +158,2 @@ | ||
name = options.names[ bone.name ] || bone.name; | ||
if ( name !== options.hip ) { | ||
@@ -171,2 +172,3 @@ | ||
// restore matrix | ||
target.updateMatrixWorld( true ); | ||
@@ -183,3 +185,2 @@ | ||
options.names = options.names || []; | ||
if ( ! source.isObject3D ) { | ||
@@ -201,3 +202,2 @@ | ||
source.updateMatrixWorld(); | ||
for ( let i = 0; i < numFrames; ++ i ) { | ||
@@ -207,3 +207,2 @@ | ||
retarget( target, source, options ); | ||
for ( let j = 0; j < bones.length; ++ j ) { | ||
@@ -213,3 +212,2 @@ | ||
boneTo = getBoneByName( name, source.skeleton ); | ||
if ( boneTo ) { | ||
@@ -221,3 +219,2 @@ | ||
}; | ||
if ( options.hip === name ) { | ||
@@ -275,3 +272,2 @@ | ||
boneData = boneDatas[ i ]; | ||
if ( boneData ) { | ||
@@ -314,3 +310,2 @@ | ||
options.names = options.names || {}; | ||
if ( ! source.isObject3D ) { | ||
@@ -329,3 +324,2 @@ | ||
target.skeleton.pose(); | ||
for ( i = 0; i < bones.length; ++ i ) { | ||
@@ -336,3 +330,2 @@ | ||
boneTo = getBoneByName( name, sourceBones ); | ||
if ( boneTo && name !== options.hip ) { | ||
@@ -368,7 +361,5 @@ | ||
const bones = getBones( skeleton ); | ||
for ( let i = 0; i < bones.length; ++ i ) { | ||
const bone = bones[ i ]; | ||
if ( names[ bone.name ] ) { | ||
@@ -424,3 +415,2 @@ | ||
}; | ||
for ( let i = 0; i < tracks.length; ++ i ) { | ||
@@ -431,3 +421,2 @@ | ||
const trackData = regexp.exec( tracks[ i ].name ); | ||
if ( trackData && name === trackData[ 1 ] ) { | ||
@@ -450,7 +439,5 @@ | ||
bones = []; | ||
search: for ( let i = 0; i < sourceBones.length; i ++ ) { | ||
const boneName = sourceBones[ i ].name; | ||
for ( let j = 0; j < targetBones.length; j ++ ) { | ||
@@ -507,3 +494,2 @@ | ||
callback( a, b ); | ||
for ( let i = 0; i < a.children.length; i ++ ) { | ||
@@ -510,0 +496,0 @@ |
@@ -14,2 +14,3 @@ ( function () { | ||
// handles wrapping of uv.x > 1 only | ||
const abc = 'abc'; | ||
@@ -22,3 +23,2 @@ const a = new THREE.Vector2(); | ||
const width = size; // power of 2 required for wrapping | ||
const height = size; | ||
@@ -30,4 +30,6 @@ canvas.width = width; | ||
ctx.strokeStyle = 'rgb( 63, 63, 63 )'; | ||
ctx.textAlign = 'center'; // paint background white | ||
ctx.textAlign = 'center'; | ||
// paint background white | ||
ctx.fillStyle = 'rgb( 255, 255, 255 )'; | ||
@@ -37,6 +39,6 @@ ctx.fillRect( 0, 0, width, height ); | ||
const uvAttribute = geometry.attributes.uv; | ||
if ( index ) { | ||
// indexed geometry | ||
for ( let i = 0, il = index.count; i < il; i += 3 ) { | ||
@@ -57,2 +59,3 @@ | ||
// non-indexed geometry | ||
for ( let i = 0, il = uvAttribute.count; i < il; i += 3 ) { | ||
@@ -73,9 +76,8 @@ | ||
return canvas; | ||
function processFace( face, uvs, index ) { | ||
// draw contour of face | ||
ctx.beginPath(); | ||
a.set( 0, 0 ); | ||
for ( let j = 0, jl = uvs.length; j < jl; j ++ ) { | ||
@@ -86,3 +88,2 @@ | ||
a.y += uv.y; | ||
if ( j === 0 ) { | ||
@@ -101,21 +102,28 @@ | ||
ctx.closePath(); | ||
ctx.stroke(); // calculate center of face | ||
ctx.stroke(); | ||
a.divideScalar( uvs.length ); // label the face number | ||
// calculate center of face | ||
a.divideScalar( uvs.length ); | ||
// label the face number | ||
ctx.font = '18px Arial'; | ||
ctx.fillStyle = 'rgb( 63, 63, 63 )'; | ||
ctx.fillText( index, a.x * width, ( 1 - a.y ) * height ); | ||
if ( a.x > 0.95 ) { | ||
// wrap x // 0.95 is arbitrary | ||
ctx.fillText( index, a.x % 1 * width, ( 1 - a.y ) * height ); | ||
} // | ||
} | ||
// | ||
ctx.font = '12px Arial'; | ||
ctx.fillStyle = 'rgb( 191, 191, 191 )'; // label uv edge orders | ||
ctx.fillStyle = 'rgb( 191, 191, 191 )'; | ||
// label uv edge orders | ||
for ( let j = 0, jl = uvs.length; j < jl; j ++ ) { | ||
@@ -127,6 +135,6 @@ | ||
ctx.fillText( abc[ j ] + vnum, b.x * width, ( 1 - b.y ) * height ); | ||
if ( b.x > 0.95 ) { | ||
// wrap x | ||
ctx.fillText( abc[ j ] + vnum, b.x % 1 * width, ( 1 - b.y ) * height ); | ||
@@ -133,0 +141,0 @@ |
@@ -6,2 +6,3 @@ ( function () { | ||
*/ | ||
class WorkerPool { | ||
@@ -18,3 +19,2 @@ | ||
} | ||
_initWorker( workerId ) { | ||
@@ -31,11 +31,8 @@ | ||
} | ||
_getIdleWorker() { | ||
for ( let i = 0; i < this.pool; i ++ ) if ( ! ( this.workerStatus & 1 << i ) ) return i; | ||
return - 1; | ||
} | ||
_onMessage( workerId, msg ) { | ||
@@ -45,3 +42,2 @@ | ||
resolve && resolve( msg ); | ||
if ( this.queue.length ) { | ||
@@ -64,3 +60,2 @@ | ||
} | ||
setWorkerCreator( workerCreator ) { | ||
@@ -71,3 +66,2 @@ | ||
} | ||
setWorkerLimit( pool ) { | ||
@@ -78,3 +72,2 @@ | ||
} | ||
postMessage( msg, transfer ) { | ||
@@ -85,7 +78,5 @@ | ||
const workerId = this._getIdleWorker(); | ||
if ( workerId !== - 1 ) { | ||
this._initWorker( workerId ); | ||
this.workerStatus |= 1 << workerId; | ||
@@ -108,3 +99,2 @@ this.workersResolve[ workerId ] = resolve; | ||
} | ||
dispose() { | ||
@@ -111,0 +101,0 @@ |
@@ -54,2 +54,6 @@ import { | ||
} else if ( object.isCamera ) { | ||
output += buildCamera( object ); | ||
} | ||
@@ -559,2 +563,47 @@ | ||
function buildCamera( camera ) { | ||
const name = camera.name ? camera.name : 'Camera_' + camera.id; | ||
const transform = buildMatrix( camera.matrixWorld ); | ||
if ( camera.matrixWorld.determinant() < 0 ) { | ||
console.warn( 'THREE.USDZExporter: USDZ does not support negative scales', camera ); | ||
} | ||
if (camera.isOrthographicCamera) { | ||
return `def Camera "${name}" | ||
{ | ||
matrix4d xformOp:transform = ${ transform } | ||
uniform token[] xformOpOrder = ["xformOp:transform"] | ||
float2 clippingRange = (${camera.near}, ${camera.far}) | ||
float horizontalAperture = ${(Math.abs(camera.left) + Math.abs(camera.right)) * 10} | ||
float verticalAperture = ${(Math.abs(camera.top) + Math.abs(camera.bottom)) * 10} | ||
token projection = "orthographic" | ||
} | ||
`; | ||
} else { | ||
return `def Camera "${name}" | ||
{ | ||
matrix4d xformOp:transform = ${ transform } | ||
uniform token[] xformOpOrder = ["xformOp:transform"] | ||
float2 clippingRange = (${camera.near}, ${camera.far}) | ||
float focalLength = ${camera.getFocalLength()} | ||
float focusDistance = ${camera.focus} | ||
float horizontalAperture = ${camera.getFilmWidth()} | ||
token projection = "perspective" | ||
float verticalAperture = ${camera.getFilmHeight()} | ||
} | ||
`; | ||
} | ||
} | ||
export { USDZExporter }; |
@@ -39,2 +39,4 @@ import { | ||
material.map.dispose(); | ||
canvases.delete( dom ); | ||
@@ -41,0 +43,0 @@ this.removeEventListener( 'mousedown', onEvent ); |
@@ -16,2 +16,3 @@ /** | ||
CompressedTexture, | ||
CompressedArrayTexture, | ||
Data3DTexture, | ||
@@ -39,3 +40,3 @@ DataTexture, | ||
sRGBEncoding, | ||
UnsignedByteType | ||
UnsignedByteType, | ||
} from 'three'; | ||
@@ -241,3 +242,3 @@ import { WorkerPool } from '../utils/WorkerPool.js'; | ||
_createTextureFrom( transcodeResult ) { | ||
_createTextureFrom( transcodeResult, container ) { | ||
@@ -248,6 +249,11 @@ const { mipmaps, width, height, format, type, error, dfdTransferFn, dfdFlags } = transcodeResult; | ||
const texture = new CompressedTexture( mipmaps, width, height, format, UnsignedByteType ); | ||
const texture = container.layerCount > 1 | ||
? new CompressedArrayTexture( mipmaps, width, height, container.layerCount, format, UnsignedByteType ) | ||
: new CompressedTexture( mipmaps, width, height, format, UnsignedByteType ); | ||
texture.minFilter = mipmaps.length === 1 ? LinearFilter : LinearMipmapLinearFilter; | ||
texture.magFilter = LinearFilter; | ||
texture.generateMipmaps = false; | ||
texture.needsUpdate = true; | ||
@@ -264,5 +270,5 @@ texture.encoding = dfdTransferFn === KHR_DF_TRANSFER_SRGB ? sRGBEncoding : LinearEncoding; | ||
* @param {object?} config | ||
* @return {Promise<CompressedTexture|DataTexture|Data3DTexture>} | ||
* @return {Promise<CompressedTexture|CompressedArrayTexture|DataTexture|Data3DTexture>} | ||
*/ | ||
_createTexture( buffer, config = {} ) { | ||
async _createTexture( buffer, config = {} ) { | ||
@@ -278,3 +284,2 @@ const container = read( new Uint8Array( buffer ) ); | ||
// | ||
const taskConfig = config; | ||
@@ -285,3 +290,3 @@ const texturePending = this.init().then( () => { | ||
} ).then( ( e ) => this._createTextureFrom( e.data ) ); | ||
} ).then( ( e ) => this._createTextureFrom( e.data, container ) ); | ||
@@ -447,2 +452,3 @@ // Cache the task result. | ||
const height = ktx2File.getHeight(); | ||
const layers = ktx2File.getLayers() || 1; | ||
const levels = ktx2File.getLevels(); | ||
@@ -473,26 +479,35 @@ const hasAlpha = ktx2File.getHasAlpha(); | ||
const levelInfo = ktx2File.getImageLevelInfo( mip, 0, 0 ); | ||
const mipWidth = levelInfo.origWidth; | ||
const mipHeight = levelInfo.origHeight; | ||
const dst = new Uint8Array( ktx2File.getImageTranscodedSizeInBytes( mip, 0, 0, transcoderFormat ) ); | ||
const layerMips = []; | ||
const status = ktx2File.transcodeImage( | ||
dst, | ||
mip, | ||
0, | ||
0, | ||
transcoderFormat, | ||
0, | ||
- 1, | ||
- 1, | ||
); | ||
let mipWidth, mipHeight; | ||
if ( ! status ) { | ||
for ( let layer = 0; layer < layers; layer ++ ) { | ||
cleanup(); | ||
throw new Error( 'THREE.KTX2Loader: .transcodeImage failed.' ); | ||
const levelInfo = ktx2File.getImageLevelInfo( mip, layer, 0 ); | ||
mipWidth = levelInfo.origWidth; | ||
mipHeight = levelInfo.origHeight; | ||
const dst = new Uint8Array( ktx2File.getImageTranscodedSizeInBytes( mip, layer, 0, transcoderFormat ) ); | ||
const status = ktx2File.transcodeImage( | ||
dst, | ||
mip, | ||
layer, | ||
0, | ||
transcoderFormat, | ||
0, | ||
- 1, | ||
- 1, | ||
); | ||
if ( ! status ) { | ||
cleanup(); | ||
throw new Error( 'THREE.KTX2Loader: .transcodeImage failed.' ); | ||
} | ||
layerMips.push( dst ); | ||
} | ||
mipmaps.push( { data: dst, width: mipWidth, height: mipHeight } ); | ||
mipmaps.push( { data: concat( layerMips ), width: mipWidth, height: mipHeight } ); | ||
@@ -624,2 +639,29 @@ } | ||
/** Concatenates N byte arrays. */ | ||
function concat( arrays ) { | ||
let totalByteLength = 0; | ||
for ( const array of arrays ) { | ||
totalByteLength += array.byteLength; | ||
} | ||
const result = new Uint8Array( totalByteLength ); | ||
let byteOffset = 0; | ||
for ( const array of arrays ) { | ||
result.set( array, byteOffset ); | ||
byteOffset += array.byteLength; | ||
} | ||
return result; | ||
} | ||
}; | ||
@@ -686,4 +728,2 @@ | ||
// | ||
const level = container.levels[ 0 ]; | ||
@@ -745,3 +785,2 @@ | ||
} | ||
// | ||
@@ -748,0 +787,0 @@ |
@@ -8,2 +8,4 @@ import { | ||
import lottie from '../libs/lottie_canvas.module.js'; | ||
class LottieLoader extends Loader { | ||
@@ -32,3 +34,3 @@ | ||
// bodymoving uses container.offetWidth and offsetHeight | ||
// lottie uses container.offetWidth and offsetHeight | ||
// to define width/height | ||
@@ -41,3 +43,3 @@ | ||
const animation = bodymovin.loadAnimation( { | ||
const animation = lottie.loadAnimation( { | ||
container: container, | ||
@@ -44,0 +46,0 @@ animType: 'canvas', |
@@ -21,3 +21,3 @@ import { Vector3 } from 'three'; | ||
this.updateType = NodeUpdateType.Object; | ||
this.updateType = NodeUpdateType.OBJECT; | ||
@@ -24,0 +24,0 @@ this._uniformNode = new UniformNode( null ); |
@@ -13,2 +13,3 @@ import Node from '../core/Node.js'; | ||
static WORLD = 'world'; | ||
static WORLD_DIRECTION = 'worldDirection'; | ||
static VIEW = 'view'; | ||
@@ -60,2 +61,7 @@ static VIEW_DIRECTION = 'viewDirection'; | ||
} else if ( scope === PositionNode.WORLD_DIRECTION ) { | ||
const vertexPositionNode = new MathNode( MathNode.NEGATE, new PositionNode( PositionNode.WORLD ) ); | ||
outputNode = new MathNode( MathNode.NORMALIZE, new VaryingNode( vertexPositionNode ) ); | ||
} | ||
@@ -62,0 +68,0 @@ |
@@ -19,3 +19,3 @@ import Node from '../core/Node.js'; | ||
this.updateType = NodeUpdateType.Object; | ||
this.updateType = NodeUpdateType.OBJECT; | ||
@@ -22,0 +22,0 @@ this.setNodeType( uniformType ); |
@@ -76,3 +76,3 @@ import Node from '../core/Node.js'; | ||
this.updateType = NodeUpdateType.Object; | ||
this.updateType = NodeUpdateType.OBJECT; | ||
@@ -79,0 +79,0 @@ // |
export const NodeShaderStage = { | ||
Vertex: 'vertex', | ||
Fragment: 'fragment' | ||
VERTEX: 'vertex', | ||
FRAGMENT: 'fragment' | ||
}; | ||
export const NodeUpdateType = { | ||
None: 'none', | ||
Frame: 'frame', | ||
Object: 'object' | ||
NONE: 'none', | ||
FRAME: 'frame', | ||
OBJECT: 'object' | ||
}; | ||
export const NodeType = { | ||
Boolean: 'bool', | ||
Integer: 'int', | ||
Float: 'float', | ||
Vector2: 'vec2', | ||
Vector3: 'vec3', | ||
Vector4: 'vec4', | ||
Matrix3: 'mat3', | ||
Matrix4: 'mat4' | ||
BOOLEAN: 'bool', | ||
INTEGER: 'int', | ||
FLOAT: 'float', | ||
VECTOR2: 'vec2', | ||
VECTOR3: 'vec3', | ||
VECTOR4: 'vec4', | ||
MATRIX3: 'mat3', | ||
MATRIX4: 'mat4' | ||
}; |
@@ -15,3 +15,3 @@ import { NodeUpdateType } from './constants.js'; | ||
this.updateType = NodeUpdateType.None; | ||
this.updateType = NodeUpdateType.NONE; | ||
@@ -18,0 +18,0 @@ this.uuid = MathUtils.generateUUID(); |
@@ -120,3 +120,3 @@ import NodeUniform from './NodeUniform.js'; | ||
if ( updateType !== NodeUpdateType.None ) { | ||
if ( updateType !== NodeUpdateType.NONE ) { | ||
@@ -123,0 +123,0 @@ this.updateNodes.push( node ); |
@@ -25,3 +25,3 @@ import { NodeUpdateType } from './constants.js'; | ||
if ( node.updateType === NodeUpdateType.Frame ) { | ||
if ( node.updateType === NodeUpdateType.FRAME ) { | ||
@@ -36,3 +36,3 @@ if ( this.updateMap.get( node ) !== this.frameId ) { | ||
} else if ( node.updateType === NodeUpdateType.Object ) { | ||
} else if ( node.updateType === NodeUpdateType.OBJECT ) { | ||
@@ -39,0 +39,0 @@ node.update( this ); |
@@ -1,10 +0,13 @@ | ||
class NodeVarying { | ||
import NodeVar from './NodeVar.js'; | ||
class NodeVarying extends NodeVar { | ||
constructor( name, type ) { | ||
super( name, type ); | ||
this.needsInterpolation = false; | ||
this.isNodeVarying = true; | ||
this.name = name; | ||
this.type = type; | ||
} | ||
@@ -11,0 +14,0 @@ |
@@ -31,8 +31,10 @@ import Node from './Node.js'; | ||
const { name, node } = this; | ||
const type = this.getNodeType( builder ); | ||
const node = this.node; | ||
const name = this.name; | ||
const nodeVarying = builder.getVaryingFromNode( this, type ); | ||
// this property can be used to check if the varying can be optimized for a var | ||
nodeVarying.needsInterpolation ||= builder.shaderStage === 'fragment'; | ||
if ( name !== null ) { | ||
@@ -44,6 +46,6 @@ | ||
const propertyName = builder.getPropertyName( nodeVarying, NodeShaderStage.Vertex ); | ||
const propertyName = builder.getPropertyName( nodeVarying, NodeShaderStage.VERTEX ); | ||
// force node run in vertex stage | ||
builder.flowNodeFromShaderStage( NodeShaderStage.Vertex, node, type, propertyName ); | ||
builder.flowNodeFromShaderStage( NodeShaderStage.VERTEX, node, type, propertyName ); | ||
@@ -50,0 +52,0 @@ return builder.getPropertyName( nodeVarying ); |
@@ -18,3 +18,3 @@ import Node from '../core/Node.js'; | ||
this.updateType = NodeUpdateType.Object; | ||
this.updateType = NodeUpdateType.OBJECT; | ||
@@ -21,0 +21,0 @@ this.updateDispatchCount(); |
@@ -13,3 +13,3 @@ import LightingNode from './LightingNode.js'; | ||
this.updateType = NodeUpdateType.Object; | ||
this.updateType = NodeUpdateType.OBJECT; | ||
@@ -16,0 +16,0 @@ this.light = light; |
@@ -7,2 +7,3 @@ import { MaterialLoader } from 'three'; | ||
MeshStandardNodeMaterial, | ||
MeshPhysicalNodeMaterial, | ||
PointsNodeMaterial, | ||
@@ -21,4 +22,5 @@ SpriteNodeMaterial | ||
MeshStandardNodeMaterial, | ||
MeshPhysicalNodeMaterial, | ||
PointsNodeMaterial, | ||
SpriteNodeMaterial, | ||
SpriteNodeMaterial | ||
}; | ||
@@ -25,0 +27,0 @@ |
@@ -8,3 +8,4 @@ import { | ||
import { mx_hsvtorgb, mx_rgbtohsv } from './lib/mx_hsv.js'; | ||
import { nodeObject, float, vec2, vec4, add, sub, mul, mix, clamp, uv, length, smoothstep, dFdx, dFdy, convert } from '../shadernode/ShaderNodeElements.js'; | ||
import { mx_srgb_texture_to_lin_rec709 } from './lib/mx_transform_color.js'; | ||
import { nodeObject, float, vec2, vec4, add, sub, mul, mix, clamp, uv, length, smoothstep, dFdx, dFdy, sign, pow, abs, convert } from '../shadernode/ShaderNodeElements.js'; | ||
@@ -32,2 +33,5 @@ export const mx_aastep = ( threshold, value ) => { | ||
export const mx_safepower = ( in1, in2 = 1 ) => mul( sign( in1 ), pow( abs( in1 ), in2 ) ); | ||
export const mx_contrast = ( input, amount = 1, pivot = .5 ) => add( mul( sub( input, pivot ), amount ), pivot ); | ||
export const mx_noise_float = ( texcoord = uv(), amplitude = 1, pivot = 0 ) => add( mul( amplitude, mx_perlin_noise_float( convert( texcoord, 'vec2|vec3' ) ) ), pivot ); | ||
@@ -57,2 +61,2 @@ export const mx_noise_vec2 = ( texcoord = uv(), amplitude = 1, pivot = 0 ) => add( mul( amplitude, mx_perlin_noise_vec2( convert( texcoord, 'vec2|vec3' ) ) ), pivot ); | ||
export { mx_hsvtorgb, mx_rgbtohsv }; | ||
export { mx_hsvtorgb, mx_rgbtohsv, mx_srgb_texture_to_lin_rec709 }; |
@@ -36,2 +36,3 @@ import TempNode from '../core/TempNode.js'; | ||
static ROUND = 'round'; | ||
static RECIPROCAL = 'reciprocal'; | ||
@@ -163,2 +164,6 @@ // 2 inputs | ||
} else if ( method === MathNode.RECIPROCAL ) { | ||
return builder.format( '( 1.0 / ' + a.build( builder, inputType ) + ' )', type, output ); | ||
} else { | ||
@@ -165,0 +170,0 @@ |
@@ -62,2 +62,3 @@ // core | ||
import NormalMapNode from './display/NormalMapNode.js'; | ||
import PosterizeNode from './display/PosterizeNode.js'; | ||
import ToneMappingNode from './display/ToneMappingNode.js'; | ||
@@ -83,2 +84,3 @@ | ||
import ConvertNode from './utils/ConvertNode.js'; | ||
import EquirectUVNode from './utils/EquirectUVNode.js'; | ||
import JoinNode from './utils/JoinNode.js'; | ||
@@ -93,2 +95,3 @@ import MatcapUVNode from './utils/MatcapUVNode.js'; | ||
import TimerNode from './utils/TimerNode.js'; | ||
import TriplanarTexturesNode from './utils/TriplanarTexturesNode.js'; | ||
@@ -188,2 +191,3 @@ // loaders | ||
NormalMapNode, | ||
PosterizeNode, | ||
ToneMappingNode, | ||
@@ -209,2 +213,3 @@ | ||
ConvertNode, | ||
EquirectUVNode, | ||
JoinNode, | ||
@@ -219,2 +224,3 @@ MatcapUVNode, | ||
TimerNode, | ||
TriplanarTexturesNode, | ||
@@ -235,3 +241,3 @@ // procedural | ||
WGSLNodeParser, | ||
GLSLNodeParser, | ||
GLSLNodeParser | ||
@@ -308,2 +314,3 @@ }; | ||
NormalMapNode, | ||
PosterizeNode, | ||
ToneMappingNode, | ||
@@ -329,2 +336,3 @@ | ||
ConvertNode, | ||
EquirectUVNode, | ||
JoinNode, | ||
@@ -339,2 +347,3 @@ MatcapUVNode, | ||
TimerNode, | ||
TriplanarTexturesNode, | ||
@@ -355,3 +364,3 @@ // procedural | ||
WGSLNodeParser, | ||
GLSLNodeParser, | ||
GLSLNodeParser | ||
}; |
@@ -184,2 +184,3 @@ // core | ||
export const round = nodeProxy( MathNode, MathNode.ROUND ); | ||
export const reciprocal = nodeProxy( MathNode, MathNode.RECIPROCAL ); | ||
@@ -269,2 +270,3 @@ export const atan2 = nodeProxy( MathNode, MathNode.ATAN2 ); | ||
export const positionWorld = nodeImmutable( PositionNode, PositionNode.WORLD ); | ||
export const positionWorldDirection = nodeImmutable( PositionNode, PositionNode.WORLD_DIRECTION ); | ||
export const positionView = nodeImmutable( PositionNode, PositionNode.VIEW ); | ||
@@ -271,0 +273,0 @@ export const positionViewDirection = nodeImmutable( PositionNode, PositionNode.VIEW_DIRECTION ); |
@@ -12,2 +12,3 @@ // accessors | ||
import NormalMapNode from '../display/NormalMapNode.js'; | ||
import PosterizeNode from '../display/PosterizeNode.js'; | ||
import ToneMappingNode from '../display/ToneMappingNode.js'; | ||
@@ -21,2 +22,3 @@ | ||
// utils | ||
import EquirectUVNode from '../utils/EquirectUVNode.js'; | ||
import MatcapUVNode from '../utils/MatcapUVNode.js'; | ||
@@ -29,2 +31,3 @@ import MaxMipLevelNode from '../utils/MaxMipLevelNode.js'; | ||
import TimerNode from '../utils/TimerNode.js'; | ||
import TriplanarTexturesNode from '../utils/TriplanarTexturesNode.js'; | ||
@@ -93,2 +96,4 @@ // geometry | ||
export const posterize = nodeProxy( PosterizeNode ); | ||
// lighting | ||
@@ -104,2 +109,4 @@ | ||
export const matcapUV = nodeImmutable( MatcapUVNode ); | ||
export const equirectUV = nodeProxy( EquirectUVNode ); | ||
export const maxMipLevel = nodeProxy( MaxMipLevelNode ); | ||
@@ -125,2 +132,5 @@ | ||
export const triplanarTextures = nodeProxy( TriplanarTexturesNode ); | ||
export const triplanarTexture = ( texture, ...params ) => triplanarTextures( texture, texture, texture, ...params ); | ||
// geometry | ||
@@ -127,0 +137,0 @@ |
@@ -12,3 +12,3 @@ import TempNode from '../core/TempNode.js'; | ||
generate( builder ) { | ||
construct() { | ||
@@ -18,6 +18,4 @@ const x = normalize( vec3( positionViewDirection.z, 0, negate( positionViewDirection.x ) ) ); | ||
const uv = add( mul( vec2( dot( x, transformedNormalView ), dot( y, transformedNormalView ) ), 0.495 ), 0.5 ); | ||
return add( mul( vec2( dot( x, transformedNormalView ), dot( y, transformedNormalView ) ), 0.495 ), 0.5 ); | ||
return uv.build( builder, this.getNodeType( builder ) ); | ||
} | ||
@@ -24,0 +22,0 @@ |
@@ -12,3 +12,3 @@ import UniformNode from '../core/UniformNode.js'; | ||
this.updateType = NodeUpdateType.Frame; | ||
this.updateType = NodeUpdateType.FRAME; | ||
@@ -15,0 +15,0 @@ } |
@@ -21,16 +21,14 @@ import Node from '../core/Node.js'; | ||
generate( builder ) { | ||
construct() { | ||
const count = this.countNode; | ||
const uv = this.uvNode; | ||
const frame = this.frameNode; | ||
const { frameNode, uvNode, countNode } = this; | ||
const one = new ConstNode( 1 ); | ||
const width = new SplitNode( count, 'x' ); | ||
const height = new SplitNode( count, 'y' ); | ||
const width = new SplitNode( countNode, 'x' ); | ||
const height = new SplitNode( countNode, 'y' ); | ||
const total = new OperatorNode( '*', width, height ); | ||
const roundFrame = new MathNode( MathNode.FLOOR, new MathNode( MathNode.MOD, frame, total ) ); | ||
const roundFrame = new MathNode( MathNode.FLOOR, new MathNode( MathNode.MOD, frameNode, total ) ); | ||
@@ -43,3 +41,3 @@ const frameNum = new OperatorNode( '+', roundFrame, one ); | ||
const scale = new OperatorNode( '/', one, count ); | ||
const scale = new OperatorNode( '/', one, countNode ); | ||
@@ -51,6 +49,6 @@ const uvFrameOffset = new JoinNode( [ | ||
const uvScale = new OperatorNode( '*', uv, scale ); | ||
const uvScale = new OperatorNode( '*', uvNode, scale ); | ||
const uvFrame = new OperatorNode( '+', uvScale, uvFrameOffset ); | ||
return uvFrame.build( builder, this.getNodeType( builder ) ); | ||
return uvFrame; | ||
@@ -57,0 +55,0 @@ } |
@@ -18,3 +18,3 @@ import UniformNode from '../core/UniformNode.js'; | ||
this.updateType = NodeUpdateType.Frame; | ||
this.updateType = NodeUpdateType.FRAME; | ||
@@ -21,0 +21,0 @@ } |
@@ -33,3 +33,3 @@ import { | ||
this.shaderMaterial = new ShaderMaterial( { | ||
this.compFsMaterial = new ShaderMaterial( { | ||
@@ -42,6 +42,6 @@ uniforms: this.uniforms, | ||
this.compFsQuad = new FullScreenQuad( this.shaderMaterial ); | ||
this.compFsQuad = new FullScreenQuad( this.compFsMaterial ); | ||
const material = new MeshBasicMaterial(); | ||
this.copyFsQuad = new FullScreenQuad( material ); | ||
this.copyFsMaterial = new MeshBasicMaterial(); | ||
this.copyFsQuad = new FullScreenQuad( this.copyFsMaterial ); | ||
@@ -90,4 +90,17 @@ } | ||
dispose() { | ||
this.textureComp.dispose(); | ||
this.textureOld.dispose(); | ||
this.compFsMaterial.dispose(); | ||
this.copyFsMaterial.dispose(); | ||
this.compFsQuad.dispose(); | ||
this.copyFsQuad.dispose(); | ||
} | ||
} | ||
export { AfterimagePass }; |
@@ -13,3 +13,3 @@ import { | ||
constructor( strength = 1, kernelSize = 25, sigma = 4, resolution = 256 ) { | ||
constructor( strength = 1, kernelSize = 25, sigma = 4 ) { | ||
@@ -20,5 +20,5 @@ super(); | ||
this.renderTargetX = new WebGLRenderTarget( resolution, resolution ); | ||
this.renderTargetX = new WebGLRenderTarget(); // will be resized later | ||
this.renderTargetX.texture.name = 'BloomPass.x'; | ||
this.renderTargetY = new WebGLRenderTarget( resolution, resolution ); | ||
this.renderTargetY = new WebGLRenderTarget(); // will be resized later | ||
this.renderTargetY.texture.name = 'BloomPass.y'; | ||
@@ -110,2 +110,21 @@ | ||
setSize( width, height ) { | ||
this.renderTargetX.setSize( width, height ); | ||
this.renderTargetY.setSize( width, height ); | ||
} | ||
dispose() { | ||
this.renderTargetX.dispose(); | ||
this.renderTargetY.dispose(); | ||
this.materialCombine.dispose(); | ||
this.materialConvolution.dispose(); | ||
this.fsQuad.dispose(); | ||
} | ||
} | ||
@@ -112,0 +131,0 @@ |
@@ -34,6 +34,3 @@ import { | ||
const width = params.width || window.innerWidth || 1; | ||
const height = params.height || window.innerHeight || 1; | ||
this.renderTargetDepth = new WebGLRenderTarget( width, height, { | ||
this.renderTargetDepth = new WebGLRenderTarget( 1, 1, { // will be resized later | ||
minFilter: NearestFilter, | ||
@@ -130,4 +127,21 @@ magFilter: NearestFilter | ||
setSize( width, height ) { | ||
this.renderTargetDepth.setSize( width, height ); | ||
} | ||
dispose() { | ||
this.renderTargetDepth.dispose(); | ||
this.materialDepth.dispose(); | ||
this.materialBokeh.dispose(); | ||
this.fsQuad.dispose(); | ||
} | ||
} | ||
export { BokehPass }; |
@@ -15,3 +15,3 @@ import { | ||
constructor( camera, envMap, opacity = 1 ) { | ||
constructor( camera, tCube, opacity = 1 ) { | ||
@@ -41,3 +41,3 @@ super(); | ||
return this.uniforms.envMap.value; | ||
return this.uniforms.tCube.value; | ||
@@ -48,3 +48,3 @@ } | ||
this.envMap = envMap; | ||
this.tCube = tCube; | ||
this.opacity = opacity; | ||
@@ -66,4 +66,4 @@ | ||
this.cubeMesh.material.uniforms.envMap.value = this.envMap; | ||
this.cubeMesh.material.uniforms.flipEnvMap.value = ( this.envMap.isCubeTexture && this.envMap.isRenderTargetTexture === false ) ? - 1 : 1; | ||
this.cubeMesh.material.uniforms.tCube.value = this.tCube; | ||
this.cubeMesh.material.uniforms.tFlip.value = ( this.tCube.isCubeTexture && this.tCube.isRenderTargetTexture === false ) ? - 1 : 1; | ||
this.cubeMesh.material.uniforms.opacity.value = this.opacity; | ||
@@ -80,4 +80,11 @@ this.cubeMesh.material.transparent = ( this.opacity < 1.0 ); | ||
dispose() { | ||
this.cubeMesh.geometry.dispose(); | ||
this.cubeMesh.material.dispose(); | ||
} | ||
} | ||
export { CubeTexturePass }; |
@@ -56,4 +56,12 @@ import { | ||
dispose() { | ||
this.material.dispose(); | ||
this.fsQuad.dispose(); | ||
} | ||
} | ||
export { DotScreenPass }; |
@@ -235,2 +235,11 @@ import { | ||
dispose() { | ||
this.renderTarget1.dispose(); | ||
this.renderTarget2.dispose(); | ||
this.copyPass.dispose(); | ||
} | ||
} | ||
@@ -237,0 +246,0 @@ |
@@ -57,4 +57,12 @@ import { | ||
dispose() { | ||
this.material.dispose(); | ||
this.fsQuad.dispose(); | ||
} | ||
} | ||
export { FilmPass }; |
@@ -25,4 +25,6 @@ import { | ||
this.uniforms[ 'tDisp' ].value = this.generateHeightmap( dt_size ); | ||
this.heightMap = this.generateHeightmap( dt_size ); | ||
this.uniforms[ 'tDisp' ].value = this.heightMap; | ||
this.material = new ShaderMaterial( { | ||
@@ -117,4 +119,14 @@ uniforms: this.uniforms, | ||
dispose() { | ||
this.material.dispose(); | ||
this.heightMap.dispose(); | ||
this.fsQuad.dispose(); | ||
} | ||
} | ||
export { GlitchPass }; |
@@ -75,4 +75,12 @@ import { | ||
dispose() { | ||
this.material.dispose(); | ||
this.fsQuad.dispose(); | ||
} | ||
} | ||
export { HalftonePass }; |
@@ -143,2 +143,12 @@ import { | ||
this.depthMaterial.dispose(); | ||
this.prepareMaskMaterial.dispose(); | ||
this.edgeDetectionMaterial.dispose(); | ||
this.separableBlurMaterial1.dispose(); | ||
this.separableBlurMaterial2.dispose(); | ||
this.overlayMaterial.dispose(); | ||
this.materialCopy.dispose(); | ||
this.fsQuad.dispose(); | ||
} | ||
@@ -145,0 +155,0 @@ |
@@ -34,2 +34,4 @@ import { | ||
dispose() {} | ||
} | ||
@@ -36,0 +38,0 @@ |
@@ -403,2 +403,22 @@ import { | ||
dispose() { | ||
this.saoRenderTarget.dispose(); | ||
this.blurIntermediateRenderTarget.dispose(); | ||
this.beautyRenderTarget.dispose(); | ||
this.normalRenderTarget.dispose(); | ||
this.depthRenderTarget.dispose(); | ||
this.depthMaterial.dispose(); | ||
this.normalMaterial.dispose(); | ||
this.saoMaterial.dispose(); | ||
this.vBlurMaterial.dispose(); | ||
this.hBlurMaterial.dispose(); | ||
this.materialCopy.dispose(); | ||
this.depthCopy.dispose(); | ||
this.fsQuad.dispose(); | ||
} | ||
} | ||
@@ -405,0 +425,0 @@ |
@@ -35,3 +35,3 @@ import { | ||
this.renderTarget = new WebGLRenderTarget( window.innerWidth, window.innerHeight ); | ||
this.renderTarget = new WebGLRenderTarget(); // will be resized later | ||
this.renderTarget.texture.name = 'SavePass.rt'; | ||
@@ -61,4 +61,20 @@ | ||
setSize( width, height ) { | ||
this.renderTarget.setSize( width, height ); | ||
} | ||
dispose() { | ||
this.renderTarget.dispose(); | ||
this.material.dispose(); | ||
this.fsQuad.dispose(); | ||
} | ||
} | ||
export { SavePass }; |
@@ -66,4 +66,12 @@ import { | ||
dispose() { | ||
this.material.dispose(); | ||
this.fsQuad.dispose(); | ||
} | ||
} | ||
export { ShaderPass }; |
@@ -186,4 +186,20 @@ import { | ||
dispose() { | ||
this.edgesRT.dispose(); | ||
this.weightsRT.dispose(); | ||
this.areaTexture.dispose(); | ||
this.searchTexture.dispose(); | ||
this.materialEdges.dispose(); | ||
this.materialWeights.dispose(); | ||
this.materialBlend.dispose(); | ||
this.fsQuad.dispose(); | ||
} | ||
} | ||
export { SMAAPass }; |
@@ -66,2 +66,6 @@ import { | ||
this.copyMaterial.dispose(); | ||
this.fsQuad.dispose(); | ||
} | ||
@@ -68,0 +72,0 @@ |
@@ -133,2 +133,11 @@ import { | ||
dispose() { | ||
super.dispose(); | ||
if ( this.sampleRenderTarget !== undefined ) this.sampleRenderTarget.dispose(); | ||
if ( this.holdRenderTarget !== undefined ) this.holdRenderTarget.dispose(); | ||
} | ||
} | ||
@@ -135,0 +144,0 @@ |
@@ -58,4 +58,12 @@ import { | ||
dispose() { | ||
this.material.dispose(); | ||
this.fsQuad.dispose(); | ||
} | ||
} | ||
export { TexturePass }; |
@@ -173,2 +173,18 @@ import { | ||
// | ||
for ( let i = 0; i < this.separableBlurMaterials.length; i ++ ) { | ||
this.separableBlurMaterials[ i ].dispose(); | ||
} | ||
this.compositeMaterial.dispose(); | ||
this.materialCopy.dispose(); | ||
this.basic.dispose(); | ||
// | ||
this.fsQuad.dispose(); | ||
} | ||
@@ -175,0 +191,0 @@ |
@@ -76,4 +76,14 @@ import { defaultShaderStages, NodeFrame, MathNode, GLSLNodeParser, NodeBuilder } from 'three/nodes'; | ||
const type = this.material.type; | ||
const material = this.material; | ||
let type = material.type; | ||
// see https://github.com/mrdoob/three.js/issues/23707 | ||
if ( material.isMeshPhysicalNodeMaterial ) type = 'MeshPhysicalNodeMaterial'; | ||
else if ( material.isMeshStandardNodeMaterial ) type = 'MeshStandardNodeMaterial'; | ||
else if ( material.isMeshBasicNodeMaterial ) type = 'MeshBasicNodeMaterial'; | ||
else if ( material.isPointsNodeMaterial ) type = 'PointsNodeMaterial'; | ||
else if ( material.isLineBasicNodeMaterial ) type = 'LineBasicNodeMaterial'; | ||
// shader lib | ||
@@ -505,3 +515,3 @@ | ||
getVaryings( /* shaderStage */ ) { | ||
getVaryings( shaderStage ) { | ||
@@ -512,6 +522,22 @@ let snippet = ''; | ||
for ( const varying of varyings ) { | ||
if ( shaderStage === 'vertex' ) { | ||
snippet += `varying ${varying.type} ${varying.name}; `; | ||
for ( const varying of varyings ) { | ||
snippet += `${varying.needsInterpolation ? 'varying' : '/*varying*/'} ${varying.type} ${varying.name}; `; | ||
} | ||
} else if ( shaderStage === 'fragment' ) { | ||
for ( const varying of varyings ) { | ||
if ( varying.needsInterpolation ) { | ||
snippet += `varying ${varying.type} ${varying.name}; `; | ||
} | ||
} | ||
} | ||
@@ -698,3 +724,3 @@ | ||
'main() {', | ||
this.flowCode[ shaderStage ] | ||
'\n\t' + this.flowCode[ shaderStage ] | ||
); | ||
@@ -701,0 +727,0 @@ |
@@ -203,3 +203,3 @@ import WebGPUUniformsGroup from '../WebGPUUniformsGroup.js'; | ||
if ( node.isNodeVarying === true ) { | ||
if ( node.isNodeVarying === true && node.needsInterpolation === true ) { | ||
@@ -467,2 +467,3 @@ if ( shaderStage === 'vertex' ) { | ||
const varyings = this.varyings; | ||
const vars = this.vars[ shaderStage ]; | ||
@@ -473,4 +474,12 @@ for ( let index = 0; index < varyings.length; index ++ ) { | ||
snippets.push( `@location( ${index} ) ${ varying.name } : ${ this.getType( varying.type ) }` ); | ||
if ( varying.needsInterpolation ) { | ||
snippets.push( `@location( ${index} ) ${ varying.name } : ${ this.getType( varying.type ) }` ); | ||
} else if ( vars.includes( varying ) === false ) { | ||
vars.push( varying ); | ||
} | ||
} | ||
@@ -481,2 +490,3 @@ | ||
const varyings = this.varyings; | ||
const vars = this.vars[ shaderStage ]; | ||
@@ -487,4 +497,12 @@ for ( let index = 0; index < varyings.length; index ++ ) { | ||
snippets.push( `@location( ${index} ) ${ varying.name } : ${ this.getType( varying.type ) }` ); | ||
if ( varying.needsInterpolation ) { | ||
snippets.push( `@location( ${index} ) ${ varying.name } : ${ this.getType( varying.type ) }` ); | ||
} else if ( vars.includes( varying ) === false ) { | ||
vars.push( varying ); | ||
} | ||
} | ||
@@ -491,0 +509,0 @@ |
import { GPUIndexFormat, GPUTextureFormat, GPUStoreOp } from './constants.js'; | ||
import WebGPUAnimation from './WebGPUAnimation.js'; | ||
import WebGPUObjects from './WebGPUObjects.js'; | ||
@@ -135,2 +136,4 @@ import WebGPUAttributes from './WebGPUAttributes.js'; | ||
this._animation = new WebGPUAnimation(); | ||
this._renderPassDescriptor = null; | ||
@@ -151,2 +154,4 @@ | ||
this._initialized = false; | ||
// some parameters require default values other than "undefined" | ||
@@ -173,2 +178,8 @@ | ||
if ( this._initialized === true ) { | ||
throw new Error( 'WebGPURenderer: Device has already been initialized.' ); | ||
} | ||
const parameters = this._parameters; | ||
@@ -198,3 +209,3 @@ | ||
context.configure( { | ||
device: device, | ||
device, | ||
format: GPUTextureFormat.BGRA8Unorm, // this is the only valid context format right now (r121) | ||
@@ -239,12 +250,17 @@ alphaMode: 'premultiplied' | ||
this._animation.setNodes( this._nodes ); | ||
this._animation.start(); | ||
this._initialized = true; | ||
} | ||
render( scene, camera ) { | ||
async render( scene, camera ) { | ||
// @TODO: move this to animation loop | ||
if ( this._initialized === false ) return await this.init(); | ||
this._nodes.updateFrame(); | ||
// | ||
if ( this._animation.isAnimating === false ) this._nodes.updateFrame(); | ||
if ( scene.matrixWorldAutoUpdate === true ) scene.updateMatrixWorld(); | ||
@@ -284,2 +300,4 @@ | ||
this._textures.initRenderTarget( renderTarget ); | ||
// @TODO: Support RenderTarget with antialiasing. | ||
@@ -363,2 +381,14 @@ | ||
setAnimationLoop( callback ) { | ||
if ( this._initialized === false ) this.init(); | ||
const animation = this._animation; | ||
animation.setAnimationLoop( callback ); | ||
( callback === null ) ? animation.stop() : animation.start(); | ||
} | ||
getContext() { | ||
@@ -581,2 +611,5 @@ | ||
this.setRenderTarget( null ); | ||
this.setAnimationLoop( null ); | ||
} | ||
@@ -588,12 +621,8 @@ | ||
if ( renderTarget !== null ) { | ||
} | ||
this._textures.initRenderTarget( renderTarget ); | ||
async compute( ...computeNodes ) { | ||
} | ||
if ( this._initialized === false ) return await this.init(); | ||
} | ||
compute( ...computeNodes ) { | ||
const device = this._device; | ||
@@ -600,0 +629,0 @@ const computePipelines = this._computePipelines; |
@@ -195,7 +195,2 @@ import { | ||
// gather .userData | ||
mergedGeometry.userData.mergedUserData = mergedGeometry.userData.mergedUserData || []; | ||
mergedGeometry.userData.mergedUserData.push( geometry.userData ); | ||
if ( useGroups ) { | ||
@@ -376,2 +371,24 @@ | ||
/** | ||
* @param {BufferAttribute} | ||
* @return {BufferAttribute} | ||
*/ | ||
export function deepCloneAttribute( attribute ) { | ||
if ( attribute.isInstancedInterleavedBufferAttribute || attribute.isInterleavedBufferAttribute ) { | ||
return deinterleaveAttribute( attribute ); | ||
} | ||
if ( attribute.isInstancedBufferAttribute ) { | ||
return new InstancedBufferAttribute().copy( attribute ); | ||
} | ||
return new BufferAttribute().copy( attribute ); | ||
} | ||
/** | ||
* @param {Array<BufferAttribute>} attributes | ||
@@ -378,0 +395,0 @@ * @return {Array<InterleavedBufferAttribute>} |
import { | ||
BufferAttribute, | ||
BufferGeometry, | ||
Color, | ||
Group, | ||
Matrix4, | ||
Mesh, | ||
BufferAttribute, | ||
BufferGeometry | ||
Vector3 | ||
} from 'three'; | ||
import { mergeGroups } from './BufferGeometryUtils.js'; | ||
import { mergeGroups, deepCloneAttribute } from './BufferGeometryUtils.js'; | ||
const _color = /*@__PURE__*/new Color(); | ||
const _matrix = /*@__PURE__*/new Matrix4(); | ||
function createMeshesFromInstancedMesh( instancedMesh ) { | ||
@@ -121,6 +127,125 @@ | ||
function reduceVertices( object, func, initialValue ) { | ||
let value = initialValue; | ||
const vertex = new Vector3(); | ||
object.updateWorldMatrix( true, true ); | ||
object.traverseVisible( ( child ) => { | ||
const { geometry } = child; | ||
if ( geometry !== undefined ) { | ||
const { position } = geometry.attributes; | ||
if ( position !== undefined ) { | ||
for ( let i = 0, l = position.count; i < l; i ++ ) { | ||
vertex.fromBufferAttribute( position, i ); | ||
if ( child.isSkinnedMesh ) { | ||
child.boneTransform( i, vertex ); | ||
} else { | ||
vertex.applyMatrix4( child.matrixWorld ); | ||
} | ||
value = func( value, vertex ); | ||
} | ||
} | ||
} | ||
} ); | ||
return value; | ||
} | ||
/** | ||
* @param {InstancedMesh} | ||
* @param {function(int, int):int} | ||
*/ | ||
function sortInstancedMesh( mesh, compareFn ) { | ||
// store copy of instanced attributes for lookups | ||
const instanceMatrixRef = deepCloneAttribute( mesh.instanceMatrix ); | ||
const instanceColorRef = mesh.instanceColor ? deepCloneAttribute( mesh.instanceColor ) : null; | ||
const attributeRefs = new Map(); | ||
for ( const name in mesh.geometry.attributes ) { | ||
const attribute = mesh.geometry.attributes[ name ]; | ||
if ( attribute.isInstancedBufferAttribute ) { | ||
attributeRefs.set( attribute, deepCloneAttribute( attribute ) ); | ||
} | ||
} | ||
// compute sort order | ||
const tokens = []; | ||
for ( let i = 0; i < mesh.count; i ++ ) tokens.push( i ); | ||
tokens.sort( compareFn ); | ||
// apply sort order | ||
for ( let i = 0; i < tokens.length; i ++ ) { | ||
const refIndex = tokens[ i ]; | ||
_matrix.fromArray( instanceMatrixRef.array, refIndex * mesh.instanceMatrix.itemSize ); | ||
_matrix.toArray( mesh.instanceMatrix.array, i * mesh.instanceMatrix.itemSize ); | ||
if ( mesh.instanceColor ) { | ||
_color.fromArray( instanceColorRef.array, refIndex * mesh.instanceColor.itemSize ); | ||
_color.toArray( mesh.instanceColor.array, i * mesh.instanceColor.itemSize ); | ||
} | ||
for ( const name in mesh.geometry.attributes ) { | ||
const attribute = mesh.geometry.attributes[ name ]; | ||
if ( attribute.isInstancedBufferAttribute ) { | ||
const attributeRef = attributeRefs.get( attribute ); | ||
attribute.setX( i, attributeRef.getX( refIndex ) ); | ||
if ( attribute.itemSize > 1 ) attribute.setY( i, attributeRef.getY( refIndex ) ); | ||
if ( attribute.itemSize > 2 ) attribute.setZ( i, attributeRef.getZ( refIndex ) ); | ||
if ( attribute.itemSize > 3 ) attribute.setW( i, attributeRef.getW( refIndex ) ); | ||
} | ||
} | ||
} | ||
} | ||
export { | ||
createMeshesFromInstancedMesh, | ||
createMeshesFromMultiMaterialMesh, | ||
createMultiMaterialObject | ||
createMultiMaterialObject, | ||
reduceVertices, | ||
sortInstancedMesh | ||
}; |
{ | ||
"name": "three", | ||
"version": "0.145.0", | ||
"version": "0.146.0", | ||
"description": "JavaScript 3D library", | ||
@@ -68,3 +68,2 @@ "type": "module", | ||
"fflate": "readonly", | ||
"bodymovin": "readonly", | ||
"OIMO": "readonly", | ||
@@ -146,11 +145,11 @@ "Stats": "readonly", | ||
"devDependencies": { | ||
"@babel/core": "^7.18.9", | ||
"@babel/eslint-parser": "^7.18.9", | ||
"@babel/core": "^7.19.3", | ||
"@babel/eslint-parser": "^7.19.1", | ||
"@babel/plugin-proposal-class-properties": "^7.18.6", | ||
"@babel/preset-env": "^7.18.9", | ||
"@babel/preset-env": "^7.19.3", | ||
"@rollup/plugin-babel": "^5.3.1", | ||
"@rollup/plugin-node-resolve": "^13.3.0", | ||
"@rollup/plugin-node-resolve": "^14.1.0", | ||
"chalk": "^5.0.1", | ||
"concurrently": "^7.3.0", | ||
"eslint": "^8.20.0", | ||
"concurrently": "^7.4.0", | ||
"eslint": "^8.24.0", | ||
"eslint-config-mdcs": "^5.0.0", | ||
@@ -160,6 +159,6 @@ "eslint-plugin-compat": "^4.0.2", | ||
"eslint-plugin-import": "^2.26.0", | ||
"rollup": "^2.77.2", | ||
"rollup": "^2.79.1", | ||
"rollup-plugin-filesize": "^9.1.2", | ||
"rollup-plugin-terser": "^7.0.2", | ||
"rollup-plugin-visualizer": "^5.7.1", | ||
"rollup-plugin-visualizer": "^5.8.2", | ||
"servez": "^1.14.1" | ||
@@ -166,0 +165,0 @@ }, |
let _context; | ||
const AudioContext = { | ||
class AudioContext { | ||
getContext: function () { | ||
static getContext() { | ||
@@ -15,5 +15,5 @@ if ( _context === undefined ) { | ||
}, | ||
} | ||
setContext: function ( value ) { | ||
static setContext( value ) { | ||
@@ -24,4 +24,4 @@ _context = value; | ||
}; | ||
} | ||
export { AudioContext }; |
@@ -1,2 +0,2 @@ | ||
export const REVISION = '145'; | ||
export const REVISION = '146'; | ||
export const MOUSE = { LEFT: 0, MIDDLE: 1, RIGHT: 2, ROTATE: 0, DOLLY: 1, PAN: 2 }; | ||
@@ -3,0 +3,0 @@ export const TOUCH = { ROTATE: 0, PAN: 1, DOLLY_PAN: 2, DOLLY_ROTATE: 3 }; |
/** | ||
* Port from https://github.com/mapbox/earcut (v2.2.2) | ||
* Port from https://github.com/mapbox/earcut (v2.2.4) | ||
*/ | ||
@@ -39,7 +39,7 @@ | ||
invSize = Math.max( maxX - minX, maxY - minY ); | ||
invSize = invSize !== 0 ? 1 / invSize : 0; | ||
invSize = invSize !== 0 ? 32767 / invSize : 0; | ||
} | ||
earcutLinked( outerNode, triangles, dim, minX, minY, invSize ); | ||
earcutLinked( outerNode, triangles, dim, minX, minY, invSize, 0 ); | ||
@@ -129,5 +129,5 @@ return triangles; | ||
// cut off the triangle | ||
triangles.push( prev.i / dim ); | ||
triangles.push( ear.i / dim ); | ||
triangles.push( next.i / dim ); | ||
triangles.push( prev.i / dim | 0 ); | ||
triangles.push( ear.i / dim | 0 ); | ||
triangles.push( next.i / dim | 0 ); | ||
@@ -187,7 +187,15 @@ removeNode( ear ); | ||
// now make sure we don't have other points inside the potential ear | ||
let p = ear.next.next; | ||
const ax = a.x, bx = b.x, cx = c.x, ay = a.y, by = b.y, cy = c.y; | ||
while ( p !== ear.prev ) { | ||
// triangle bbox; min & max are calculated like this for speed | ||
const x0 = ax < bx ? ( ax < cx ? ax : cx ) : ( bx < cx ? bx : cx ), | ||
y0 = ay < by ? ( ay < cy ? ay : cy ) : ( by < cy ? by : cy ), | ||
x1 = ax > bx ? ( ax > cx ? ax : cx ) : ( bx > cx ? bx : cx ), | ||
y1 = ay > by ? ( ay > cy ? ay : cy ) : ( by > cy ? by : cy ); | ||
if ( pointInTriangle( a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y ) && | ||
let p = c.next; | ||
while ( p !== a ) { | ||
if ( p.x >= x0 && p.x <= x1 && p.y >= y0 && p.y <= y1 && | ||
pointInTriangle( ax, ay, bx, by, cx, cy, p.x, p.y ) && | ||
area( p.prev, p, p.next ) >= 0 ) return false; | ||
@@ -210,11 +218,13 @@ p = p.next; | ||
const ax = a.x, bx = b.x, cx = c.x, ay = a.y, by = b.y, cy = c.y; | ||
// triangle bbox; min & max are calculated like this for speed | ||
const minTX = a.x < b.x ? ( a.x < c.x ? a.x : c.x ) : ( b.x < c.x ? b.x : c.x ), | ||
minTY = a.y < b.y ? ( a.y < c.y ? a.y : c.y ) : ( b.y < c.y ? b.y : c.y ), | ||
maxTX = a.x > b.x ? ( a.x > c.x ? a.x : c.x ) : ( b.x > c.x ? b.x : c.x ), | ||
maxTY = a.y > b.y ? ( a.y > c.y ? a.y : c.y ) : ( b.y > c.y ? b.y : c.y ); | ||
const x0 = ax < bx ? ( ax < cx ? ax : cx ) : ( bx < cx ? bx : cx ), | ||
y0 = ay < by ? ( ay < cy ? ay : cy ) : ( by < cy ? by : cy ), | ||
x1 = ax > bx ? ( ax > cx ? ax : cx ) : ( bx > cx ? bx : cx ), | ||
y1 = ay > by ? ( ay > cy ? ay : cy ) : ( by > cy ? by : cy ); | ||
// z-order range for the current triangle bbox; | ||
const minZ = zOrder( minTX, minTY, minX, minY, invSize ), | ||
maxZ = zOrder( maxTX, maxTY, minX, minY, invSize ); | ||
const minZ = zOrder( x0, y0, minX, minY, invSize ), | ||
maxZ = zOrder( x1, y1, minX, minY, invSize ); | ||
@@ -227,10 +237,8 @@ let p = ear.prevZ, | ||
if ( p !== ear.prev && p !== ear.next && | ||
pointInTriangle( a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y ) && | ||
area( p.prev, p, p.next ) >= 0 ) return false; | ||
if ( p.x >= x0 && p.x <= x1 && p.y >= y0 && p.y <= y1 && p !== a && p !== c && | ||
pointInTriangle( ax, ay, bx, by, cx, cy, p.x, p.y ) && area( p.prev, p, p.next ) >= 0 ) return false; | ||
p = p.prevZ; | ||
if ( n !== ear.prev && n !== ear.next && | ||
pointInTriangle( a.x, a.y, b.x, b.y, c.x, c.y, n.x, n.y ) && | ||
area( n.prev, n, n.next ) >= 0 ) return false; | ||
if ( n.x >= x0 && n.x <= x1 && n.y >= y0 && n.y <= y1 && n !== a && n !== c && | ||
pointInTriangle( ax, ay, bx, by, cx, cy, n.x, n.y ) && area( n.prev, n, n.next ) >= 0 ) return false; | ||
n = n.nextZ; | ||
@@ -243,5 +251,4 @@ | ||
if ( p !== ear.prev && p !== ear.next && | ||
pointInTriangle( a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y ) && | ||
area( p.prev, p, p.next ) >= 0 ) return false; | ||
if ( p.x >= x0 && p.x <= x1 && p.y >= y0 && p.y <= y1 && p !== a && p !== c && | ||
pointInTriangle( ax, ay, bx, by, cx, cy, p.x, p.y ) && area( p.prev, p, p.next ) >= 0 ) return false; | ||
p = p.prevZ; | ||
@@ -254,5 +261,4 @@ | ||
if ( n !== ear.prev && n !== ear.next && | ||
pointInTriangle( a.x, a.y, b.x, b.y, c.x, c.y, n.x, n.y ) && | ||
area( n.prev, n, n.next ) >= 0 ) return false; | ||
if ( n.x >= x0 && n.x <= x1 && n.y >= y0 && n.y <= y1 && n !== a && n !== c && | ||
pointInTriangle( ax, ay, bx, by, cx, cy, n.x, n.y ) && area( n.prev, n, n.next ) >= 0 ) return false; | ||
n = n.nextZ; | ||
@@ -277,5 +283,5 @@ | ||
triangles.push( a.i / dim ); | ||
triangles.push( p.i / dim ); | ||
triangles.push( b.i / dim ); | ||
triangles.push( a.i / dim | 0 ); | ||
triangles.push( p.i / dim | 0 ); | ||
triangles.push( b.i / dim | 0 ); | ||
@@ -318,4 +324,4 @@ // remove two nodes involved | ||
// run earcut on each half | ||
earcutLinked( a, triangles, dim, minX, minY, invSize ); | ||
earcutLinked( c, triangles, dim, minX, minY, invSize ); | ||
earcutLinked( a, triangles, dim, minX, minY, invSize, 0 ); | ||
earcutLinked( c, triangles, dim, minX, minY, invSize, 0 ); | ||
return; | ||
@@ -356,4 +362,3 @@ | ||
eliminateHole( queue[ i ], outerNode ); | ||
outerNode = filterPoints( outerNode, outerNode.next ); | ||
outerNode = eliminateHole( queue[ i ], outerNode ); | ||
@@ -375,13 +380,15 @@ } | ||
outerNode = findHoleBridge( hole, outerNode ); | ||
if ( outerNode ) { | ||
const bridge = findHoleBridge( hole, outerNode ); | ||
if ( ! bridge ) { | ||
const b = splitPolygon( outerNode, hole ); | ||
return outerNode; | ||
// filter collinear points around the cuts | ||
filterPoints( outerNode, outerNode.next ); | ||
filterPoints( b, b.next ); | ||
} | ||
const bridgeReverse = splitPolygon( bridge, hole ); | ||
// filter collinear points around the cuts | ||
filterPoints( bridgeReverse, bridgeReverse.next ); | ||
return filterPoints( bridge, bridge.next ); | ||
} | ||
@@ -392,7 +399,8 @@ | ||
let p = outerNode; | ||
const hx = hole.x; | ||
const hy = hole.y; | ||
let qx = - Infinity, m; | ||
let p = outerNode, | ||
qx = - Infinity, | ||
m; | ||
const hx = hole.x, hy = hole.y; | ||
// find a segment intersected by a ray from the hole's leftmost point to the left; | ||
@@ -408,10 +416,4 @@ // segment's endpoint with lesser x will be potential connection point | ||
qx = x; | ||
if ( x === hx ) { | ||
if ( hy === p.y ) return p; | ||
if ( hy === p.next.y ) return p.next; | ||
} | ||
m = p.x < p.next.x ? p : p.next; | ||
if ( x === hx ) return m; // hole touches outer segment; pick leftmost endpoint | ||
@@ -428,4 +430,2 @@ } | ||
if ( hx === qx ) return m; // hole touches outer segment; pick leftmost endpoint | ||
// look for points inside the triangle of hole point, segment intersection and endpoint; | ||
@@ -479,3 +479,3 @@ // if there are no points found, we have a valid connection; | ||
if ( p.z === null ) p.z = zOrder( p.x, p.y, minX, minY, invSize ); | ||
if ( p.z === 0 ) p.z = zOrder( p.x, p.y, minX, minY, invSize ); | ||
p.prevZ = p.prev; | ||
@@ -564,4 +564,4 @@ p.nextZ = p.next; | ||
// coords are transformed into non-negative 15-bit integer range | ||
x = 32767 * ( x - minX ) * invSize; | ||
y = 32767 * ( y - minY ) * invSize; | ||
x = ( x - minX ) * invSize | 0; | ||
y = ( y - minY ) * invSize | 0; | ||
@@ -601,5 +601,5 @@ x = ( x | ( x << 8 ) ) & 0x00FF00FF; | ||
return ( cx - px ) * ( ay - py ) - ( ax - px ) * ( cy - py ) >= 0 && | ||
( ax - px ) * ( by - py ) - ( bx - px ) * ( ay - py ) >= 0 && | ||
( bx - px ) * ( cy - py ) - ( cx - px ) * ( by - py ) >= 0; | ||
return ( cx - px ) * ( ay - py ) >= ( ax - px ) * ( cy - py ) && | ||
( ax - px ) * ( by - py ) >= ( bx - px ) * ( ay - py ) && | ||
( bx - px ) * ( cy - py ) >= ( cx - px ) * ( by - py ); | ||
@@ -611,6 +611,6 @@ } | ||
return a.next.i !== b.i && a.prev.i !== b.i && ! intersectsPolygon( a, b ) && // doesn't intersect other edges | ||
( locallyInside( a, b ) && locallyInside( b, a ) && middleInside( a, b ) && // locally visible | ||
( area( a.prev, a, b.prev ) || area( a, b.prev, b ) ) || // does not create opposite-facing sectors | ||
equals( a, b ) && area( a.prev, a, a.next ) > 0 && area( b.prev, b, b.next ) > 0 ); // special zero-length case | ||
return a.next.i !== b.i && a.prev.i !== b.i && ! intersectsPolygon( a, b ) && // dones't intersect other edges | ||
( locallyInside( a, b ) && locallyInside( b, a ) && middleInside( a, b ) && // locally visible | ||
( area( a.prev, a, b.prev ) || area( a, b.prev, b ) ) || // does not create opposite-facing sectors | ||
equals( a, b ) && area( a.prev, a, a.next ) > 0 && area( b.prev, b, b.next ) > 0 ); // special zero-length case | ||
@@ -672,3 +672,3 @@ } | ||
if ( p.i !== a.i && p.next.i !== a.i && p.i !== b.i && p.next.i !== b.i && | ||
intersects( p, p.next, a, b ) ) return true; | ||
intersects( p, p.next, a, b ) ) return true; | ||
p = p.next; | ||
@@ -701,3 +701,3 @@ | ||
if ( ( ( p.y > py ) !== ( p.next.y > py ) ) && p.next.y !== p.y && | ||
( px < ( p.next.x - p.x ) * ( py - p.y ) / ( p.next.y - p.y ) + p.x ) ) | ||
( px < ( p.next.x - p.x ) * ( py - p.y ) / ( p.next.y - p.y ) + p.x ) ) | ||
inside = ! inside; | ||
@@ -784,3 +784,3 @@ p = p.next; | ||
// z-order curve value | ||
this.z = null; | ||
this.z = 0; | ||
@@ -787,0 +787,0 @@ // previous and next nodes in z-order |
@@ -783,2 +783,4 @@ import { | ||
if ( data.backgroundBlurriness !== undefined ) object.backgroundBlurriness = data.backgroundBlurriness; | ||
break; | ||
@@ -785,0 +787,0 @@ |
@@ -303,3 +303,3 @@ import { EventDispatcher } from '../core/EventDispatcher.js'; | ||
if ( this.thicknessMap && this.thicknessMap.isTexture ) data.thicknessMap = this.thicknessMap.toJSON( meta ).uuid; | ||
if ( this.attenuationDistance !== undefined ) data.attenuationDistance = this.attenuationDistance; | ||
if ( this.attenuationDistance !== undefined && this.attenuationDistance !== Infinity ) data.attenuationDistance = this.attenuationDistance; | ||
if ( this.attenuationColor !== undefined ) data.attenuationColor = this.attenuationColor.getHex(); | ||
@@ -306,0 +306,0 @@ |
@@ -359,9 +359,6 @@ import { Vector3 } from './Vector3.js'; | ||
// These lines also handle the case where tmin or tmax is NaN | ||
// (result of 0 * Infinity). x !== x returns true if x is NaN | ||
if ( tymin > tmin || isNaN( tmin ) ) tmin = tymin; | ||
if ( tymin > tmin || tmin !== tmin ) tmin = tymin; | ||
if ( tymax < tmax || isNaN( tmax ) ) tmax = tymax; | ||
if ( tymax < tmax || tmax !== tmax ) tmax = tymax; | ||
if ( invdirz >= 0 ) { | ||
@@ -368,0 +365,0 @@ |
@@ -6,4 +6,3 @@ import { Box3 } from './Box3.js'; | ||
const _v1 = /*@__PURE__*/ new Vector3(); | ||
const _toFarthestPoint = /*@__PURE__*/ new Vector3(); | ||
const _toPoint = /*@__PURE__*/ new Vector3(); | ||
const _v2 = /*@__PURE__*/ new Vector3(); | ||
@@ -168,2 +167,3 @@ class Sphere { | ||
this.center.copy( point ); | ||
this.radius = 0; | ||
@@ -175,20 +175,18 @@ | ||
// from https://github.com/juj/MathGeoLib/blob/2940b99b99cfe575dd45103ef20f4019dee15b54/src/Geometry/Sphere.cpp#L649-L671 | ||
_v1.subVectors( point, this.center ); | ||
_toPoint.subVectors( point, this.center ); | ||
const lengthSq = _v1.lengthSq(); | ||
const lengthSq = _toPoint.lengthSq(); | ||
if ( lengthSq > ( this.radius * this.radius ) ) { | ||
// calculate the minimal sphere | ||
const length = Math.sqrt( lengthSq ); | ||
const missingRadiusHalf = ( length - this.radius ) * 0.5; | ||
// Nudge this sphere towards the target point. Add half the missing distance to radius, | ||
// and the other half to position. This gives a tighter enclosure, instead of if | ||
// the whole missing distance were just added to radius. | ||
const delta = ( length - this.radius ) * 0.5; | ||
this.center.add( _toPoint.multiplyScalar( missingRadiusHalf / length ) ); | ||
this.radius += missingRadiusHalf; | ||
this.center.addScaledVector( _v1, delta / length ); | ||
this.radius += delta; | ||
} | ||
@@ -202,3 +200,2 @@ | ||
// handle empty sphere cases | ||
if ( sphere.isEmpty() ) { | ||
@@ -208,4 +205,6 @@ | ||
} else if ( this.isEmpty() ) { | ||
} | ||
if ( this.isEmpty() ) { | ||
this.copy( sphere ); | ||
@@ -217,22 +216,16 @@ | ||
// from https://github.com/juj/MathGeoLib/blob/2940b99b99cfe575dd45103ef20f4019dee15b54/src/Geometry/Sphere.cpp#L759-L769 | ||
if ( this.center.equals( sphere.center ) === true ) { | ||
// To enclose another sphere into this sphere, we only need to enclose two points: | ||
// 1) Enclose the farthest point on the other sphere into this sphere. | ||
// 2) Enclose the opposite point of the farthest point into this sphere. | ||
this.radius = Math.max( this.radius, sphere.radius ); | ||
if ( this.center.equals( sphere.center ) === true ) { | ||
} else { | ||
_toFarthestPoint.set( 0, 0, 1 ).multiplyScalar( sphere.radius ); | ||
_v2.subVectors( sphere.center, this.center ).setLength( sphere.radius ); | ||
this.expandByPoint( _v1.copy( sphere.center ).add( _v2 ) ); | ||
} else { | ||
this.expandByPoint( _v1.copy( sphere.center ).sub( _v2 ) ); | ||
_toFarthestPoint.subVectors( sphere.center, this.center ).normalize().multiplyScalar( sphere.radius ); | ||
} | ||
this.expandByPoint( _v1.copy( sphere.center ).add( _toFarthestPoint ) ); | ||
this.expandByPoint( _v1.copy( sphere.center ).sub( _toFarthestPoint ) ); | ||
return this; | ||
@@ -239,0 +232,0 @@ |
@@ -10,2 +10,3 @@ import { InstancedBufferAttribute } from '../core/InstancedBufferAttribute.js'; | ||
const _identity = /*@__PURE__*/ new Matrix4(); | ||
const _mesh = /*@__PURE__*/ new Mesh(); | ||
@@ -28,2 +29,8 @@ | ||
for ( let i = 0; i < count; i ++ ) { | ||
this.setMatrixAt( i, _identity ); | ||
} | ||
} | ||
@@ -30,0 +37,0 @@ |
@@ -109,2 +109,3 @@ import alphamap_fragment from './ShaderChunk/alphamap_fragment.glsl.js'; | ||
import * as background from './ShaderLib/background.glsl.js'; | ||
import * as backgroundCube from './ShaderLib/backgroundCube.glsl.js'; | ||
import * as cube from './ShaderLib/cube.glsl.js'; | ||
@@ -236,2 +237,4 @@ import * as depth from './ShaderLib/depth.glsl.js'; | ||
background_frag: background.fragment, | ||
backgroundCube_vert: backgroundCube.vertex, | ||
backgroundCube_frag: backgroundCube.fragment, | ||
cube_vert: cube.vertex, | ||
@@ -238,0 +241,0 @@ cube_frag: cube.fragment, |
@@ -41,6 +41,2 @@ export default /* glsl */` | ||
#elif defined( ENVMAP_TYPE_CUBE_UV ) | ||
vec4 envColor = textureCubeUV( envMap, reflectVec, 0.0 ); | ||
#else | ||
@@ -47,0 +43,0 @@ |
@@ -28,2 +28,10 @@ export default /* glsl */` | ||
vec2 packDepthToRG( in highp float v ) { | ||
return packDepthToRGBA( v ).yx; | ||
} | ||
float unpackRGToDepth( const in highp vec2 v ) { | ||
return unpackRGBAToDepth( vec4( v.xy, 0.0, 0.0 ) ); | ||
} | ||
vec4 pack2HalfToRGBA( vec2 v ) { | ||
@@ -30,0 +38,0 @@ vec4 r = vec4( v.x, fract( v.x * 255.0 ), v.y, fract( v.y * 255.0 ) ); |
@@ -228,10 +228,22 @@ import { ShaderChunk } from './ShaderChunk.js'; | ||
backgroundCube: { | ||
uniforms: { | ||
envMap: { value: null }, | ||
flipEnvMap: { value: - 1 }, | ||
backgroundBlurriness: { value: 0 } | ||
}, | ||
vertexShader: ShaderChunk.backgroundCube_vert, | ||
fragmentShader: ShaderChunk.backgroundCube_frag | ||
}, | ||
cube: { | ||
uniforms: /*@__PURE__*/ mergeUniforms( [ | ||
UniformsLib.envmap, | ||
{ | ||
opacity: { value: 1.0 } | ||
} | ||
] ), | ||
uniforms: { | ||
tCube: { value: null }, | ||
tFlip: { value: - 1 }, | ||
opacity: { value: 1.0 } | ||
}, | ||
@@ -238,0 +250,0 @@ vertexShader: ShaderChunk.cube_vert, |
@@ -19,3 +19,4 @@ export const vertex = /* glsl */` | ||
export const fragment = /* glsl */` | ||
#include <envmap_common_pars_fragment> | ||
uniform samplerCube tCube; | ||
uniform float tFlip; | ||
uniform float opacity; | ||
@@ -25,10 +26,7 @@ | ||
#include <cube_uv_reflection_fragment> | ||
void main() { | ||
vec3 vReflect = vWorldDirection; | ||
#include <envmap_fragment> | ||
vec4 texColor = textureCube( tCube, vec3( tFlip * vWorldDirection.x, vWorldDirection.yz ) ); | ||
gl_FragColor = envColor; | ||
gl_FragColor = texColor; | ||
gl_FragColor.a *= opacity; | ||
@@ -35,0 +33,0 @@ |
@@ -37,3 +37,3 @@ import { Color } from '../../math/Color.js'; | ||
ior: { value: 1.5 }, // physical | ||
refractionRatio: { value: 0.98 } // basic, lambert, phong | ||
refractionRatio: { value: 0.98 }, // basic, lambert, phong | ||
@@ -40,0 +40,0 @@ }, |
@@ -10,3 +10,3 @@ import { BackSide, FrontSide, CubeUVReflectionMapping } from '../../constants.js'; | ||
function WebGLBackground( renderer, cubemaps, state, objects, alpha, premultipliedAlpha ) { | ||
function WebGLBackground( renderer, cubemaps, cubeuvmaps, state, objects, alpha, premultipliedAlpha ) { | ||
@@ -30,3 +30,4 @@ const clearColor = new Color( 0x000000 ); | ||
background = cubemaps.get( background ); | ||
const usePMREM = scene.backgroundBlurriness > 0; // use PMREM if the user wants to blur the background | ||
background = ( usePMREM ? cubeuvmaps : cubemaps ).get( background ); | ||
@@ -72,5 +73,5 @@ } | ||
name: 'BackgroundCubeMaterial', | ||
uniforms: cloneUniforms( ShaderLib.cube.uniforms ), | ||
vertexShader: ShaderLib.cube.vertexShader, | ||
fragmentShader: ShaderLib.cube.fragmentShader, | ||
uniforms: cloneUniforms( ShaderLib.backgroundCube.uniforms ), | ||
vertexShader: ShaderLib.backgroundCube.vertexShader, | ||
fragmentShader: ShaderLib.backgroundCube.fragmentShader, | ||
side: BackSide, | ||
@@ -109,2 +110,3 @@ depthTest: false, | ||
boxMesh.material.uniforms.flipEnvMap.value = ( background.isCubeTexture && background.isRenderTargetTexture === false ) ? - 1 : 1; | ||
boxMesh.material.uniforms.backgroundBlurriness.value = scene.backgroundBlurriness; | ||
@@ -111,0 +113,0 @@ if ( currentBackground !== background || |
@@ -955,2 +955,16 @@ import { NotEqualDepth, GreaterDepth, GreaterEqualDepth, EqualDepth, LessEqualDepth, LessDepth, AlwaysDepth, NeverDepth, CullFaceFront, CullFaceBack, CullFaceNone, DoubleSide, BackSide, CustomBlending, MultiplyBlending, SubtractiveBlending, AdditiveBlending, NoBlending, NormalBlending, AddEquation, SubtractEquation, ReverseSubtractEquation, MinEquation, MaxEquation, ZeroFactor, OneFactor, SrcColorFactor, SrcAlphaFactor, SrcAlphaSaturateFactor, DstColorFactor, DstAlphaFactor, OneMinusSrcColorFactor, OneMinusSrcAlphaFactor, OneMinusDstColorFactor, OneMinusDstAlphaFactor } from '../../constants.js'; | ||
function compressedTexImage3D() { | ||
try { | ||
gl.compressedTexImage3D.apply( gl, arguments ); | ||
} catch ( error ) { | ||
console.error( 'THREE.WebGLState:', error ); | ||
} | ||
} | ||
function texSubImage2D() { | ||
@@ -998,2 +1012,16 @@ | ||
function compressedTexSubImage3D() { | ||
try { | ||
gl.compressedTexSubImage3D.apply( gl, arguments ); | ||
} catch ( error ) { | ||
console.error( 'THREE.WebGLState:', error ); | ||
} | ||
} | ||
function texStorage2D() { | ||
@@ -1244,2 +1272,3 @@ | ||
compressedTexImage2D: compressedTexImage2D, | ||
compressedTexImage3D: compressedTexImage3D, | ||
texImage2D: texImage2D, | ||
@@ -1256,2 +1285,3 @@ texImage3D: texImage3D, | ||
compressedTexSubImage2D: compressedTexSubImage2D, | ||
compressedTexSubImage3D: compressedTexSubImage3D, | ||
@@ -1258,0 +1288,0 @@ scissor: scissor, |
@@ -14,3 +14,3 @@ import { LinearFilter, LinearMipmapLinearFilter, LinearMipmapNearestFilter, NearestFilter, NearestMipmapLinearFilter, NearestMipmapNearestFilter, RGBAFormat, DepthFormat, DepthStencilFormat, UnsignedShortType, UnsignedIntType, UnsignedInt248Type, FloatType, HalfFloatType, MirroredRepeatWrapping, ClampToEdgeWrapping, RepeatWrapping, sRGBEncoding, LinearEncoding, UnsignedByteType, _SRGBAFormat } from '../../constants.js'; | ||
const multisampledRTTExt = extensions.has( 'WEBGL_multisampled_render_to_texture' ) ? extensions.get( 'WEBGL_multisampled_render_to_texture' ) : null; | ||
const supportsInvalidateFramebuffer = /OculusBrowser/g.test( navigator.userAgent ); | ||
const supportsInvalidateFramebuffer = /OculusBrowser/g.test( typeof navigator === 'undefined' ? '' : navigator.userAgent ); | ||
@@ -419,2 +419,3 @@ const _videoTextures = new WeakMap(); | ||
array.push( texture.wrapT ); | ||
array.push( texture.wrapR || 0 ); | ||
array.push( texture.magFilter ); | ||
@@ -676,3 +677,3 @@ array.push( texture.minFilter ); | ||
if ( texture.isDataArrayTexture ) textureType = _gl.TEXTURE_2D_ARRAY; | ||
if ( texture.isDataArrayTexture || texture.isCompressedArrayTexture ) textureType = _gl.TEXTURE_2D_ARRAY; | ||
if ( texture.isData3DTexture ) textureType = _gl.TEXTURE_3D; | ||
@@ -859,23 +860,31 @@ | ||
if ( useTexStorage && allocateMemory ) { | ||
if ( texture.isCompressedArrayTexture ) { | ||
state.texStorage2D( _gl.TEXTURE_2D, levels, glInternalFormat, mipmaps[ 0 ].width, mipmaps[ 0 ].height ); | ||
if ( useTexStorage && allocateMemory ) { | ||
} | ||
state.texStorage3D( _gl.TEXTURE_2D_ARRAY, levels, glInternalFormat, mipmaps[ 0 ].width, mipmaps[ 0 ].height, image.depth ); | ||
for ( let i = 0, il = mipmaps.length; i < il; i ++ ) { | ||
} | ||
mipmap = mipmaps[ i ]; | ||
for ( let i = 0, il = mipmaps.length; i < il; i ++ ) { | ||
if ( texture.format !== RGBAFormat ) { | ||
mipmap = mipmaps[ i ]; | ||
if ( glFormat !== null ) { | ||
if ( texture.format !== RGBAFormat ) { | ||
if ( useTexStorage ) { | ||
if ( glFormat !== null ) { | ||
state.compressedTexSubImage2D( _gl.TEXTURE_2D, i, 0, 0, mipmap.width, mipmap.height, glFormat, mipmap.data ); | ||
if ( useTexStorage ) { | ||
state.compressedTexSubImage3D( _gl.TEXTURE_2D_ARRAY, i, 0, 0, 0, mipmap.width, mipmap.height, image.depth, glFormat, mipmap.data, 0, 0 ); | ||
} else { | ||
state.compressedTexImage3D( _gl.TEXTURE_2D_ARRAY, i, glInternalFormat, mipmap.width, mipmap.height, image.depth, 0, mipmap.data, 0, 0 ); | ||
} | ||
} else { | ||
state.compressedTexImage2D( _gl.TEXTURE_2D, i, glInternalFormat, mipmap.width, mipmap.height, 0, mipmap.data ); | ||
console.warn( 'THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .uploadTexture()' ); | ||
@@ -886,16 +895,60 @@ } | ||
console.warn( 'THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .uploadTexture()' ); | ||
if ( useTexStorage ) { | ||
state.texSubImage3D( _gl.TEXTURE_2D_ARRAY, i, 0, 0, 0, mipmap.width, mipmap.height, image.depth, glFormat, glType, mipmap.data ); | ||
} else { | ||
state.texImage3D( _gl.TEXTURE_2D_ARRAY, i, glInternalFormat, mipmap.width, mipmap.height, image.depth, 0, glFormat, glType, mipmap.data ); | ||
} | ||
} | ||
} else { | ||
} | ||
if ( useTexStorage ) { | ||
} else { | ||
state.texSubImage2D( _gl.TEXTURE_2D, i, 0, 0, mipmap.width, mipmap.height, glFormat, glType, mipmap.data ); | ||
if ( useTexStorage && allocateMemory ) { | ||
state.texStorage2D( _gl.TEXTURE_2D, levels, glInternalFormat, mipmaps[ 0 ].width, mipmaps[ 0 ].height ); | ||
} | ||
for ( let i = 0, il = mipmaps.length; i < il; i ++ ) { | ||
mipmap = mipmaps[ i ]; | ||
if ( texture.format !== RGBAFormat ) { | ||
if ( glFormat !== null ) { | ||
if ( useTexStorage ) { | ||
state.compressedTexSubImage2D( _gl.TEXTURE_2D, i, 0, 0, mipmap.width, mipmap.height, glFormat, mipmap.data ); | ||
} else { | ||
state.compressedTexImage2D( _gl.TEXTURE_2D, i, glInternalFormat, mipmap.width, mipmap.height, 0, mipmap.data ); | ||
} | ||
} else { | ||
console.warn( 'THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .uploadTexture()' ); | ||
} | ||
} else { | ||
state.texImage2D( _gl.TEXTURE_2D, i, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data ); | ||
if ( useTexStorage ) { | ||
state.texSubImage2D( _gl.TEXTURE_2D, i, 0, 0, mipmap.width, mipmap.height, glFormat, glType, mipmap.data ); | ||
} else { | ||
state.texImage2D( _gl.TEXTURE_2D, i, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data ); | ||
} | ||
} | ||
@@ -1277,3 +1330,3 @@ | ||
} else { | ||
} else if ( textureTarget === _gl.TEXTURE_2D || ( textureTarget >= _gl.TEXTURE_CUBE_MAP_POSITIVE_X && textureTarget <= _gl.TEXTURE_CUBE_MAP_NEGATIVE_Z ) ) { // see #24753 | ||
@@ -1280,0 +1333,0 @@ _gl.framebufferTexture2D( _gl.FRAMEBUFFER, attachment, textureTarget, properties.get( texture ).__webglTexture, 0 ); |
@@ -365,3 +365,3 @@ /** | ||
// Single integer / boolean vector (from flat array) | ||
// Single integer / boolean vector (from flat array or THREE.VectorN) | ||
@@ -372,8 +372,23 @@ function setValueV2i( gl, v ) { | ||
if ( arraysEqual( cache, v ) ) return; | ||
if ( v.x !== undefined ) { | ||
gl.uniform2iv( this.addr, v ); | ||
if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y ) { | ||
copyArray( cache, v ); | ||
gl.uniform2i( this.addr, v.x, v.y ); | ||
cache[ 0 ] = v.x; | ||
cache[ 1 ] = v.y; | ||
} | ||
} else { | ||
if ( arraysEqual( cache, v ) ) return; | ||
gl.uniform2iv( this.addr, v ); | ||
copyArray( cache, v ); | ||
} | ||
} | ||
@@ -385,8 +400,24 @@ | ||
if ( arraysEqual( cache, v ) ) return; | ||
if ( v.x !== undefined ) { | ||
gl.uniform3iv( this.addr, v ); | ||
if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y || cache[ 2 ] !== v.z ) { | ||
copyArray( cache, v ); | ||
gl.uniform3i( this.addr, v.x, v.y, v.z ); | ||
cache[ 0 ] = v.x; | ||
cache[ 1 ] = v.y; | ||
cache[ 2 ] = v.z; | ||
} | ||
} else { | ||
if ( arraysEqual( cache, v ) ) return; | ||
gl.uniform3iv( this.addr, v ); | ||
copyArray( cache, v ); | ||
} | ||
} | ||
@@ -398,8 +429,25 @@ | ||
if ( arraysEqual( cache, v ) ) return; | ||
if ( v.x !== undefined ) { | ||
gl.uniform4iv( this.addr, v ); | ||
if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y || cache[ 2 ] !== v.z || cache[ 3 ] !== v.w ) { | ||
copyArray( cache, v ); | ||
gl.uniform4i( this.addr, v.x, v.y, v.z, v.w ); | ||
cache[ 0 ] = v.x; | ||
cache[ 1 ] = v.y; | ||
cache[ 2 ] = v.z; | ||
cache[ 3 ] = v.w; | ||
} | ||
} else { | ||
if ( arraysEqual( cache, v ) ) return; | ||
gl.uniform4iv( this.addr, v ); | ||
copyArray( cache, v ); | ||
} | ||
} | ||
@@ -421,3 +469,3 @@ | ||
// Single unsigned integer vector (from flat array) | ||
// Single unsigned integer vector (from flat array or THREE.VectorN) | ||
@@ -428,8 +476,23 @@ function setValueV2ui( gl, v ) { | ||
if ( arraysEqual( cache, v ) ) return; | ||
if ( v.x !== undefined ) { | ||
gl.uniform2uiv( this.addr, v ); | ||
if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y ) { | ||
copyArray( cache, v ); | ||
gl.uniform2ui( this.addr, v.x, v.y ); | ||
cache[ 0 ] = v.x; | ||
cache[ 1 ] = v.y; | ||
} | ||
} else { | ||
if ( arraysEqual( cache, v ) ) return; | ||
gl.uniform2uiv( this.addr, v ); | ||
copyArray( cache, v ); | ||
} | ||
} | ||
@@ -441,8 +504,24 @@ | ||
if ( arraysEqual( cache, v ) ) return; | ||
if ( v.x !== undefined ) { | ||
gl.uniform3uiv( this.addr, v ); | ||
if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y || cache[ 2 ] !== v.z ) { | ||
copyArray( cache, v ); | ||
gl.uniform3ui( this.addr, v.x, v.y, v.z ); | ||
cache[ 0 ] = v.x; | ||
cache[ 1 ] = v.y; | ||
cache[ 2 ] = v.z; | ||
} | ||
} else { | ||
if ( arraysEqual( cache, v ) ) return; | ||
gl.uniform3uiv( this.addr, v ); | ||
copyArray( cache, v ); | ||
} | ||
} | ||
@@ -454,8 +533,25 @@ | ||
if ( arraysEqual( cache, v ) ) return; | ||
if ( v.x !== undefined ) { | ||
gl.uniform4uiv( this.addr, v ); | ||
if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y || cache[ 2 ] !== v.z || cache[ 3 ] !== v.w ) { | ||
copyArray( cache, v ); | ||
gl.uniform4ui( this.addr, v.x, v.y, v.z, v.w ); | ||
cache[ 0 ] = v.x; | ||
cache[ 1 ] = v.y; | ||
cache[ 2 ] = v.z; | ||
cache[ 3 ] = v.w; | ||
} | ||
} else { | ||
if ( arraysEqual( cache, v ) ) return; | ||
gl.uniform4uiv( this.addr, v ); | ||
copyArray( cache, v ); | ||
} | ||
} | ||
@@ -462,0 +558,0 @@ |
@@ -6,3 +6,3 @@ import { WebGLRenderTarget } from './WebGLRenderTarget.js'; | ||
constructor( width, height, depth ) { | ||
constructor( width = 1, height = 1, depth = 1 ) { | ||
@@ -9,0 +9,0 @@ super( width, height ); |
@@ -6,3 +6,3 @@ import { WebGLRenderTarget } from './WebGLRenderTarget.js'; | ||
constructor( width, height, depth ) { | ||
constructor( width = 1, height = 1, depth = 1 ) { | ||
@@ -9,0 +9,0 @@ super( width, height ); |
@@ -12,3 +12,3 @@ import { BackSide, LinearFilter, LinearMipmapLinearFilter, NoBlending } from '../constants.js'; | ||
constructor( size, options = {} ) { | ||
constructor( size = 1, options = {} ) { | ||
@@ -15,0 +15,0 @@ super( size, size, options ); |
@@ -5,3 +5,3 @@ import { WebGLRenderTarget } from './WebGLRenderTarget.js'; | ||
constructor( width, height, count, options = {} ) { | ||
constructor( width = 1, height = 1, count = 1, options = {} ) { | ||
@@ -8,0 +8,0 @@ super( width, height, options ); |
@@ -340,3 +340,3 @@ import { | ||
renderStates = new WebGLRenderStates( extensions, capabilities ); | ||
background = new WebGLBackground( _this, cubemaps, state, objects, _alpha, _premultipliedAlpha ); | ||
background = new WebGLBackground( _this, cubemaps, cubeuvmaps, state, objects, _alpha, _premultipliedAlpha ); | ||
shadowMap = new WebGLShadowMap( _this, objects, capabilities ); | ||
@@ -1939,2 +1939,5 @@ uniformsGroups = new WebGLUniformsGroups( _gl, info, capabilities, state ); | ||
let useDefaultFramebuffer = true; | ||
let framebuffer = null; | ||
let isCube = false; | ||
let isRenderTarget3D = false; | ||
@@ -1962,13 +1965,5 @@ if ( renderTarget ) { | ||
} | ||
let framebuffer = null; | ||
let isCube = false; | ||
let isRenderTarget3D = false; | ||
if ( renderTarget ) { | ||
const texture = renderTarget.texture; | ||
if ( texture.isData3DTexture || texture.isDataArrayTexture ) { | ||
if ( texture.isData3DTexture || texture.isDataArrayTexture || texture.isCompressedArrayTexture ) { | ||
@@ -2214,3 +2209,3 @@ isRenderTarget3D = true; | ||
if ( srcTexture.isCompressedTexture ) { | ||
if ( srcTexture.isCompressedArrayTexture ) { | ||
@@ -2251,3 +2246,3 @@ console.warn( 'THREE.WebGLRenderer.copyTextureToTexture3D: untested support for compressed srcTexture.' ); | ||
} else if ( texture.isDataArrayTexture ) { | ||
} else if ( texture.isDataArrayTexture || texture.isCompressedArrayTexture ) { | ||
@@ -2254,0 +2249,0 @@ textures.setTexture2DArray( texture, 0 ); |
@@ -14,3 +14,3 @@ import { EventDispatcher } from '../core/EventDispatcher.js'; | ||
constructor( width, height, options = {} ) { | ||
constructor( width = 1, height = 1, options = {} ) { | ||
@@ -17,0 +17,0 @@ super(); |
@@ -17,2 +17,4 @@ import { Object3D } from '../core/Object3D.js'; | ||
this.backgroundBlurriness = 0; | ||
this.overrideMaterial = null; | ||
@@ -36,2 +38,4 @@ | ||
this.backgroundBlurriness = source.backgroundBlurriness; | ||
if ( source.overrideMaterial !== null ) this.overrideMaterial = source.overrideMaterial.clone(); | ||
@@ -50,2 +54,3 @@ | ||
if ( this.fog !== null ) data.object.fog = this.fog.toJSON(); | ||
if ( this.backgroundBlurriness > 0 ) data.backgroundBlurriness = this.backgroundBlurriness; | ||
@@ -52,0 +57,0 @@ return data; |
@@ -36,2 +36,3 @@ import { REVISION } from './constants.js'; | ||
export { CompressedTexture } from './textures/CompressedTexture.js'; | ||
export { CompressedArrayTexture } from './textures/CompressedArrayTexture.js'; | ||
export { CubeTexture } from './textures/CubeTexture.js'; | ||
@@ -38,0 +39,0 @@ export { CanvasTexture } from './textures/CanvasTexture.js'; |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
33285270
1171
430786
50