| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619 |
- import { Quaternion } from '../math/Quaternion.js';
- import { Vector3 } from '../math/Vector3.js';
- import { Matrix4 } from '../math/Matrix4.js';
- import { EventDispatcher } from './EventDispatcher.js';
- import { Euler } from '../math/Euler.js';
- import { Layers } from './Layers.js';
- import { Matrix3 } from '../math/Matrix3.js';
- import { generateUUID } from '../math/MathUtils.js';
- import { error } from '../utils.js';
- let _object3DId = 0;
- const _v1 = /*@__PURE__*/ new Vector3();
- const _q1 = /*@__PURE__*/ new Quaternion();
- const _m1 = /*@__PURE__*/ new Matrix4();
- const _target = /*@__PURE__*/ new Vector3();
- const _position = /*@__PURE__*/ new Vector3();
- const _scale = /*@__PURE__*/ new Vector3();
- const _quaternion = /*@__PURE__*/ new Quaternion();
- const _xAxis = /*@__PURE__*/ new Vector3( 1, 0, 0 );
- const _yAxis = /*@__PURE__*/ new Vector3( 0, 1, 0 );
- const _zAxis = /*@__PURE__*/ new Vector3( 0, 0, 1 );
- /**
- * Fires when the object has been added to its parent object.
- *
- * @event Object3D#added
- * @type {Object}
- */
- const _addedEvent = { type: 'added' };
- /**
- * Fires when the object has been removed from its parent object.
- *
- * @event Object3D#removed
- * @type {Object}
- */
- const _removedEvent = { type: 'removed' };
- /**
- * Fires when a new child object has been added.
- *
- * @event Object3D#childadded
- * @type {Object}
- */
- const _childaddedEvent = { type: 'childadded', child: null };
- /**
- * Fires when a child object has been removed.
- *
- * @event Object3D#childremoved
- * @type {Object}
- */
- const _childremovedEvent = { type: 'childremoved', child: null };
- /**
- * This is the base class for most objects in three.js and provides a set of
- * properties and methods for manipulating objects in 3D space.
- *
- * @augments EventDispatcher
- */
- class Object3D extends EventDispatcher {
- /**
- * Constructs a new 3D object.
- */
- constructor() {
- super();
- /**
- * This flag can be used for type testing.
- *
- * @type {boolean}
- * @readonly
- * @default true
- */
- this.isObject3D = true;
- /**
- * The ID of the 3D object.
- *
- * @name Object3D#id
- * @type {number}
- * @readonly
- */
- Object.defineProperty( this, 'id', { value: _object3DId ++ } );
- /**
- * The UUID of the 3D object.
- *
- * @type {string}
- * @readonly
- */
- this.uuid = generateUUID();
- /**
- * The name of the 3D object.
- *
- * @type {string}
- */
- this.name = '';
- /**
- * The type property is used for detecting the object type
- * in context of serialization/deserialization.
- *
- * @type {string}
- * @readonly
- */
- this.type = 'Object3D';
- /**
- * A reference to the parent object.
- *
- * @type {?Object3D}
- * @default null
- */
- this.parent = null;
- /**
- * An array holding the child 3D objects of this instance.
- *
- * @type {Array<Object3D>}
- */
- this.children = [];
- /**
- * Defines the `up` direction of the 3D object which influences
- * the orientation via methods like {@link Object3D#lookAt}.
- *
- * The default values for all 3D objects is defined by `Object3D.DEFAULT_UP`.
- *
- * @type {Vector3}
- */
- this.up = Object3D.DEFAULT_UP.clone();
- const position = new Vector3();
- const rotation = new Euler();
- const quaternion = new Quaternion();
- const scale = new Vector3( 1, 1, 1 );
- function onRotationChange() {
- quaternion.setFromEuler( rotation, false );
- }
- function onQuaternionChange() {
- rotation.setFromQuaternion( quaternion, undefined, false );
- }
- rotation._onChange( onRotationChange );
- quaternion._onChange( onQuaternionChange );
- Object.defineProperties( this, {
- /**
- * Represents the object's local position.
- *
- * @name Object3D#position
- * @type {Vector3}
- * @default (0,0,0)
- */
- position: {
- configurable: true,
- enumerable: true,
- value: position
- },
- /**
- * Represents the object's local rotation as Euler angles, in radians.
- *
- * @name Object3D#rotation
- * @type {Euler}
- * @default (0,0,0)
- */
- rotation: {
- configurable: true,
- enumerable: true,
- value: rotation
- },
- /**
- * Represents the object's local rotation as Quaternions.
- *
- * @name Object3D#quaternion
- * @type {Quaternion}
- */
- quaternion: {
- configurable: true,
- enumerable: true,
- value: quaternion
- },
- /**
- * Represents the object's local scale.
- *
- * @name Object3D#scale
- * @type {Vector3}
- * @default (1,1,1)
- */
- scale: {
- configurable: true,
- enumerable: true,
- value: scale
- },
- /**
- * Represents the object's model-view matrix.
- *
- * @name Object3D#modelViewMatrix
- * @type {Matrix4}
- */
- modelViewMatrix: {
- value: new Matrix4()
- },
- /**
- * Represents the object's normal matrix.
- *
- * @name Object3D#normalMatrix
- * @type {Matrix3}
- */
- normalMatrix: {
- value: new Matrix3()
- }
- } );
- /**
- * Represents the object's transformation matrix in local space.
- *
- * @type {Matrix4}
- */
- this.matrix = new Matrix4();
- /**
- * Represents the object's transformation matrix in world space.
- * If the 3D object has no parent, then it's identical to the local transformation matrix
- *
- * @type {Matrix4}
- */
- this.matrixWorld = new Matrix4();
- /**
- * When set to `true`, the engine automatically computes the local matrix from position,
- * rotation and scale every frame.
- *
- * The default values for all 3D objects is defined by `Object3D.DEFAULT_MATRIX_AUTO_UPDATE`.
- *
- * @type {boolean}
- * @default true
- */
- this.matrixAutoUpdate = Object3D.DEFAULT_MATRIX_AUTO_UPDATE;
- /**
- * When set to `true`, the engine automatically computes the world matrix from the current local
- * matrix and the object's transformation hierarchy.
- *
- * The default values for all 3D objects is defined by `Object3D.DEFAULT_MATRIX_WORLD_AUTO_UPDATE`.
- *
- * @type {boolean}
- * @default true
- */
- this.matrixWorldAutoUpdate = Object3D.DEFAULT_MATRIX_WORLD_AUTO_UPDATE; // checked by the renderer
- /**
- * When set to `true`, it calculates the world matrix in that frame and resets this property
- * to `false`.
- *
- * @type {boolean}
- * @default false
- */
- this.matrixWorldNeedsUpdate = false;
- /**
- * The layer membership of the 3D object. The 3D object is only visible if it has
- * at least one layer in common with the camera in use. This property can also be
- * used to filter out unwanted objects in ray-intersection tests when using {@link Raycaster}.
- *
- * @type {Layers}
- */
- this.layers = new Layers();
- /**
- * When set to `true`, the 3D object gets rendered.
- *
- * @type {boolean}
- * @default true
- */
- this.visible = true;
- /**
- * When set to `true`, the 3D object gets rendered into shadow maps.
- *
- * @type {boolean}
- * @default false
- */
- this.castShadow = false;
- /**
- * When set to `true`, the 3D object is affected by shadows in the scene.
- *
- * @type {boolean}
- * @default false
- */
- this.receiveShadow = false;
- /**
- * When set to `true`, the 3D object is honored by view frustum culling.
- *
- * @type {boolean}
- * @default true
- */
- this.frustumCulled = true;
- /**
- * This value allows the default rendering order of scene graph objects to be
- * overridden although opaque and transparent objects remain sorted independently.
- * When this property is set for an instance of {@link Group},all descendants
- * objects will be sorted and rendered together. Sorting is from lowest to highest
- * render order.
- *
- * @type {number}
- * @default 0
- */
- this.renderOrder = 0;
- /**
- * An array holding the animation clips of the 3D object.
- *
- * @type {Array<AnimationClip>}
- */
- this.animations = [];
- /**
- * Custom depth material to be used when rendering to the depth map. Can only be used
- * in context of meshes. When shadow-casting with a {@link DirectionalLight} or {@link SpotLight},
- * if you are modifying vertex positions in the vertex shader you must specify a custom depth
- * material for proper shadows.
- *
- * Only relevant in context of {@link WebGLRenderer}.
- *
- * @type {(Material|undefined)}
- * @default undefined
- */
- this.customDepthMaterial = undefined;
- /**
- * Same as {@link Object3D#customDepthMaterial}, but used with {@link PointLight}.
- *
- * Only relevant in context of {@link WebGLRenderer}.
- *
- * @type {(Material|undefined)}
- * @default undefined
- */
- this.customDistanceMaterial = undefined;
- /**
- * An object that can be used to store custom data about the 3D object. It
- * should not hold references to functions as these will not be cloned.
- *
- * @type {Object}
- */
- this.userData = {};
- }
- /**
- * A callback that is executed immediately before a 3D object is rendered to a shadow map.
- *
- * @param {Renderer|WebGLRenderer} renderer - The renderer.
- * @param {Object3D} object - The 3D object.
- * @param {Camera} camera - The camera that is used to render the scene.
- * @param {Camera} shadowCamera - The shadow camera.
- * @param {BufferGeometry} geometry - The 3D object's geometry.
- * @param {Material} depthMaterial - The depth material.
- * @param {Object} group - The geometry group data.
- */
- onBeforeShadow( /* renderer, object, camera, shadowCamera, geometry, depthMaterial, group */ ) {}
- /**
- * A callback that is executed immediately after a 3D object is rendered to a shadow map.
- *
- * @param {Renderer|WebGLRenderer} renderer - The renderer.
- * @param {Object3D} object - The 3D object.
- * @param {Camera} camera - The camera that is used to render the scene.
- * @param {Camera} shadowCamera - The shadow camera.
- * @param {BufferGeometry} geometry - The 3D object's geometry.
- * @param {Material} depthMaterial - The depth material.
- * @param {Object} group - The geometry group data.
- */
- onAfterShadow( /* renderer, object, camera, shadowCamera, geometry, depthMaterial, group */ ) {}
- /**
- * A callback that is executed immediately before a 3D object is rendered.
- *
- * @param {Renderer|WebGLRenderer} renderer - The renderer.
- * @param {Object3D} object - The 3D object.
- * @param {Camera} camera - The camera that is used to render the scene.
- * @param {BufferGeometry} geometry - The 3D object's geometry.
- * @param {Material} material - The 3D object's material.
- * @param {Object} group - The geometry group data.
- */
- onBeforeRender( /* renderer, scene, camera, geometry, material, group */ ) {}
- /**
- * A callback that is executed immediately after a 3D object is rendered.
- *
- * @param {Renderer|WebGLRenderer} renderer - The renderer.
- * @param {Object3D} object - The 3D object.
- * @param {Camera} camera - The camera that is used to render the scene.
- * @param {BufferGeometry} geometry - The 3D object's geometry.
- * @param {Material} material - The 3D object's material.
- * @param {Object} group - The geometry group data.
- */
- onAfterRender( /* renderer, scene, camera, geometry, material, group */ ) {}
- /**
- * Applies the given transformation matrix to the object and updates the object's position,
- * rotation and scale.
- *
- * @param {Matrix4} matrix - The transformation matrix.
- */
- applyMatrix4( matrix ) {
- if ( this.matrixAutoUpdate ) this.updateMatrix();
- this.matrix.premultiply( matrix );
- this.matrix.decompose( this.position, this.quaternion, this.scale );
- }
- /**
- * Applies a rotation represented by given the quaternion to the 3D object.
- *
- * @param {Quaternion} q - The quaternion.
- * @return {Object3D} A reference to this instance.
- */
- applyQuaternion( q ) {
- this.quaternion.premultiply( q );
- return this;
- }
- /**
- * Sets the given rotation represented as an axis/angle couple to the 3D object.
- *
- * @param {Vector3} axis - The (normalized) axis vector.
- * @param {number} angle - The angle in radians.
- */
- setRotationFromAxisAngle( axis, angle ) {
- // assumes axis is normalized
- this.quaternion.setFromAxisAngle( axis, angle );
- }
- /**
- * Sets the given rotation represented as Euler angles to the 3D object.
- *
- * @param {Euler} euler - The Euler angles.
- */
- setRotationFromEuler( euler ) {
- this.quaternion.setFromEuler( euler, true );
- }
- /**
- * Sets the given rotation represented as rotation matrix to the 3D object.
- *
- * @param {Matrix4} m - Although a 4x4 matrix is expected, the upper 3x3 portion must be
- * a pure rotation matrix (i.e, unscaled).
- */
- setRotationFromMatrix( m ) {
- // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
- this.quaternion.setFromRotationMatrix( m );
- }
- /**
- * Sets the given rotation represented as a Quaternion to the 3D object.
- *
- * @param {Quaternion} q - The Quaternion
- */
- setRotationFromQuaternion( q ) {
- // assumes q is normalized
- this.quaternion.copy( q );
- }
- /**
- * Rotates the 3D object along an axis in local space.
- *
- * @param {Vector3} axis - The (normalized) axis vector.
- * @param {number} angle - The angle in radians.
- * @return {Object3D} A reference to this instance.
- */
- rotateOnAxis( axis, angle ) {
- // rotate object on axis in object space
- // axis is assumed to be normalized
- _q1.setFromAxisAngle( axis, angle );
- this.quaternion.multiply( _q1 );
- return this;
- }
- /**
- * Rotates the 3D object along an axis in world space.
- *
- * @param {Vector3} axis - The (normalized) axis vector.
- * @param {number} angle - The angle in radians.
- * @return {Object3D} A reference to this instance.
- */
- rotateOnWorldAxis( axis, angle ) {
- // rotate object on axis in world space
- // axis is assumed to be normalized
- // method assumes no rotated parent
- _q1.setFromAxisAngle( axis, angle );
- this.quaternion.premultiply( _q1 );
- return this;
- }
- /**
- * Rotates the 3D object around its X axis in local space.
- *
- * @param {number} angle - The angle in radians.
- * @return {Object3D} A reference to this instance.
- */
- rotateX( angle ) {
- return this.rotateOnAxis( _xAxis, angle );
- }
- /**
- * Rotates the 3D object around its Y axis in local space.
- *
- * @param {number} angle - The angle in radians.
- * @return {Object3D} A reference to this instance.
- */
- rotateY( angle ) {
- return this.rotateOnAxis( _yAxis, angle );
- }
- /**
- * Rotates the 3D object around its Z axis in local space.
- *
- * @param {number} angle - The angle in radians.
- * @return {Object3D} A reference to this instance.
- */
- rotateZ( angle ) {
- return this.rotateOnAxis( _zAxis, angle );
- }
- /**
- * Translate the 3D object by a distance along the given axis in local space.
- *
- * @param {Vector3} axis - The (normalized) axis vector.
- * @param {number} distance - The distance in world units.
- * @return {Object3D} A reference to this instance.
- */
- translateOnAxis( axis, distance ) {
- // translate object by distance along axis in object space
- // axis is assumed to be normalized
- _v1.copy( axis ).applyQuaternion( this.quaternion );
- this.position.add( _v1.multiplyScalar( distance ) );
- return this;
- }
- /**
- * Translate the 3D object by a distance along its X-axis in local space.
- *
- * @param {number} distance - The distance in world units.
- * @return {Object3D} A reference to this instance.
- */
- translateX( distance ) {
- return this.translateOnAxis( _xAxis, distance );
- }
- /**
- * Translate the 3D object by a distance along its Y-axis in local space.
- *
- * @param {number} distance - The distance in world units.
- * @return {Object3D} A reference to this instance.
- */
- translateY( distance ) {
- return this.translateOnAxis( _yAxis, distance );
- }
- /**
- * Translate the 3D object by a distance along its Z-axis in local space.
- *
- * @param {number} distance - The distance in world units.
- * @return {Object3D} A reference to this instance.
- */
- translateZ( distance ) {
- return this.translateOnAxis( _zAxis, distance );
- }
- /**
- * Converts the given vector from this 3D object's local space to world space.
- *
- * @param {Vector3} vector - The vector to convert.
- * @return {Vector3} The converted vector.
- */
- localToWorld( vector ) {
- this.updateWorldMatrix( true, false );
- return vector.applyMatrix4( this.matrixWorld );
- }
- /**
- * Converts the given vector from this 3D object's word space to local space.
- *
- * @param {Vector3} vector - The vector to convert.
- * @return {Vector3} The converted vector.
- */
- worldToLocal( vector ) {
- this.updateWorldMatrix( true, false );
- return vector.applyMatrix4( _m1.copy( this.matrixWorld ).invert() );
- }
- /**
- * Rotates the object to face a point in world space.
- *
- * This method does not support objects having non-uniformly-scaled parent(s).
- *
- * @param {number|Vector3} x - The x coordinate in world space. Alternatively, a vector representing a position in world space
- * @param {number} [y] - The y coordinate in world space.
- * @param {number} [z] - The z coordinate in world space.
- */
- lookAt( x, y, z ) {
- // This method does not support objects having non-uniformly-scaled parent(s)
- if ( x.isVector3 ) {
- _target.copy( x );
- } else {
- _target.set( x, y, z );
- }
- const parent = this.parent;
- this.updateWorldMatrix( true, false );
- _position.setFromMatrixPosition( this.matrixWorld );
- if ( this.isCamera || this.isLight ) {
- _m1.lookAt( _position, _target, this.up );
- } else {
- _m1.lookAt( _target, _position, this.up );
- }
- this.quaternion.setFromRotationMatrix( _m1 );
- if ( parent ) {
- _m1.extractRotation( parent.matrixWorld );
- _q1.setFromRotationMatrix( _m1 );
- this.quaternion.premultiply( _q1.invert() );
- }
- }
- /**
- * Adds the given 3D object as a child to this 3D object. An arbitrary number of
- * objects may be added. Any current parent on an object passed in here will be
- * removed, since an object can have at most one parent.
- *
- * @fires Object3D#added
- * @fires Object3D#childadded
- * @param {Object3D} object - The 3D object to add.
- * @return {Object3D} A reference to this instance.
- */
- add( object ) {
- if ( arguments.length > 1 ) {
- for ( let i = 0; i < arguments.length; i ++ ) {
- this.add( arguments[ i ] );
- }
- return this;
- }
- if ( object === this ) {
- error( 'Object3D.add: object can\'t be added as a child of itself.', object );
- return this;
- }
- if ( object && object.isObject3D ) {
- object.removeFromParent();
- object.parent = this;
- this.children.push( object );
- object.dispatchEvent( _addedEvent );
- _childaddedEvent.child = object;
- this.dispatchEvent( _childaddedEvent );
- _childaddedEvent.child = null;
- } else {
- error( 'Object3D.add: object not an instance of THREE.Object3D.', object );
- }
- return this;
- }
- /**
- * Removes the given 3D object as child from this 3D object.
- * An arbitrary number of objects may be removed.
- *
- * @fires Object3D#removed
- * @fires Object3D#childremoved
- * @param {Object3D} object - The 3D object to remove.
- * @return {Object3D} A reference to this instance.
- */
- remove( object ) {
- if ( arguments.length > 1 ) {
- for ( let i = 0; i < arguments.length; i ++ ) {
- this.remove( arguments[ i ] );
- }
- return this;
- }
- const index = this.children.indexOf( object );
- if ( index !== - 1 ) {
- object.parent = null;
- this.children.splice( index, 1 );
- object.dispatchEvent( _removedEvent );
- _childremovedEvent.child = object;
- this.dispatchEvent( _childremovedEvent );
- _childremovedEvent.child = null;
- }
- return this;
- }
- /**
- * Removes this 3D object from its current parent.
- *
- * @fires Object3D#removed
- * @fires Object3D#childremoved
- * @return {Object3D} A reference to this instance.
- */
- removeFromParent() {
- const parent = this.parent;
- if ( parent !== null ) {
- parent.remove( this );
- }
- return this;
- }
- /**
- * Removes all child objects.
- *
- * @fires Object3D#removed
- * @fires Object3D#childremoved
- * @return {Object3D} A reference to this instance.
- */
- clear() {
- return this.remove( ... this.children );
- }
- /**
- * Adds the given 3D object as a child of this 3D object, while maintaining the object's world
- * transform. This method does not support scene graphs having non-uniformly-scaled nodes(s).
- *
- * @fires Object3D#added
- * @fires Object3D#childadded
- * @param {Object3D} object - The 3D object to attach.
- * @return {Object3D} A reference to this instance.
- */
- attach( object ) {
- // adds object as a child of this, while maintaining the object's world transform
- // Note: This method does not support scene graphs having non-uniformly-scaled nodes(s)
- this.updateWorldMatrix( true, false );
- _m1.copy( this.matrixWorld ).invert();
- if ( object.parent !== null ) {
- object.parent.updateWorldMatrix( true, false );
- _m1.multiply( object.parent.matrixWorld );
- }
- object.applyMatrix4( _m1 );
- object.removeFromParent();
- object.parent = this;
- this.children.push( object );
- object.updateWorldMatrix( false, true );
- object.dispatchEvent( _addedEvent );
- _childaddedEvent.child = object;
- this.dispatchEvent( _childaddedEvent );
- _childaddedEvent.child = null;
- return this;
- }
- /**
- * Searches through the 3D object and its children, starting with the 3D object
- * itself, and returns the first with a matching ID.
- *
- * @param {number} id - The id.
- * @return {Object3D|undefined} The found 3D object. Returns `undefined` if no 3D object has been found.
- */
- getObjectById( id ) {
- return this.getObjectByProperty( 'id', id );
- }
- /**
- * Searches through the 3D object and its children, starting with the 3D object
- * itself, and returns the first with a matching name.
- *
- * @param {string} name - The name.
- * @return {Object3D|undefined} The found 3D object. Returns `undefined` if no 3D object has been found.
- */
- getObjectByName( name ) {
- return this.getObjectByProperty( 'name', name );
- }
- /**
- * Searches through the 3D object and its children, starting with the 3D object
- * itself, and returns the first with a matching property value.
- *
- * @param {string} name - The name of the property.
- * @param {any} value - The value.
- * @return {Object3D|undefined} The found 3D object. Returns `undefined` if no 3D object has been found.
- */
- getObjectByProperty( name, value ) {
- if ( this[ name ] === value ) return this;
- for ( let i = 0, l = this.children.length; i < l; i ++ ) {
- const child = this.children[ i ];
- const object = child.getObjectByProperty( name, value );
- if ( object !== undefined ) {
- return object;
- }
- }
- return undefined;
- }
- /**
- * Searches through the 3D object and its children, starting with the 3D object
- * itself, and returns all 3D objects with a matching property value.
- *
- * @param {string} name - The name of the property.
- * @param {any} value - The value.
- * @param {Array<Object3D>} result - The method stores the result in this array.
- * @return {Array<Object3D>} The found 3D objects.
- */
- getObjectsByProperty( name, value, result = [] ) {
- if ( this[ name ] === value ) result.push( this );
- const children = this.children;
- for ( let i = 0, l = children.length; i < l; i ++ ) {
- children[ i ].getObjectsByProperty( name, value, result );
- }
- return result;
- }
- /**
- * Returns a vector representing the position of the 3D object in world space.
- *
- * @param {Vector3} target - The target vector the result is stored to.
- * @return {Vector3} The 3D object's position in world space.
- */
- getWorldPosition( target ) {
- this.updateWorldMatrix( true, false );
- return target.setFromMatrixPosition( this.matrixWorld );
- }
- /**
- * Returns a Quaternion representing the position of the 3D object in world space.
- *
- * @param {Quaternion} target - The target Quaternion the result is stored to.
- * @return {Quaternion} The 3D object's rotation in world space.
- */
- getWorldQuaternion( target ) {
- this.updateWorldMatrix( true, false );
- this.matrixWorld.decompose( _position, target, _scale );
- return target;
- }
- /**
- * Returns a vector representing the scale of the 3D object in world space.
- *
- * @param {Vector3} target - The target vector the result is stored to.
- * @return {Vector3} The 3D object's scale in world space.
- */
- getWorldScale( target ) {
- this.updateWorldMatrix( true, false );
- this.matrixWorld.decompose( _position, _quaternion, target );
- return target;
- }
- /**
- * Returns a vector representing the ("look") direction of the 3D object in world space.
- *
- * @param {Vector3} target - The target vector the result is stored to.
- * @return {Vector3} The 3D object's direction in world space.
- */
- getWorldDirection( target ) {
- this.updateWorldMatrix( true, false );
- const e = this.matrixWorld.elements;
- return target.set( e[ 8 ], e[ 9 ], e[ 10 ] ).normalize();
- }
- /**
- * Abstract method to get intersections between a casted ray and this
- * 3D object. Renderable 3D objects such as {@link Mesh}, {@link Line} or {@link Points}
- * implement this method in order to use raycasting.
- *
- * @abstract
- * @param {Raycaster} raycaster - The raycaster.
- * @param {Array<Object>} intersects - An array holding the result of the method.
- */
- raycast( /* raycaster, intersects */ ) {}
- /**
- * Executes the callback on this 3D object and all descendants.
- *
- * Note: Modifying the scene graph inside the callback is discouraged.
- *
- * @param {Function} callback - A callback function that allows to process the current 3D object.
- */
- traverse( callback ) {
- callback( this );
- const children = this.children;
- for ( let i = 0, l = children.length; i < l; i ++ ) {
- children[ i ].traverse( callback );
- }
- }
- /**
- * Like {@link Object3D#traverse}, but the callback will only be executed for visible 3D objects.
- * Descendants of invisible 3D objects are not traversed.
- *
- * Note: Modifying the scene graph inside the callback is discouraged.
- *
- * @param {Function} callback - A callback function that allows to process the current 3D object.
- */
- traverseVisible( callback ) {
- if ( this.visible === false ) return;
- callback( this );
- const children = this.children;
- for ( let i = 0, l = children.length; i < l; i ++ ) {
- children[ i ].traverseVisible( callback );
- }
- }
- /**
- * Like {@link Object3D#traverse}, but the callback will only be executed for all ancestors.
- *
- * Note: Modifying the scene graph inside the callback is discouraged.
- *
- * @param {Function} callback - A callback function that allows to process the current 3D object.
- */
- traverseAncestors( callback ) {
- const parent = this.parent;
- if ( parent !== null ) {
- callback( parent );
- parent.traverseAncestors( callback );
- }
- }
- /**
- * Updates the transformation matrix in local space by computing it from the current
- * position, rotation and scale values.
- */
- updateMatrix() {
- this.matrix.compose( this.position, this.quaternion, this.scale );
- this.matrixWorldNeedsUpdate = true;
- }
- /**
- * Updates the transformation matrix in world space of this 3D objects and its descendants.
- *
- * To ensure correct results, this method also recomputes the 3D object's transformation matrix in
- * local space. The computation of the local and world matrix can be controlled with the
- * {@link Object3D#matrixAutoUpdate} and {@link Object3D#matrixWorldAutoUpdate} flags which are both
- * `true` by default. Set these flags to `false` if you need more control over the update matrix process.
- *
- * @param {boolean} [force=false] - When set to `true`, a recomputation of world matrices is forced even
- * when {@link Object3D#matrixWorldAutoUpdate} is set to `false`.
- */
- updateMatrixWorld( force ) {
- if ( this.matrixAutoUpdate ) this.updateMatrix();
- if ( this.matrixWorldNeedsUpdate || force ) {
- if ( this.matrixWorldAutoUpdate === true ) {
- if ( this.parent === null ) {
- this.matrixWorld.copy( this.matrix );
- } else {
- this.matrixWorld.multiplyMatrices( this.parent.matrixWorld, this.matrix );
- }
- }
- this.matrixWorldNeedsUpdate = false;
- force = true;
- }
- // make sure descendants are updated if required
- const children = this.children;
- for ( let i = 0, l = children.length; i < l; i ++ ) {
- const child = children[ i ];
- child.updateMatrixWorld( force );
- }
- }
- /**
- * An alternative version of {@link Object3D#updateMatrixWorld} with more control over the
- * update of ancestor and descendant nodes.
- *
- * @param {boolean} [updateParents=false] Whether ancestor nodes should be updated or not.
- * @param {boolean} [updateChildren=false] Whether descendant nodes should be updated or not.
- */
- updateWorldMatrix( updateParents, updateChildren ) {
- const parent = this.parent;
- if ( updateParents === true && parent !== null ) {
- parent.updateWorldMatrix( true, false );
- }
- if ( this.matrixAutoUpdate ) this.updateMatrix();
- if ( this.matrixWorldAutoUpdate === true ) {
- if ( this.parent === null ) {
- this.matrixWorld.copy( this.matrix );
- } else {
- this.matrixWorld.multiplyMatrices( this.parent.matrixWorld, this.matrix );
- }
- }
- // make sure descendants are updated
- if ( updateChildren === true ) {
- const children = this.children;
- for ( let i = 0, l = children.length; i < l; i ++ ) {
- const child = children[ i ];
- child.updateWorldMatrix( false, true );
- }
- }
- }
- /**
- * Serializes the 3D object into JSON.
- *
- * @param {?(Object|string)} meta - An optional value holding meta information about the serialization.
- * @return {Object} A JSON object representing the serialized 3D object.
- * @see {@link ObjectLoader#parse}
- */
- toJSON( meta ) {
- // meta is a string when called from JSON.stringify
- const isRootObject = ( meta === undefined || typeof meta === 'string' );
- const output = {};
- // meta is a hash used to collect geometries, materials.
- // not providing it implies that this is the root object
- // being serialized.
- if ( isRootObject ) {
- // initialize meta obj
- meta = {
- geometries: {},
- materials: {},
- textures: {},
- images: {},
- shapes: {},
- skeletons: {},
- animations: {},
- nodes: {}
- };
- output.metadata = {
- version: 4.7,
- type: 'Object',
- generator: 'Object3D.toJSON'
- };
- }
- // standard Object3D serialization
- const object = {};
- object.uuid = this.uuid;
- object.type = this.type;
- if ( this.name !== '' ) object.name = this.name;
- if ( this.castShadow === true ) object.castShadow = true;
- if ( this.receiveShadow === true ) object.receiveShadow = true;
- if ( this.visible === false ) object.visible = false;
- if ( this.frustumCulled === false ) object.frustumCulled = false;
- if ( this.renderOrder !== 0 ) object.renderOrder = this.renderOrder;
- if ( Object.keys( this.userData ).length > 0 ) object.userData = this.userData;
- object.layers = this.layers.mask;
- object.matrix = this.matrix.toArray();
- object.up = this.up.toArray();
- if ( this.matrixAutoUpdate === false ) object.matrixAutoUpdate = false;
- // object specific properties
- if ( this.isInstancedMesh ) {
- object.type = 'InstancedMesh';
- object.count = this.count;
- object.instanceMatrix = this.instanceMatrix.toJSON();
- if ( this.instanceColor !== null ) object.instanceColor = this.instanceColor.toJSON();
- }
- if ( this.isBatchedMesh ) {
- object.type = 'BatchedMesh';
- object.perObjectFrustumCulled = this.perObjectFrustumCulled;
- object.sortObjects = this.sortObjects;
- object.drawRanges = this._drawRanges;
- object.reservedRanges = this._reservedRanges;
- object.geometryInfo = this._geometryInfo.map( info => ( {
- ...info,
- boundingBox: info.boundingBox ? info.boundingBox.toJSON() : undefined,
- boundingSphere: info.boundingSphere ? info.boundingSphere.toJSON() : undefined
- } ) );
- object.instanceInfo = this._instanceInfo.map( info => ( { ...info } ) );
- object.availableInstanceIds = this._availableInstanceIds.slice();
- object.availableGeometryIds = this._availableGeometryIds.slice();
- object.nextIndexStart = this._nextIndexStart;
- object.nextVertexStart = this._nextVertexStart;
- object.geometryCount = this._geometryCount;
- object.maxInstanceCount = this._maxInstanceCount;
- object.maxVertexCount = this._maxVertexCount;
- object.maxIndexCount = this._maxIndexCount;
- object.geometryInitialized = this._geometryInitialized;
- object.matricesTexture = this._matricesTexture.toJSON( meta );
- object.indirectTexture = this._indirectTexture.toJSON( meta );
- if ( this._colorsTexture !== null ) {
- object.colorsTexture = this._colorsTexture.toJSON( meta );
- }
- if ( this.boundingSphere !== null ) {
- object.boundingSphere = this.boundingSphere.toJSON();
- }
- if ( this.boundingBox !== null ) {
- object.boundingBox = this.boundingBox.toJSON();
- }
- }
- //
- function serialize( library, element ) {
- if ( library[ element.uuid ] === undefined ) {
- library[ element.uuid ] = element.toJSON( meta );
- }
- return element.uuid;
- }
- if ( this.isScene ) {
- if ( this.background ) {
- if ( this.background.isColor ) {
- object.background = this.background.toJSON();
- } else if ( this.background.isTexture ) {
- object.background = this.background.toJSON( meta ).uuid;
- }
- }
- if ( this.environment && this.environment.isTexture && this.environment.isRenderTargetTexture !== true ) {
- object.environment = this.environment.toJSON( meta ).uuid;
- }
- } else if ( this.isMesh || this.isLine || this.isPoints ) {
- object.geometry = serialize( meta.geometries, this.geometry );
- const parameters = this.geometry.parameters;
- if ( parameters !== undefined && parameters.shapes !== undefined ) {
- const shapes = parameters.shapes;
- if ( Array.isArray( shapes ) ) {
- for ( let i = 0, l = shapes.length; i < l; i ++ ) {
- const shape = shapes[ i ];
- serialize( meta.shapes, shape );
- }
- } else {
- serialize( meta.shapes, shapes );
- }
- }
- }
- if ( this.isSkinnedMesh ) {
- object.bindMode = this.bindMode;
- object.bindMatrix = this.bindMatrix.toArray();
- if ( this.skeleton !== undefined ) {
- serialize( meta.skeletons, this.skeleton );
- object.skeleton = this.skeleton.uuid;
- }
- }
- if ( this.material !== undefined ) {
- if ( Array.isArray( this.material ) ) {
- const uuids = [];
- for ( let i = 0, l = this.material.length; i < l; i ++ ) {
- uuids.push( serialize( meta.materials, this.material[ i ] ) );
- }
- object.material = uuids;
- } else {
- object.material = serialize( meta.materials, this.material );
- }
- }
- //
- if ( this.children.length > 0 ) {
- object.children = [];
- for ( let i = 0; i < this.children.length; i ++ ) {
- object.children.push( this.children[ i ].toJSON( meta ).object );
- }
- }
- //
- if ( this.animations.length > 0 ) {
- object.animations = [];
- for ( let i = 0; i < this.animations.length; i ++ ) {
- const animation = this.animations[ i ];
- object.animations.push( serialize( meta.animations, animation ) );
- }
- }
- if ( isRootObject ) {
- const geometries = extractFromCache( meta.geometries );
- const materials = extractFromCache( meta.materials );
- const textures = extractFromCache( meta.textures );
- const images = extractFromCache( meta.images );
- const shapes = extractFromCache( meta.shapes );
- const skeletons = extractFromCache( meta.skeletons );
- const animations = extractFromCache( meta.animations );
- const nodes = extractFromCache( meta.nodes );
- if ( geometries.length > 0 ) output.geometries = geometries;
- if ( materials.length > 0 ) output.materials = materials;
- if ( textures.length > 0 ) output.textures = textures;
- if ( images.length > 0 ) output.images = images;
- if ( shapes.length > 0 ) output.shapes = shapes;
- if ( skeletons.length > 0 ) output.skeletons = skeletons;
- if ( animations.length > 0 ) output.animations = animations;
- if ( nodes.length > 0 ) output.nodes = nodes;
- }
- output.object = object;
- return output;
- // extract data from the cache hash
- // remove metadata on each item
- // and return as array
- function extractFromCache( cache ) {
- const values = [];
- for ( const key in cache ) {
- const data = cache[ key ];
- delete data.metadata;
- values.push( data );
- }
- return values;
- }
- }
- /**
- * Returns a new 3D object with copied values from this instance.
- *
- * @param {boolean} [recursive=true] - When set to `true`, descendants of the 3D object are also cloned.
- * @return {Object3D} A clone of this instance.
- */
- clone( recursive ) {
- return new this.constructor().copy( this, recursive );
- }
- /**
- * Copies the values of the given 3D object to this instance.
- *
- * @param {Object3D} source - The 3D object to copy.
- * @param {boolean} [recursive=true] - When set to `true`, descendants of the 3D object are cloned.
- * @return {Object3D} A reference to this instance.
- */
- copy( source, recursive = true ) {
- this.name = source.name;
- this.up.copy( source.up );
- this.position.copy( source.position );
- this.rotation.order = source.rotation.order;
- this.quaternion.copy( source.quaternion );
- this.scale.copy( source.scale );
- this.matrix.copy( source.matrix );
- this.matrixWorld.copy( source.matrixWorld );
- this.matrixAutoUpdate = source.matrixAutoUpdate;
- this.matrixWorldAutoUpdate = source.matrixWorldAutoUpdate;
- this.matrixWorldNeedsUpdate = source.matrixWorldNeedsUpdate;
- this.layers.mask = source.layers.mask;
- this.visible = source.visible;
- this.castShadow = source.castShadow;
- this.receiveShadow = source.receiveShadow;
- this.frustumCulled = source.frustumCulled;
- this.renderOrder = source.renderOrder;
- this.animations = source.animations.slice();
- this.userData = JSON.parse( JSON.stringify( source.userData ) );
- if ( recursive === true ) {
- for ( let i = 0; i < source.children.length; i ++ ) {
- const child = source.children[ i ];
- this.add( child.clone() );
- }
- }
- return this;
- }
- }
- /**
- * The default up direction for objects, also used as the default
- * position for {@link DirectionalLight} and {@link HemisphereLight}.
- *
- * @static
- * @type {Vector3}
- * @default (0,1,0)
- */
- Object3D.DEFAULT_UP = /*@__PURE__*/ new Vector3( 0, 1, 0 );
- /**
- * The default setting for {@link Object3D#matrixAutoUpdate} for
- * newly created 3D objects.
- *
- * @static
- * @type {boolean}
- * @default true
- */
- Object3D.DEFAULT_MATRIX_AUTO_UPDATE = true;
- /**
- * The default setting for {@link Object3D#matrixWorldAutoUpdate} for
- * newly created 3D objects.
- *
- * @static
- * @type {boolean}
- * @default true
- */
- Object3D.DEFAULT_MATRIX_WORLD_AUTO_UPDATE = true;
- export { Object3D };
|