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