123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862 |
- 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 {
- _Math
- } from '../math/Math.js';
- /**
- * @author mrdoob / http://mrdoob.com/
- * @author mikael emtinger / http://gomo.se/
- * @author alteredq / http://alteredqualia.com/
- * @author WestLangley / http://github.com/WestLangley
- * @author elephantatwork / www.elephantatwork.ch
- */
- //局部的全局变量
- var object3DId = 0;
- function Object3D() {
- // 每次执行该构造函数创建对象的时候,都会给该对象设置一个id属性,并且他一个全局变量加1赋值给id属性
- Object.defineProperty(this, 'id', {
- value: object3DId++
- });
- // generate :生成
- this.uuid = _Math.generateUUID();
- this.name = '';
- this.type = 'Object3D';
- this.parent = null;
- this.children = [];
- this.up = Object3D.DefaultUp.clone();
- var position = new Vector3();
- var rotation = new Euler();
- var quaternion = new Quaternion();
- var 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, {
- position: {
- enumerable: true,
- value: position
- },
- rotation: {
- enumerable: true,
- value: rotation
- },
- quaternion: {
- enumerable: true,
- value: quaternion
- },
- scale: {
- enumerable: true,
- value: scale
- },
- modelViewMatrix: {
- value: new Matrix4()
- },
- normalMatrix: {
- value: new Matrix3()
- }
- });
- this.matrix = new Matrix4();
- this.matrixWorld = new Matrix4();
- this.matrixAutoUpdate = Object3D.DefaultMatrixAutoUpdate;
- this.matrixWorldNeedsUpdate = false;
- // 创建obj3对象的时候,已经默认创建Layers,并且带对象创建的时候默认相当于初始化执行set(0)
- this.layers = new Layers();
- this.visible = true;
- this.castShadow = false;
- this.receiveShadow = false;
- this.frustumCulled = true;
- this.renderOrder = 0;
- this.userData = {};
- }
- Object3D.DefaultUp = new Vector3(0, 1, 0);
- Object3D.DefaultMatrixAutoUpdate = true;
- Object3D.prototype = Object.assign(Object.create(EventDispatcher.prototype), {
- constructor: Object3D,
- isObject3D: true,
- onBeforeRender: function() {},
- onAfterRender: function() {},
- applyMatrix: function(matrix) {
- this.matrix.multiplyMatrices(matrix, this.matrix);
- this.matrix.decompose(this.position, this.quaternion, this.scale);
- },
- applyQuaternion: function(q) {
- this.quaternion.premultiply(q);
- return this;
- },
- setRotationFromAxisAngle: function(axis, angle) {
- // assumes axis is normalized
- this.quaternion.setFromAxisAngle(axis, angle);
- },
- setRotationFromEuler: function(euler) {
- this.quaternion.setFromEuler(euler, true);
- },
- setRotationFromMatrix: function(m) {
- // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
- this.quaternion.setFromRotationMatrix(m);
- },
- setRotationFromQuaternion: function(q) {
- // assumes q is normalized
- this.quaternion.copy(q);
- },
- rotateOnAxis: function() {
- // rotate object on axis in object space
- // axis is assumed to be normalized
- var q1 = new Quaternion();
- return function rotateOnAxis(axis, angle) {
- q1.setFromAxisAngle(axis, angle);
- this.quaternion.multiply(q1);
- return this;
- };
- }(),
- rotateOnWorldAxis: function() {
- // rotate object on axis in world space
- // axis is assumed to be normalized
- // method assumes no rotated parent
- var q1 = new Quaternion();
- return function rotateOnWorldAxis(axis, angle) {
- q1.setFromAxisAngle(axis, angle);
- this.quaternion.premultiply(q1);
- return this;
- };
- }(),
- rotateX: function() {
- var v1 = new Vector3(1, 0, 0);
- return function rotateX(angle) {
- return this.rotateOnAxis(v1, angle);
- };
- }(),
- rotateY: function() {
- var v1 = new Vector3(0, 1, 0);
- return function rotateY(angle) {
- return this.rotateOnAxis(v1, angle);
- };
- }(),
- rotateZ: function() {
- var v1 = new Vector3(0, 0, 1);
- return function rotateZ(angle) {
- return this.rotateOnAxis(v1, angle);
- };
- }(),
- translateOnAxis: function() {
- // translate object by distance along axis in object space
- // axis is assumed to be normalized
- var v1 = new Vector3();
- return function translateOnAxis(axis, distance) {
- v1.copy(axis).applyQuaternion(this.quaternion);
- this.position.add(v1.multiplyScalar(distance));
- return this;
- };
- }(),
- translateX: function() {
- var v1 = new Vector3(1, 0, 0);
- return function translateX(distance) {
- return this.translateOnAxis(v1, distance);
- };
- }(),
- translateY: function() {
- var v1 = new Vector3(0, 1, 0);
- return function translateY(distance) {
- return this.translateOnAxis(v1, distance);
- };
- }(),
- translateZ: function() {
- var v1 = new Vector3(0, 0, 1);
- return function translateZ(distance) {
- return this.translateOnAxis(v1, distance);
- };
- }(),
- localToWorld: function(vector) {
- return vector.applyMatrix4(this.matrixWorld);
- },
- worldToLocal: function() {
- var m1 = new Matrix4();
- return function worldToLocal(vector) {
- return vector.applyMatrix4(m1.getInverse(this.matrixWorld));
- };
- }(),
- lookAt: function() {
- // This method does not support objects with rotated and/or translated parent(s)
- var m1 = new Matrix4();
- var vector = new Vector3();
- // 参数可以是一个向量,也可以是向量的三个分量
- return function lookAt(x, y, z) {
- // 判断x是不是向量v3,如果是,说明程序员使用的是三维向量
- if (x.isVector3) {
- vector.copy(x);
- } else {
- vector.set(x, y, z);
- }
- if (this.isCamera) {
- m1.lookAt(this.position, vector, this.up);
- } else {
- m1.lookAt(vector, this.position, this.up);
- }
- this.quaternion.setFromRotationMatrix(m1);
- };
- }(),
- add: function(object) {
- if (arguments.length > 1) {
- for (var i = 0; i < arguments.length; i++) {
- this.add(arguments[i]);
- }
- return this;
- }
- if (object === this) {
- console.error("THREE.Object3D.add: object can't be added as a child of itself.", object);
- return this;
- }
- if ((object && object.isObject3D)) {
- if (object.parent !== null) {
- object.parent.remove(object);
- }
- object.parent = this;
- object.dispatchEvent({
- type: 'added'
- });
- this.children.push(object);
- } else {
- console.error("THREE.Object3D.add: object not an instance of THREE.Object3D.", object);
- }
- return this;
- },
- // 参数:.remove ( object : Object3D, ... )
- // 将对象作为对象的子对象移除。可以删除任意数量的对象。
- remove: function(object) {
- // arguments对象表示所有参数组成的数组
- if (arguments.length > 1) {
- // 循环遍历 每一个参数对象执行remove删除方法
- for (var i = 0; i < arguments.length; i++) {
- this.remove(arguments[i]);
- }
- return this;
- }
- // 获得object在children数组中的索引
- var index = this.children.indexOf(object);
- if (index !== -1) {
- // 设置object的父对象属性parent为null空
- object.parent = null;
- object.dispatchEvent({
- type: 'removed'
- });
- // 删除children数组中索引是index的元素
- this.children.splice(index, 1);
- }
- return this;
- },
- // 通过id获得对象
- getObjectById: function(id) {
- // 浏览器通过id选择的生层原理
- return this.getObjectByProperty('id', id);
- },
- getObjectByName: function(name) {
- return this.getObjectByProperty('name', name);
- },
- getObjectByProperty: function(name, value) {
- if (this[name] === value) return this;
- for (var i = 0, l = this.children.length; i < l; i++) {
- var child = this.children[i];
- var object = child.getObjectByProperty(name, value);
- if (object !== undefined) {
- return object;
- }
- }
- return undefined;
- },
- getWorldPosition: function(target) {
- if (target === undefined) {
- console.warn('THREE.Object3D: .getWorldPosition() target is now required');
- target = new Vector3();
- }
- this.updateMatrixWorld(true);
- return target.setFromMatrixPosition(this.matrixWorld);
- },
- getWorldQuaternion: function() {
- var position = new Vector3();
- var scale = new Vector3();
- return function getWorldQuaternion(target) {
- if (target === undefined) {
- console.warn('THREE.Object3D: .getWorldQuaternion() target is now required');
- target = new Quaternion();
- }
- this.updateMatrixWorld(true);
- this.matrixWorld.decompose(position, target, scale);
- return target;
- };
- }(),
- getWorldScale: function() {
- var position = new Vector3();
- var quaternion = new Quaternion();
- return function getWorldScale(target) {
- if (target === undefined) {
- console.warn('THREE.Object3D: .getWorldScale() target is now required');
- target = new Vector3();
- }
- this.updateMatrixWorld(true);
- this.matrixWorld.decompose(position, quaternion, target);
- return target;
- };
- }(),
- getWorldDirection: function() {
- var quaternion = new Quaternion();
- return function getWorldDirection(target) {
- if (target === undefined) {
- console.warn('THREE.Object3D: .getWorldDirection() target is now required');
- target = new Vector3();
- }
- this.getWorldQuaternion(quaternion);
- return target.set(0, 0, 1).applyQuaternion(quaternion);
- };
- }(),
- raycast: function() {},
- traverse: function(callback) {
- callback(this);
- var children = this.children;
- for (var i = 0, l = children.length; i < l; i++) {
- children[i].traverse(callback);
- }
- },
- traverseVisible: function(callback) {
- if (this.visible === false) return;
- callback(this);
- var children = this.children;
- for (var i = 0, l = children.length; i < l; i++) {
- children[i].traverseVisible(callback);
- }
- },
- traverseAncestors: function(callback) {
- var parent = this.parent;
- if (parent !== null) {
- callback(parent);
- parent.traverseAncestors(callback);
- }
- },
- updateMatrix: function() {
- this.matrix.compose(this.position, this.quaternion, this.scale);
- this.matrixWorldNeedsUpdate = true;
- },
- updateMatrixWorld: function(force) {
- if (this.matrixAutoUpdate) this.updateMatrix();
- if (this.matrixWorldNeedsUpdate || force) {
- if (this.parent === null) {
- this.matrixWorld.copy(this.matrix);
- } else {
- this.matrixWorld.multiplyMatrices(this.parent.matrixWorld, this.matrix);
- }
- this.matrixWorldNeedsUpdate = false;
- force = true;
- }
- // update children
- var children = this.children;
- for (var i = 0, l = children.length; i < l; i++) {
- children[i].updateMatrixWorld(force);
- }
- },
- toJSON: function(meta) {
- // meta is a string when called from JSON.stringify
- var isRootObject = (meta === undefined || typeof meta === 'string');
- var 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: {}
- };
- output.metadata = {
- version: 4.5,
- type: 'Object',
- generator: 'Object3D.toJSON'
- };
- }
- // standard Object3D serialization
- var 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 (JSON.stringify(this.userData) !== '{}') object.userData = this.userData;
- object.matrix = this.matrix.toArray();
- //
- function serialize(library, element) {
- if (library[element.uuid] === undefined) {
- library[element.uuid] = element.toJSON(meta);
- }
- return element.uuid;
- }
- if (this.geometry !== undefined) {
- object.geometry = serialize(meta.geometries, this.geometry);
- var parameters = this.geometry.parameters;
- if (parameters !== undefined && parameters.shapes !== undefined) {
- var shapes = parameters.shapes;
- if (Array.isArray(shapes)) {
- for (var i = 0, l = shapes.length; i < l; i++) {
- var shape = shapes[i];
- serialize(meta.shapes, shape);
- }
- } else {
- serialize(meta.shapes, shapes);
- }
- }
- }
- if (this.material !== undefined) {
- if (Array.isArray(this.material)) {
- var uuids = [];
- for (var 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 (var i = 0; i < this.children.length; i++) {
- object.children.push(this.children[i].toJSON(meta).object);
- }
- }
- if (isRootObject) {
- var geometries = extractFromCache(meta.geometries);
- var materials = extractFromCache(meta.materials);
- var textures = extractFromCache(meta.textures);
- var images = extractFromCache(meta.images);
- var shapes = extractFromCache(meta.shapes);
- 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;
- }
- output.object = object;
- return output;
- // extract data from the cache hash
- // remove metadata on each item
- // and return as array
- function extractFromCache(cache) {
- var values = [];
- for (var key in cache) {
- var data = cache[key];
- delete data.metadata;
- values.push(data);
- }
- return values;
- }
- },
- clone: function(recursive) {
- return new this.constructor().copy(this, recursive);
- },
- copy: function(source, recursive) {
- if (recursive === undefined) recursive = true;
- this.name = source.name;
- this.up.copy(source.up);
- this.position.copy(source.position);
- this.quaternion.copy(source.quaternion);
- this.scale.copy(source.scale);
- this.matrix.copy(source.matrix);
- this.matrixWorld.copy(source.matrixWorld);
- this.matrixAutoUpdate = source.matrixAutoUpdate;
- this.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.userData = JSON.parse(JSON.stringify(source.userData));
- if (recursive === true) {
- for (var i = 0; i < source.children.length; i++) {
- var child = source.children[i];
- this.add(child.clone());
- }
- }
- return this;
- }
- });
- export {
- Object3D
- };
|