Object3D.js 38 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619
  1. import { Quaternion } from '../math/Quaternion.js';
  2. import { Vector3 } from '../math/Vector3.js';
  3. import { Matrix4 } from '../math/Matrix4.js';
  4. import { EventDispatcher } from './EventDispatcher.js';
  5. import { Euler } from '../math/Euler.js';
  6. import { Layers } from './Layers.js';
  7. import { Matrix3 } from '../math/Matrix3.js';
  8. import { generateUUID } from '../math/MathUtils.js';
  9. import { error } from '../utils.js';
  10. let _object3DId = 0;
  11. const _v1 = /*@__PURE__*/ new Vector3();
  12. const _q1 = /*@__PURE__*/ new Quaternion();
  13. const _m1 = /*@__PURE__*/ new Matrix4();
  14. const _target = /*@__PURE__*/ new Vector3();
  15. const _position = /*@__PURE__*/ new Vector3();
  16. const _scale = /*@__PURE__*/ new Vector3();
  17. const _quaternion = /*@__PURE__*/ new Quaternion();
  18. const _xAxis = /*@__PURE__*/ new Vector3( 1, 0, 0 );
  19. const _yAxis = /*@__PURE__*/ new Vector3( 0, 1, 0 );
  20. const _zAxis = /*@__PURE__*/ new Vector3( 0, 0, 1 );
  21. /**
  22. * Fires when the object has been added to its parent object.
  23. *
  24. * @event Object3D#added
  25. * @type {Object}
  26. */
  27. const _addedEvent = { type: 'added' };
  28. /**
  29. * Fires when the object has been removed from its parent object.
  30. *
  31. * @event Object3D#removed
  32. * @type {Object}
  33. */
  34. const _removedEvent = { type: 'removed' };
  35. /**
  36. * Fires when a new child object has been added.
  37. *
  38. * @event Object3D#childadded
  39. * @type {Object}
  40. */
  41. const _childaddedEvent = { type: 'childadded', child: null };
  42. /**
  43. * Fires when a child object has been removed.
  44. *
  45. * @event Object3D#childremoved
  46. * @type {Object}
  47. */
  48. const _childremovedEvent = { type: 'childremoved', child: null };
  49. /**
  50. * This is the base class for most objects in three.js and provides a set of
  51. * properties and methods for manipulating objects in 3D space.
  52. *
  53. * @augments EventDispatcher
  54. */
  55. class Object3D extends EventDispatcher {
  56. /**
  57. * Constructs a new 3D object.
  58. */
  59. constructor() {
  60. super();
  61. /**
  62. * This flag can be used for type testing.
  63. *
  64. * @type {boolean}
  65. * @readonly
  66. * @default true
  67. */
  68. this.isObject3D = true;
  69. /**
  70. * The ID of the 3D object.
  71. *
  72. * @name Object3D#id
  73. * @type {number}
  74. * @readonly
  75. */
  76. Object.defineProperty( this, 'id', { value: _object3DId ++ } );
  77. /**
  78. * The UUID of the 3D object.
  79. *
  80. * @type {string}
  81. * @readonly
  82. */
  83. this.uuid = generateUUID();
  84. /**
  85. * The name of the 3D object.
  86. *
  87. * @type {string}
  88. */
  89. this.name = '';
  90. /**
  91. * The type property is used for detecting the object type
  92. * in context of serialization/deserialization.
  93. *
  94. * @type {string}
  95. * @readonly
  96. */
  97. this.type = 'Object3D';
  98. /**
  99. * A reference to the parent object.
  100. *
  101. * @type {?Object3D}
  102. * @default null
  103. */
  104. this.parent = null;
  105. /**
  106. * An array holding the child 3D objects of this instance.
  107. *
  108. * @type {Array<Object3D>}
  109. */
  110. this.children = [];
  111. /**
  112. * Defines the `up` direction of the 3D object which influences
  113. * the orientation via methods like {@link Object3D#lookAt}.
  114. *
  115. * The default values for all 3D objects is defined by `Object3D.DEFAULT_UP`.
  116. *
  117. * @type {Vector3}
  118. */
  119. this.up = Object3D.DEFAULT_UP.clone();
  120. const position = new Vector3();
  121. const rotation = new Euler();
  122. const quaternion = new Quaternion();
  123. const scale = new Vector3( 1, 1, 1 );
  124. function onRotationChange() {
  125. quaternion.setFromEuler( rotation, false );
  126. }
  127. function onQuaternionChange() {
  128. rotation.setFromQuaternion( quaternion, undefined, false );
  129. }
  130. rotation._onChange( onRotationChange );
  131. quaternion._onChange( onQuaternionChange );
  132. Object.defineProperties( this, {
  133. /**
  134. * Represents the object's local position.
  135. *
  136. * @name Object3D#position
  137. * @type {Vector3}
  138. * @default (0,0,0)
  139. */
  140. position: {
  141. configurable: true,
  142. enumerable: true,
  143. value: position
  144. },
  145. /**
  146. * Represents the object's local rotation as Euler angles, in radians.
  147. *
  148. * @name Object3D#rotation
  149. * @type {Euler}
  150. * @default (0,0,0)
  151. */
  152. rotation: {
  153. configurable: true,
  154. enumerable: true,
  155. value: rotation
  156. },
  157. /**
  158. * Represents the object's local rotation as Quaternions.
  159. *
  160. * @name Object3D#quaternion
  161. * @type {Quaternion}
  162. */
  163. quaternion: {
  164. configurable: true,
  165. enumerable: true,
  166. value: quaternion
  167. },
  168. /**
  169. * Represents the object's local scale.
  170. *
  171. * @name Object3D#scale
  172. * @type {Vector3}
  173. * @default (1,1,1)
  174. */
  175. scale: {
  176. configurable: true,
  177. enumerable: true,
  178. value: scale
  179. },
  180. /**
  181. * Represents the object's model-view matrix.
  182. *
  183. * @name Object3D#modelViewMatrix
  184. * @type {Matrix4}
  185. */
  186. modelViewMatrix: {
  187. value: new Matrix4()
  188. },
  189. /**
  190. * Represents the object's normal matrix.
  191. *
  192. * @name Object3D#normalMatrix
  193. * @type {Matrix3}
  194. */
  195. normalMatrix: {
  196. value: new Matrix3()
  197. }
  198. } );
  199. /**
  200. * Represents the object's transformation matrix in local space.
  201. *
  202. * @type {Matrix4}
  203. */
  204. this.matrix = new Matrix4();
  205. /**
  206. * Represents the object's transformation matrix in world space.
  207. * If the 3D object has no parent, then it's identical to the local transformation matrix
  208. *
  209. * @type {Matrix4}
  210. */
  211. this.matrixWorld = new Matrix4();
  212. /**
  213. * When set to `true`, the engine automatically computes the local matrix from position,
  214. * rotation and scale every frame.
  215. *
  216. * The default values for all 3D objects is defined by `Object3D.DEFAULT_MATRIX_AUTO_UPDATE`.
  217. *
  218. * @type {boolean}
  219. * @default true
  220. */
  221. this.matrixAutoUpdate = Object3D.DEFAULT_MATRIX_AUTO_UPDATE;
  222. /**
  223. * When set to `true`, the engine automatically computes the world matrix from the current local
  224. * matrix and the object's transformation hierarchy.
  225. *
  226. * The default values for all 3D objects is defined by `Object3D.DEFAULT_MATRIX_WORLD_AUTO_UPDATE`.
  227. *
  228. * @type {boolean}
  229. * @default true
  230. */
  231. this.matrixWorldAutoUpdate = Object3D.DEFAULT_MATRIX_WORLD_AUTO_UPDATE; // checked by the renderer
  232. /**
  233. * When set to `true`, it calculates the world matrix in that frame and resets this property
  234. * to `false`.
  235. *
  236. * @type {boolean}
  237. * @default false
  238. */
  239. this.matrixWorldNeedsUpdate = false;
  240. /**
  241. * The layer membership of the 3D object. The 3D object is only visible if it has
  242. * at least one layer in common with the camera in use. This property can also be
  243. * used to filter out unwanted objects in ray-intersection tests when using {@link Raycaster}.
  244. *
  245. * @type {Layers}
  246. */
  247. this.layers = new Layers();
  248. /**
  249. * When set to `true`, the 3D object gets rendered.
  250. *
  251. * @type {boolean}
  252. * @default true
  253. */
  254. this.visible = true;
  255. /**
  256. * When set to `true`, the 3D object gets rendered into shadow maps.
  257. *
  258. * @type {boolean}
  259. * @default false
  260. */
  261. this.castShadow = false;
  262. /**
  263. * When set to `true`, the 3D object is affected by shadows in the scene.
  264. *
  265. * @type {boolean}
  266. * @default false
  267. */
  268. this.receiveShadow = false;
  269. /**
  270. * When set to `true`, the 3D object is honored by view frustum culling.
  271. *
  272. * @type {boolean}
  273. * @default true
  274. */
  275. this.frustumCulled = true;
  276. /**
  277. * This value allows the default rendering order of scene graph objects to be
  278. * overridden although opaque and transparent objects remain sorted independently.
  279. * When this property is set for an instance of {@link Group},all descendants
  280. * objects will be sorted and rendered together. Sorting is from lowest to highest
  281. * render order.
  282. *
  283. * @type {number}
  284. * @default 0
  285. */
  286. this.renderOrder = 0;
  287. /**
  288. * An array holding the animation clips of the 3D object.
  289. *
  290. * @type {Array<AnimationClip>}
  291. */
  292. this.animations = [];
  293. /**
  294. * Custom depth material to be used when rendering to the depth map. Can only be used
  295. * in context of meshes. When shadow-casting with a {@link DirectionalLight} or {@link SpotLight},
  296. * if you are modifying vertex positions in the vertex shader you must specify a custom depth
  297. * material for proper shadows.
  298. *
  299. * Only relevant in context of {@link WebGLRenderer}.
  300. *
  301. * @type {(Material|undefined)}
  302. * @default undefined
  303. */
  304. this.customDepthMaterial = undefined;
  305. /**
  306. * Same as {@link Object3D#customDepthMaterial}, but used with {@link PointLight}.
  307. *
  308. * Only relevant in context of {@link WebGLRenderer}.
  309. *
  310. * @type {(Material|undefined)}
  311. * @default undefined
  312. */
  313. this.customDistanceMaterial = undefined;
  314. /**
  315. * An object that can be used to store custom data about the 3D object. It
  316. * should not hold references to functions as these will not be cloned.
  317. *
  318. * @type {Object}
  319. */
  320. this.userData = {};
  321. }
  322. /**
  323. * A callback that is executed immediately before a 3D object is rendered to a shadow map.
  324. *
  325. * @param {Renderer|WebGLRenderer} renderer - The renderer.
  326. * @param {Object3D} object - The 3D object.
  327. * @param {Camera} camera - The camera that is used to render the scene.
  328. * @param {Camera} shadowCamera - The shadow camera.
  329. * @param {BufferGeometry} geometry - The 3D object's geometry.
  330. * @param {Material} depthMaterial - The depth material.
  331. * @param {Object} group - The geometry group data.
  332. */
  333. onBeforeShadow( /* renderer, object, camera, shadowCamera, geometry, depthMaterial, group */ ) {}
  334. /**
  335. * A callback that is executed immediately after a 3D object is rendered to a shadow map.
  336. *
  337. * @param {Renderer|WebGLRenderer} renderer - The renderer.
  338. * @param {Object3D} object - The 3D object.
  339. * @param {Camera} camera - The camera that is used to render the scene.
  340. * @param {Camera} shadowCamera - The shadow camera.
  341. * @param {BufferGeometry} geometry - The 3D object's geometry.
  342. * @param {Material} depthMaterial - The depth material.
  343. * @param {Object} group - The geometry group data.
  344. */
  345. onAfterShadow( /* renderer, object, camera, shadowCamera, geometry, depthMaterial, group */ ) {}
  346. /**
  347. * A callback that is executed immediately before a 3D object is rendered.
  348. *
  349. * @param {Renderer|WebGLRenderer} renderer - The renderer.
  350. * @param {Object3D} object - The 3D object.
  351. * @param {Camera} camera - The camera that is used to render the scene.
  352. * @param {BufferGeometry} geometry - The 3D object's geometry.
  353. * @param {Material} material - The 3D object's material.
  354. * @param {Object} group - The geometry group data.
  355. */
  356. onBeforeRender( /* renderer, scene, camera, geometry, material, group */ ) {}
  357. /**
  358. * A callback that is executed immediately after a 3D object is rendered.
  359. *
  360. * @param {Renderer|WebGLRenderer} renderer - The renderer.
  361. * @param {Object3D} object - The 3D object.
  362. * @param {Camera} camera - The camera that is used to render the scene.
  363. * @param {BufferGeometry} geometry - The 3D object's geometry.
  364. * @param {Material} material - The 3D object's material.
  365. * @param {Object} group - The geometry group data.
  366. */
  367. onAfterRender( /* renderer, scene, camera, geometry, material, group */ ) {}
  368. /**
  369. * Applies the given transformation matrix to the object and updates the object's position,
  370. * rotation and scale.
  371. *
  372. * @param {Matrix4} matrix - The transformation matrix.
  373. */
  374. applyMatrix4( matrix ) {
  375. if ( this.matrixAutoUpdate ) this.updateMatrix();
  376. this.matrix.premultiply( matrix );
  377. this.matrix.decompose( this.position, this.quaternion, this.scale );
  378. }
  379. /**
  380. * Applies a rotation represented by given the quaternion to the 3D object.
  381. *
  382. * @param {Quaternion} q - The quaternion.
  383. * @return {Object3D} A reference to this instance.
  384. */
  385. applyQuaternion( q ) {
  386. this.quaternion.premultiply( q );
  387. return this;
  388. }
  389. /**
  390. * Sets the given rotation represented as an axis/angle couple to the 3D object.
  391. *
  392. * @param {Vector3} axis - The (normalized) axis vector.
  393. * @param {number} angle - The angle in radians.
  394. */
  395. setRotationFromAxisAngle( axis, angle ) {
  396. // assumes axis is normalized
  397. this.quaternion.setFromAxisAngle( axis, angle );
  398. }
  399. /**
  400. * Sets the given rotation represented as Euler angles to the 3D object.
  401. *
  402. * @param {Euler} euler - The Euler angles.
  403. */
  404. setRotationFromEuler( euler ) {
  405. this.quaternion.setFromEuler( euler, true );
  406. }
  407. /**
  408. * Sets the given rotation represented as rotation matrix to the 3D object.
  409. *
  410. * @param {Matrix4} m - Although a 4x4 matrix is expected, the upper 3x3 portion must be
  411. * a pure rotation matrix (i.e, unscaled).
  412. */
  413. setRotationFromMatrix( m ) {
  414. // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
  415. this.quaternion.setFromRotationMatrix( m );
  416. }
  417. /**
  418. * Sets the given rotation represented as a Quaternion to the 3D object.
  419. *
  420. * @param {Quaternion} q - The Quaternion
  421. */
  422. setRotationFromQuaternion( q ) {
  423. // assumes q is normalized
  424. this.quaternion.copy( q );
  425. }
  426. /**
  427. * Rotates the 3D object along an axis in local space.
  428. *
  429. * @param {Vector3} axis - The (normalized) axis vector.
  430. * @param {number} angle - The angle in radians.
  431. * @return {Object3D} A reference to this instance.
  432. */
  433. rotateOnAxis( axis, angle ) {
  434. // rotate object on axis in object space
  435. // axis is assumed to be normalized
  436. _q1.setFromAxisAngle( axis, angle );
  437. this.quaternion.multiply( _q1 );
  438. return this;
  439. }
  440. /**
  441. * Rotates the 3D object along an axis in world space.
  442. *
  443. * @param {Vector3} axis - The (normalized) axis vector.
  444. * @param {number} angle - The angle in radians.
  445. * @return {Object3D} A reference to this instance.
  446. */
  447. rotateOnWorldAxis( axis, angle ) {
  448. // rotate object on axis in world space
  449. // axis is assumed to be normalized
  450. // method assumes no rotated parent
  451. _q1.setFromAxisAngle( axis, angle );
  452. this.quaternion.premultiply( _q1 );
  453. return this;
  454. }
  455. /**
  456. * Rotates the 3D object around its X axis in local space.
  457. *
  458. * @param {number} angle - The angle in radians.
  459. * @return {Object3D} A reference to this instance.
  460. */
  461. rotateX( angle ) {
  462. return this.rotateOnAxis( _xAxis, angle );
  463. }
  464. /**
  465. * Rotates the 3D object around its Y axis in local space.
  466. *
  467. * @param {number} angle - The angle in radians.
  468. * @return {Object3D} A reference to this instance.
  469. */
  470. rotateY( angle ) {
  471. return this.rotateOnAxis( _yAxis, angle );
  472. }
  473. /**
  474. * Rotates the 3D object around its Z axis in local space.
  475. *
  476. * @param {number} angle - The angle in radians.
  477. * @return {Object3D} A reference to this instance.
  478. */
  479. rotateZ( angle ) {
  480. return this.rotateOnAxis( _zAxis, angle );
  481. }
  482. /**
  483. * Translate the 3D object by a distance along the given axis in local space.
  484. *
  485. * @param {Vector3} axis - The (normalized) axis vector.
  486. * @param {number} distance - The distance in world units.
  487. * @return {Object3D} A reference to this instance.
  488. */
  489. translateOnAxis( axis, distance ) {
  490. // translate object by distance along axis in object space
  491. // axis is assumed to be normalized
  492. _v1.copy( axis ).applyQuaternion( this.quaternion );
  493. this.position.add( _v1.multiplyScalar( distance ) );
  494. return this;
  495. }
  496. /**
  497. * Translate the 3D object by a distance along its X-axis in local space.
  498. *
  499. * @param {number} distance - The distance in world units.
  500. * @return {Object3D} A reference to this instance.
  501. */
  502. translateX( distance ) {
  503. return this.translateOnAxis( _xAxis, distance );
  504. }
  505. /**
  506. * Translate the 3D object by a distance along its Y-axis in local space.
  507. *
  508. * @param {number} distance - The distance in world units.
  509. * @return {Object3D} A reference to this instance.
  510. */
  511. translateY( distance ) {
  512. return this.translateOnAxis( _yAxis, distance );
  513. }
  514. /**
  515. * Translate the 3D object by a distance along its Z-axis in local space.
  516. *
  517. * @param {number} distance - The distance in world units.
  518. * @return {Object3D} A reference to this instance.
  519. */
  520. translateZ( distance ) {
  521. return this.translateOnAxis( _zAxis, distance );
  522. }
  523. /**
  524. * Converts the given vector from this 3D object's local space to world space.
  525. *
  526. * @param {Vector3} vector - The vector to convert.
  527. * @return {Vector3} The converted vector.
  528. */
  529. localToWorld( vector ) {
  530. this.updateWorldMatrix( true, false );
  531. return vector.applyMatrix4( this.matrixWorld );
  532. }
  533. /**
  534. * Converts the given vector from this 3D object's word space to local space.
  535. *
  536. * @param {Vector3} vector - The vector to convert.
  537. * @return {Vector3} The converted vector.
  538. */
  539. worldToLocal( vector ) {
  540. this.updateWorldMatrix( true, false );
  541. return vector.applyMatrix4( _m1.copy( this.matrixWorld ).invert() );
  542. }
  543. /**
  544. * Rotates the object to face a point in world space.
  545. *
  546. * This method does not support objects having non-uniformly-scaled parent(s).
  547. *
  548. * @param {number|Vector3} x - The x coordinate in world space. Alternatively, a vector representing a position in world space
  549. * @param {number} [y] - The y coordinate in world space.
  550. * @param {number} [z] - The z coordinate in world space.
  551. */
  552. lookAt( x, y, z ) {
  553. // This method does not support objects having non-uniformly-scaled parent(s)
  554. if ( x.isVector3 ) {
  555. _target.copy( x );
  556. } else {
  557. _target.set( x, y, z );
  558. }
  559. const parent = this.parent;
  560. this.updateWorldMatrix( true, false );
  561. _position.setFromMatrixPosition( this.matrixWorld );
  562. if ( this.isCamera || this.isLight ) {
  563. _m1.lookAt( _position, _target, this.up );
  564. } else {
  565. _m1.lookAt( _target, _position, this.up );
  566. }
  567. this.quaternion.setFromRotationMatrix( _m1 );
  568. if ( parent ) {
  569. _m1.extractRotation( parent.matrixWorld );
  570. _q1.setFromRotationMatrix( _m1 );
  571. this.quaternion.premultiply( _q1.invert() );
  572. }
  573. }
  574. /**
  575. * Adds the given 3D object as a child to this 3D object. An arbitrary number of
  576. * objects may be added. Any current parent on an object passed in here will be
  577. * removed, since an object can have at most one parent.
  578. *
  579. * @fires Object3D#added
  580. * @fires Object3D#childadded
  581. * @param {Object3D} object - The 3D object to add.
  582. * @return {Object3D} A reference to this instance.
  583. */
  584. add( object ) {
  585. if ( arguments.length > 1 ) {
  586. for ( let i = 0; i < arguments.length; i ++ ) {
  587. this.add( arguments[ i ] );
  588. }
  589. return this;
  590. }
  591. if ( object === this ) {
  592. error( 'Object3D.add: object can\'t be added as a child of itself.', object );
  593. return this;
  594. }
  595. if ( object && object.isObject3D ) {
  596. object.removeFromParent();
  597. object.parent = this;
  598. this.children.push( object );
  599. object.dispatchEvent( _addedEvent );
  600. _childaddedEvent.child = object;
  601. this.dispatchEvent( _childaddedEvent );
  602. _childaddedEvent.child = null;
  603. } else {
  604. error( 'Object3D.add: object not an instance of THREE.Object3D.', object );
  605. }
  606. return this;
  607. }
  608. /**
  609. * Removes the given 3D object as child from this 3D object.
  610. * An arbitrary number of objects may be removed.
  611. *
  612. * @fires Object3D#removed
  613. * @fires Object3D#childremoved
  614. * @param {Object3D} object - The 3D object to remove.
  615. * @return {Object3D} A reference to this instance.
  616. */
  617. remove( object ) {
  618. if ( arguments.length > 1 ) {
  619. for ( let i = 0; i < arguments.length; i ++ ) {
  620. this.remove( arguments[ i ] );
  621. }
  622. return this;
  623. }
  624. const index = this.children.indexOf( object );
  625. if ( index !== - 1 ) {
  626. object.parent = null;
  627. this.children.splice( index, 1 );
  628. object.dispatchEvent( _removedEvent );
  629. _childremovedEvent.child = object;
  630. this.dispatchEvent( _childremovedEvent );
  631. _childremovedEvent.child = null;
  632. }
  633. return this;
  634. }
  635. /**
  636. * Removes this 3D object from its current parent.
  637. *
  638. * @fires Object3D#removed
  639. * @fires Object3D#childremoved
  640. * @return {Object3D} A reference to this instance.
  641. */
  642. removeFromParent() {
  643. const parent = this.parent;
  644. if ( parent !== null ) {
  645. parent.remove( this );
  646. }
  647. return this;
  648. }
  649. /**
  650. * Removes all child objects.
  651. *
  652. * @fires Object3D#removed
  653. * @fires Object3D#childremoved
  654. * @return {Object3D} A reference to this instance.
  655. */
  656. clear() {
  657. return this.remove( ... this.children );
  658. }
  659. /**
  660. * Adds the given 3D object as a child of this 3D object, while maintaining the object's world
  661. * transform. This method does not support scene graphs having non-uniformly-scaled nodes(s).
  662. *
  663. * @fires Object3D#added
  664. * @fires Object3D#childadded
  665. * @param {Object3D} object - The 3D object to attach.
  666. * @return {Object3D} A reference to this instance.
  667. */
  668. attach( object ) {
  669. // adds object as a child of this, while maintaining the object's world transform
  670. // Note: This method does not support scene graphs having non-uniformly-scaled nodes(s)
  671. this.updateWorldMatrix( true, false );
  672. _m1.copy( this.matrixWorld ).invert();
  673. if ( object.parent !== null ) {
  674. object.parent.updateWorldMatrix( true, false );
  675. _m1.multiply( object.parent.matrixWorld );
  676. }
  677. object.applyMatrix4( _m1 );
  678. object.removeFromParent();
  679. object.parent = this;
  680. this.children.push( object );
  681. object.updateWorldMatrix( false, true );
  682. object.dispatchEvent( _addedEvent );
  683. _childaddedEvent.child = object;
  684. this.dispatchEvent( _childaddedEvent );
  685. _childaddedEvent.child = null;
  686. return this;
  687. }
  688. /**
  689. * Searches through the 3D object and its children, starting with the 3D object
  690. * itself, and returns the first with a matching ID.
  691. *
  692. * @param {number} id - The id.
  693. * @return {Object3D|undefined} The found 3D object. Returns `undefined` if no 3D object has been found.
  694. */
  695. getObjectById( id ) {
  696. return this.getObjectByProperty( 'id', id );
  697. }
  698. /**
  699. * Searches through the 3D object and its children, starting with the 3D object
  700. * itself, and returns the first with a matching name.
  701. *
  702. * @param {string} name - The name.
  703. * @return {Object3D|undefined} The found 3D object. Returns `undefined` if no 3D object has been found.
  704. */
  705. getObjectByName( name ) {
  706. return this.getObjectByProperty( 'name', name );
  707. }
  708. /**
  709. * Searches through the 3D object and its children, starting with the 3D object
  710. * itself, and returns the first with a matching property value.
  711. *
  712. * @param {string} name - The name of the property.
  713. * @param {any} value - The value.
  714. * @return {Object3D|undefined} The found 3D object. Returns `undefined` if no 3D object has been found.
  715. */
  716. getObjectByProperty( name, value ) {
  717. if ( this[ name ] === value ) return this;
  718. for ( let i = 0, l = this.children.length; i < l; i ++ ) {
  719. const child = this.children[ i ];
  720. const object = child.getObjectByProperty( name, value );
  721. if ( object !== undefined ) {
  722. return object;
  723. }
  724. }
  725. return undefined;
  726. }
  727. /**
  728. * Searches through the 3D object and its children, starting with the 3D object
  729. * itself, and returns all 3D objects with a matching property value.
  730. *
  731. * @param {string} name - The name of the property.
  732. * @param {any} value - The value.
  733. * @param {Array<Object3D>} result - The method stores the result in this array.
  734. * @return {Array<Object3D>} The found 3D objects.
  735. */
  736. getObjectsByProperty( name, value, result = [] ) {
  737. if ( this[ name ] === value ) result.push( this );
  738. const children = this.children;
  739. for ( let i = 0, l = children.length; i < l; i ++ ) {
  740. children[ i ].getObjectsByProperty( name, value, result );
  741. }
  742. return result;
  743. }
  744. /**
  745. * Returns a vector representing the position of the 3D object in world space.
  746. *
  747. * @param {Vector3} target - The target vector the result is stored to.
  748. * @return {Vector3} The 3D object's position in world space.
  749. */
  750. getWorldPosition( target ) {
  751. this.updateWorldMatrix( true, false );
  752. return target.setFromMatrixPosition( this.matrixWorld );
  753. }
  754. /**
  755. * Returns a Quaternion representing the position of the 3D object in world space.
  756. *
  757. * @param {Quaternion} target - The target Quaternion the result is stored to.
  758. * @return {Quaternion} The 3D object's rotation in world space.
  759. */
  760. getWorldQuaternion( target ) {
  761. this.updateWorldMatrix( true, false );
  762. this.matrixWorld.decompose( _position, target, _scale );
  763. return target;
  764. }
  765. /**
  766. * Returns a vector representing the scale of the 3D object in world space.
  767. *
  768. * @param {Vector3} target - The target vector the result is stored to.
  769. * @return {Vector3} The 3D object's scale in world space.
  770. */
  771. getWorldScale( target ) {
  772. this.updateWorldMatrix( true, false );
  773. this.matrixWorld.decompose( _position, _quaternion, target );
  774. return target;
  775. }
  776. /**
  777. * Returns a vector representing the ("look") direction of the 3D object in world space.
  778. *
  779. * @param {Vector3} target - The target vector the result is stored to.
  780. * @return {Vector3} The 3D object's direction in world space.
  781. */
  782. getWorldDirection( target ) {
  783. this.updateWorldMatrix( true, false );
  784. const e = this.matrixWorld.elements;
  785. return target.set( e[ 8 ], e[ 9 ], e[ 10 ] ).normalize();
  786. }
  787. /**
  788. * Abstract method to get intersections between a casted ray and this
  789. * 3D object. Renderable 3D objects such as {@link Mesh}, {@link Line} or {@link Points}
  790. * implement this method in order to use raycasting.
  791. *
  792. * @abstract
  793. * @param {Raycaster} raycaster - The raycaster.
  794. * @param {Array<Object>} intersects - An array holding the result of the method.
  795. */
  796. raycast( /* raycaster, intersects */ ) {}
  797. /**
  798. * Executes the callback on this 3D object and all descendants.
  799. *
  800. * Note: Modifying the scene graph inside the callback is discouraged.
  801. *
  802. * @param {Function} callback - A callback function that allows to process the current 3D object.
  803. */
  804. traverse( callback ) {
  805. callback( this );
  806. const children = this.children;
  807. for ( let i = 0, l = children.length; i < l; i ++ ) {
  808. children[ i ].traverse( callback );
  809. }
  810. }
  811. /**
  812. * Like {@link Object3D#traverse}, but the callback will only be executed for visible 3D objects.
  813. * Descendants of invisible 3D objects are not traversed.
  814. *
  815. * Note: Modifying the scene graph inside the callback is discouraged.
  816. *
  817. * @param {Function} callback - A callback function that allows to process the current 3D object.
  818. */
  819. traverseVisible( callback ) {
  820. if ( this.visible === false ) return;
  821. callback( this );
  822. const children = this.children;
  823. for ( let i = 0, l = children.length; i < l; i ++ ) {
  824. children[ i ].traverseVisible( callback );
  825. }
  826. }
  827. /**
  828. * Like {@link Object3D#traverse}, but the callback will only be executed for all ancestors.
  829. *
  830. * Note: Modifying the scene graph inside the callback is discouraged.
  831. *
  832. * @param {Function} callback - A callback function that allows to process the current 3D object.
  833. */
  834. traverseAncestors( callback ) {
  835. const parent = this.parent;
  836. if ( parent !== null ) {
  837. callback( parent );
  838. parent.traverseAncestors( callback );
  839. }
  840. }
  841. /**
  842. * Updates the transformation matrix in local space by computing it from the current
  843. * position, rotation and scale values.
  844. */
  845. updateMatrix() {
  846. this.matrix.compose( this.position, this.quaternion, this.scale );
  847. this.matrixWorldNeedsUpdate = true;
  848. }
  849. /**
  850. * Updates the transformation matrix in world space of this 3D objects and its descendants.
  851. *
  852. * To ensure correct results, this method also recomputes the 3D object's transformation matrix in
  853. * local space. The computation of the local and world matrix can be controlled with the
  854. * {@link Object3D#matrixAutoUpdate} and {@link Object3D#matrixWorldAutoUpdate} flags which are both
  855. * `true` by default. Set these flags to `false` if you need more control over the update matrix process.
  856. *
  857. * @param {boolean} [force=false] - When set to `true`, a recomputation of world matrices is forced even
  858. * when {@link Object3D#matrixWorldAutoUpdate} is set to `false`.
  859. */
  860. updateMatrixWorld( force ) {
  861. if ( this.matrixAutoUpdate ) this.updateMatrix();
  862. if ( this.matrixWorldNeedsUpdate || force ) {
  863. if ( this.matrixWorldAutoUpdate === true ) {
  864. if ( this.parent === null ) {
  865. this.matrixWorld.copy( this.matrix );
  866. } else {
  867. this.matrixWorld.multiplyMatrices( this.parent.matrixWorld, this.matrix );
  868. }
  869. }
  870. this.matrixWorldNeedsUpdate = false;
  871. force = true;
  872. }
  873. // make sure descendants are updated if required
  874. const children = this.children;
  875. for ( let i = 0, l = children.length; i < l; i ++ ) {
  876. const child = children[ i ];
  877. child.updateMatrixWorld( force );
  878. }
  879. }
  880. /**
  881. * An alternative version of {@link Object3D#updateMatrixWorld} with more control over the
  882. * update of ancestor and descendant nodes.
  883. *
  884. * @param {boolean} [updateParents=false] Whether ancestor nodes should be updated or not.
  885. * @param {boolean} [updateChildren=false] Whether descendant nodes should be updated or not.
  886. */
  887. updateWorldMatrix( updateParents, updateChildren ) {
  888. const parent = this.parent;
  889. if ( updateParents === true && parent !== null ) {
  890. parent.updateWorldMatrix( true, false );
  891. }
  892. if ( this.matrixAutoUpdate ) this.updateMatrix();
  893. if ( this.matrixWorldAutoUpdate === true ) {
  894. if ( this.parent === null ) {
  895. this.matrixWorld.copy( this.matrix );
  896. } else {
  897. this.matrixWorld.multiplyMatrices( this.parent.matrixWorld, this.matrix );
  898. }
  899. }
  900. // make sure descendants are updated
  901. if ( updateChildren === true ) {
  902. const children = this.children;
  903. for ( let i = 0, l = children.length; i < l; i ++ ) {
  904. const child = children[ i ];
  905. child.updateWorldMatrix( false, true );
  906. }
  907. }
  908. }
  909. /**
  910. * Serializes the 3D object into JSON.
  911. *
  912. * @param {?(Object|string)} meta - An optional value holding meta information about the serialization.
  913. * @return {Object} A JSON object representing the serialized 3D object.
  914. * @see {@link ObjectLoader#parse}
  915. */
  916. toJSON( meta ) {
  917. // meta is a string when called from JSON.stringify
  918. const isRootObject = ( meta === undefined || typeof meta === 'string' );
  919. const output = {};
  920. // meta is a hash used to collect geometries, materials.
  921. // not providing it implies that this is the root object
  922. // being serialized.
  923. if ( isRootObject ) {
  924. // initialize meta obj
  925. meta = {
  926. geometries: {},
  927. materials: {},
  928. textures: {},
  929. images: {},
  930. shapes: {},
  931. skeletons: {},
  932. animations: {},
  933. nodes: {}
  934. };
  935. output.metadata = {
  936. version: 4.7,
  937. type: 'Object',
  938. generator: 'Object3D.toJSON'
  939. };
  940. }
  941. // standard Object3D serialization
  942. const object = {};
  943. object.uuid = this.uuid;
  944. object.type = this.type;
  945. if ( this.name !== '' ) object.name = this.name;
  946. if ( this.castShadow === true ) object.castShadow = true;
  947. if ( this.receiveShadow === true ) object.receiveShadow = true;
  948. if ( this.visible === false ) object.visible = false;
  949. if ( this.frustumCulled === false ) object.frustumCulled = false;
  950. if ( this.renderOrder !== 0 ) object.renderOrder = this.renderOrder;
  951. if ( Object.keys( this.userData ).length > 0 ) object.userData = this.userData;
  952. object.layers = this.layers.mask;
  953. object.matrix = this.matrix.toArray();
  954. object.up = this.up.toArray();
  955. if ( this.matrixAutoUpdate === false ) object.matrixAutoUpdate = false;
  956. // object specific properties
  957. if ( this.isInstancedMesh ) {
  958. object.type = 'InstancedMesh';
  959. object.count = this.count;
  960. object.instanceMatrix = this.instanceMatrix.toJSON();
  961. if ( this.instanceColor !== null ) object.instanceColor = this.instanceColor.toJSON();
  962. }
  963. if ( this.isBatchedMesh ) {
  964. object.type = 'BatchedMesh';
  965. object.perObjectFrustumCulled = this.perObjectFrustumCulled;
  966. object.sortObjects = this.sortObjects;
  967. object.drawRanges = this._drawRanges;
  968. object.reservedRanges = this._reservedRanges;
  969. object.geometryInfo = this._geometryInfo.map( info => ( {
  970. ...info,
  971. boundingBox: info.boundingBox ? info.boundingBox.toJSON() : undefined,
  972. boundingSphere: info.boundingSphere ? info.boundingSphere.toJSON() : undefined
  973. } ) );
  974. object.instanceInfo = this._instanceInfo.map( info => ( { ...info } ) );
  975. object.availableInstanceIds = this._availableInstanceIds.slice();
  976. object.availableGeometryIds = this._availableGeometryIds.slice();
  977. object.nextIndexStart = this._nextIndexStart;
  978. object.nextVertexStart = this._nextVertexStart;
  979. object.geometryCount = this._geometryCount;
  980. object.maxInstanceCount = this._maxInstanceCount;
  981. object.maxVertexCount = this._maxVertexCount;
  982. object.maxIndexCount = this._maxIndexCount;
  983. object.geometryInitialized = this._geometryInitialized;
  984. object.matricesTexture = this._matricesTexture.toJSON( meta );
  985. object.indirectTexture = this._indirectTexture.toJSON( meta );
  986. if ( this._colorsTexture !== null ) {
  987. object.colorsTexture = this._colorsTexture.toJSON( meta );
  988. }
  989. if ( this.boundingSphere !== null ) {
  990. object.boundingSphere = this.boundingSphere.toJSON();
  991. }
  992. if ( this.boundingBox !== null ) {
  993. object.boundingBox = this.boundingBox.toJSON();
  994. }
  995. }
  996. //
  997. function serialize( library, element ) {
  998. if ( library[ element.uuid ] === undefined ) {
  999. library[ element.uuid ] = element.toJSON( meta );
  1000. }
  1001. return element.uuid;
  1002. }
  1003. if ( this.isScene ) {
  1004. if ( this.background ) {
  1005. if ( this.background.isColor ) {
  1006. object.background = this.background.toJSON();
  1007. } else if ( this.background.isTexture ) {
  1008. object.background = this.background.toJSON( meta ).uuid;
  1009. }
  1010. }
  1011. if ( this.environment && this.environment.isTexture && this.environment.isRenderTargetTexture !== true ) {
  1012. object.environment = this.environment.toJSON( meta ).uuid;
  1013. }
  1014. } else if ( this.isMesh || this.isLine || this.isPoints ) {
  1015. object.geometry = serialize( meta.geometries, this.geometry );
  1016. const parameters = this.geometry.parameters;
  1017. if ( parameters !== undefined && parameters.shapes !== undefined ) {
  1018. const shapes = parameters.shapes;
  1019. if ( Array.isArray( shapes ) ) {
  1020. for ( let i = 0, l = shapes.length; i < l; i ++ ) {
  1021. const shape = shapes[ i ];
  1022. serialize( meta.shapes, shape );
  1023. }
  1024. } else {
  1025. serialize( meta.shapes, shapes );
  1026. }
  1027. }
  1028. }
  1029. if ( this.isSkinnedMesh ) {
  1030. object.bindMode = this.bindMode;
  1031. object.bindMatrix = this.bindMatrix.toArray();
  1032. if ( this.skeleton !== undefined ) {
  1033. serialize( meta.skeletons, this.skeleton );
  1034. object.skeleton = this.skeleton.uuid;
  1035. }
  1036. }
  1037. if ( this.material !== undefined ) {
  1038. if ( Array.isArray( this.material ) ) {
  1039. const uuids = [];
  1040. for ( let i = 0, l = this.material.length; i < l; i ++ ) {
  1041. uuids.push( serialize( meta.materials, this.material[ i ] ) );
  1042. }
  1043. object.material = uuids;
  1044. } else {
  1045. object.material = serialize( meta.materials, this.material );
  1046. }
  1047. }
  1048. //
  1049. if ( this.children.length > 0 ) {
  1050. object.children = [];
  1051. for ( let i = 0; i < this.children.length; i ++ ) {
  1052. object.children.push( this.children[ i ].toJSON( meta ).object );
  1053. }
  1054. }
  1055. //
  1056. if ( this.animations.length > 0 ) {
  1057. object.animations = [];
  1058. for ( let i = 0; i < this.animations.length; i ++ ) {
  1059. const animation = this.animations[ i ];
  1060. object.animations.push( serialize( meta.animations, animation ) );
  1061. }
  1062. }
  1063. if ( isRootObject ) {
  1064. const geometries = extractFromCache( meta.geometries );
  1065. const materials = extractFromCache( meta.materials );
  1066. const textures = extractFromCache( meta.textures );
  1067. const images = extractFromCache( meta.images );
  1068. const shapes = extractFromCache( meta.shapes );
  1069. const skeletons = extractFromCache( meta.skeletons );
  1070. const animations = extractFromCache( meta.animations );
  1071. const nodes = extractFromCache( meta.nodes );
  1072. if ( geometries.length > 0 ) output.geometries = geometries;
  1073. if ( materials.length > 0 ) output.materials = materials;
  1074. if ( textures.length > 0 ) output.textures = textures;
  1075. if ( images.length > 0 ) output.images = images;
  1076. if ( shapes.length > 0 ) output.shapes = shapes;
  1077. if ( skeletons.length > 0 ) output.skeletons = skeletons;
  1078. if ( animations.length > 0 ) output.animations = animations;
  1079. if ( nodes.length > 0 ) output.nodes = nodes;
  1080. }
  1081. output.object = object;
  1082. return output;
  1083. // extract data from the cache hash
  1084. // remove metadata on each item
  1085. // and return as array
  1086. function extractFromCache( cache ) {
  1087. const values = [];
  1088. for ( const key in cache ) {
  1089. const data = cache[ key ];
  1090. delete data.metadata;
  1091. values.push( data );
  1092. }
  1093. return values;
  1094. }
  1095. }
  1096. /**
  1097. * Returns a new 3D object with copied values from this instance.
  1098. *
  1099. * @param {boolean} [recursive=true] - When set to `true`, descendants of the 3D object are also cloned.
  1100. * @return {Object3D} A clone of this instance.
  1101. */
  1102. clone( recursive ) {
  1103. return new this.constructor().copy( this, recursive );
  1104. }
  1105. /**
  1106. * Copies the values of the given 3D object to this instance.
  1107. *
  1108. * @param {Object3D} source - The 3D object to copy.
  1109. * @param {boolean} [recursive=true] - When set to `true`, descendants of the 3D object are cloned.
  1110. * @return {Object3D} A reference to this instance.
  1111. */
  1112. copy( source, recursive = true ) {
  1113. this.name = source.name;
  1114. this.up.copy( source.up );
  1115. this.position.copy( source.position );
  1116. this.rotation.order = source.rotation.order;
  1117. this.quaternion.copy( source.quaternion );
  1118. this.scale.copy( source.scale );
  1119. this.matrix.copy( source.matrix );
  1120. this.matrixWorld.copy( source.matrixWorld );
  1121. this.matrixAutoUpdate = source.matrixAutoUpdate;
  1122. this.matrixWorldAutoUpdate = source.matrixWorldAutoUpdate;
  1123. this.matrixWorldNeedsUpdate = source.matrixWorldNeedsUpdate;
  1124. this.layers.mask = source.layers.mask;
  1125. this.visible = source.visible;
  1126. this.castShadow = source.castShadow;
  1127. this.receiveShadow = source.receiveShadow;
  1128. this.frustumCulled = source.frustumCulled;
  1129. this.renderOrder = source.renderOrder;
  1130. this.animations = source.animations.slice();
  1131. this.userData = JSON.parse( JSON.stringify( source.userData ) );
  1132. if ( recursive === true ) {
  1133. for ( let i = 0; i < source.children.length; i ++ ) {
  1134. const child = source.children[ i ];
  1135. this.add( child.clone() );
  1136. }
  1137. }
  1138. return this;
  1139. }
  1140. }
  1141. /**
  1142. * The default up direction for objects, also used as the default
  1143. * position for {@link DirectionalLight} and {@link HemisphereLight}.
  1144. *
  1145. * @static
  1146. * @type {Vector3}
  1147. * @default (0,1,0)
  1148. */
  1149. Object3D.DEFAULT_UP = /*@__PURE__*/ new Vector3( 0, 1, 0 );
  1150. /**
  1151. * The default setting for {@link Object3D#matrixAutoUpdate} for
  1152. * newly created 3D objects.
  1153. *
  1154. * @static
  1155. * @type {boolean}
  1156. * @default true
  1157. */
  1158. Object3D.DEFAULT_MATRIX_AUTO_UPDATE = true;
  1159. /**
  1160. * The default setting for {@link Object3D#matrixWorldAutoUpdate} for
  1161. * newly created 3D objects.
  1162. *
  1163. * @static
  1164. * @type {boolean}
  1165. * @default true
  1166. */
  1167. Object3D.DEFAULT_MATRIX_WORLD_AUTO_UPDATE = true;
  1168. export { Object3D };
粤ICP备19079148号