| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677 |
- 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. If set to `false`, the app is responsible for recomputing
- * the local matrix by calling `updateMatrix()`.
- *
- * 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. If set to `false`, the app is responsible for
- * recomputing the world matrix by directly updating the `matrixWorld` property.
- *
- * 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;
- /**
- * Whether the 3D object is supposed to be static or not. If set to `true`, it means
- * the 3D object is not going to be changed after the initial renderer. This includes
- * geometry and material settings. A static 3D object can be processed by the renderer
- * slightly faster since certain state checks can be bypassed.
- *
- * Only relevant in context of {@link WebGPURenderer}.
- *
- * @type {boolean}
- * @default false
- */
- this.static = false;
- /**
- * 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 = {};
- /**
- * The pivot point for rotation and scale transformations.
- * When set, rotation and scale are applied around this point
- * instead of the object's origin.
- *
- * @type {?Vector3}
- * @default null
- */
- this.pivot = null;
- }
- /**
- * 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 world 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 );
- const pivot = this.pivot;
- if ( pivot !== null ) {
- const px = pivot.x, py = pivot.y, pz = pivot.z;
- const te = this.matrix.elements;
- te[ 12 ] += px - te[ 0 ] * px - te[ 4 ] * py - te[ 8 ] * pz;
- te[ 13 ] += py - te[ 1 ] * px - te[ 5 ] * py - te[ 9 ] * pz;
- te[ 14 ] += pz - te[ 2 ] * px - te[ 6 ] * py - te[ 10 ] * pz;
- }
- 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#matrixWorldNeedsUpdate} is `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.
- * @param {boolean} [force=false] - When set to `true`, a recomputation of world matrices is forced even
- * when {@link Object3D#matrixWorldNeedsUpdate} is `false`.
- */
- updateWorldMatrix( updateParents, updateChildren, force = false ) {
- const parent = this.parent;
- if ( updateParents === true && parent !== null ) {
- parent.updateWorldMatrix( true, false );
- }
- 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 ( updateChildren === true ) {
- const children = this.children;
- for ( let i = 0, l = children.length; i < l; i ++ ) {
- const child = children[ i ];
- child.updateWorldMatrix( false, true, force );
- }
- }
- }
- /**
- * 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 ( this.static !== false ) object.static = this.static;
- 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.pivot !== null ) object.pivot = this.pivot.toArray();
- if ( this.matrixAutoUpdate === false ) object.matrixAutoUpdate = false;
- if ( this.morphTargetDictionary !== undefined ) object.morphTargetDictionary = Object.assign( {}, this.morphTargetDictionary );
- if ( this.morphTargetInfluences !== undefined ) object.morphTargetInfluences = this.morphTargetInfluences.slice();
- // 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.pivot = ( source.pivot !== null ) ? source.pivot.clone() : null;
- 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.static = source.static;
- 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 };
|