├── .idea └── .name ├── renderers ├── shaders │ ├── ShaderChunk.js │ ├── UniformsUtils.js │ └── UniformsLib.js ├── WebGLRenderTargetCube.js ├── webgl │ ├── WebGLShader.js │ └── WebGLExtensions.js └── WebGLRenderTarget.js ├── README.md ├── core ├── Face4.js ├── Projector.js ├── Clock.js ├── Face3.js ├── EventDispatcher.js ├── Raycaster.js └── BufferAttribute.js ├── objects ├── Group.js ├── Bone.js ├── Sprite.js ├── LensFlare.js ├── LOD.js ├── Line.js ├── PointCloud.js ├── SkinnedMesh.js ├── Skeleton.js └── MorphAnimMesh.js ├── extras ├── objects │ └── ImmediateRenderObject.js ├── GeometryUtils.js ├── SceneUtils.js └── ImageUtils.js ├── lights ├── AmbientLight.js ├── Light.js ├── PointLight.js ├── HemisphereLight.js ├── AreaLight.js ├── SpotLight.js └── DirectionalLight.js ├── scenes ├── FogExp2.js ├── Fog.js └── Scene.js ├── materials ├── RawShaderMaterial.js ├── MeshFaceMaterial.js ├── SpriteMaterial.js ├── MeshDepthMaterial.js ├── MeshNormalMaterial.js ├── LineBasicMaterial.js ├── LineDashedMaterial.js ├── PointCloudMaterial.js ├── ShaderMaterial.js ├── MeshBasicMaterial.js ├── MeshLambertMaterial.js └── MeshPhongMaterial.js ├── textures ├── VideoTexture.js ├── CubeTexture.js ├── DataTexture.js └── CompressedTexture.js ├── cameras ├── Camera.js ├── OrthographicCamera.js ├── CubeCamera.js └── PerspectiveCamera.js └── math ├── Line3.js ├── Sphere.js ├── Math.js ├── Spline.js ├── Frustum.js ├── Triangle.js ├── Box2.js └── Plane.js /.idea/.name: -------------------------------------------------------------------------------- 1 | ThreeJS-Notes -------------------------------------------------------------------------------- /renderers/shaders/ShaderChunk.js: -------------------------------------------------------------------------------- 1 | THREE.ShaderChunk = {}; 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ThreeJS-Notes 2 | 对ThreeJS的中文注释,可以使用JSDOC可以自动生成说明文档 3 | 部分内容参照omni360同学已经写过的注释,https://github.com/omni360/three.js.sourcecode 4 | 5 | -------------------------------------------------------------------------------- /core/Face4.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author mrdoob / http://mrdoob.com/ 3 | */ 4 | /** 5 | * @classdesc 四角面对象类(四维空间内) 6 | * @ignore 7 | */ 8 | THREE.Face4 = function ( a, b, c, d, normal, color, materialIndex ) { 9 | 10 | console.warn( 'THREE.Face4 has been removed. A THREE.Face3 will be created instead.' ) 11 | return new THREE.Face3( a, b, c, normal, color, materialIndex ); 12 | 13 | }; 14 | -------------------------------------------------------------------------------- /objects/Group.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author mrdoob / http://mrdoob.com/ 3 | */ 4 | /** 5 | * @classdesc 对象组 6 | * @constructor 7 | */ 8 | THREE.Group = function () { 9 | 10 | THREE.Object3D.call( this ); 11 | 12 | this.type = 'Group'; 13 | 14 | }; 15 | /** 16 | * @desc Group从Object3D的原型继承所有属性方法 17 | * @type {THREE.Object3D} 18 | */ 19 | THREE.Group.prototype = Object.create( THREE.Object3D.prototype ); 20 | -------------------------------------------------------------------------------- /extras/objects/ImmediateRenderObject.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author alteredq / http://alteredqualia.com/ 3 | */ 4 | /** 5 | * @classdesc 即时渲染对象
6 | * 注释内容部分参照 http://blog.csdn.net/omni360 7 | * @constructor 8 | */ 9 | THREE.ImmediateRenderObject = function () { 10 | 11 | THREE.Object3D.call( this ); 12 | 13 | this.render = function ( renderCallback ) {}; 14 | 15 | }; 16 | /** 17 | * @desc ImmediateRenderObject从Object3D的原型继承所有属性方法 18 | * @type {THREE.Object3D} 19 | */ 20 | THREE.ImmediateRenderObject.prototype = Object.create( THREE.Object3D.prototype ); 21 | -------------------------------------------------------------------------------- /objects/Bone.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author mikael emtinger / http://gomo.se/ 3 | * @author alteredq / http://alteredqualia.com/ 4 | * @author ikerr / http://verold.com 5 | */ 6 | /** 7 | * @classdesc 骨骼对象
8 | * 注释内容部分参照 http://blog.csdn.net/omni360 9 | * @param {THREE.SkinnedMesh} belongsToSkin 蒙皮对象 10 | * @constructor 11 | */ 12 | THREE.Bone = function ( belongsToSkin ) { 13 | 14 | THREE.Object3D.call( this ); 15 | /** 16 | * @desc 骨骼对象的皮肤 17 | * @type {THREE.SkinnedMesh} 18 | */ 19 | this.skin = belongsToSkin; 20 | 21 | }; 22 | /** 23 | * @desc Bone从Object3D的原型继承所有属性方法 24 | * @type {THREE.Object3D} 25 | */ 26 | THREE.Bone.prototype = Object.create( THREE.Object3D.prototype ); 27 | 28 | -------------------------------------------------------------------------------- /renderers/WebGLRenderTargetCube.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author alteredq / http://alteredqualia.com 3 | */ 4 | /** 5 | * @classdesc 立方体渲染目标对象 6 | * @param {number} width 宽度 7 | * @param {number} height 高度 8 | * @param {*} options 参数列表 9 | * @constructor 10 | */ 11 | THREE.WebGLRenderTargetCube = function ( width, height, options ) { 12 | 13 | THREE.WebGLRenderTarget.call( this, width, height, options ); 14 | 15 | this.activeCubeFace = 0; // PX 0, NX 1, PY 2, NY 3, PZ 4, NZ 5 16 | 17 | }; 18 | /** 19 | * @desc WebGLRenderTargetCube对象从WebGLRenderTarget的原型继承所有属性方法 20 | * @type {THREE.WebGLRenderTarget} 21 | */ 22 | THREE.WebGLRenderTargetCube.prototype = Object.create( THREE.WebGLRenderTarget.prototype ); 23 | -------------------------------------------------------------------------------- /core/Projector.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author mrdoob / http://mrdoob.com/ 3 | */ 4 | /** 5 | * @ignore 6 | * @constructor 7 | */ 8 | THREE.Projector = function () { 9 | 10 | console.warn( 'THREE.Projector has been moved to /examples/renderers/Projector.js.' ); 11 | 12 | this.projectVector = function ( vector, camera ) { 13 | 14 | console.warn( 'THREE.Projector: .projectVector() is now vector.project().' ); 15 | vector.project( camera ); 16 | 17 | }; 18 | 19 | this.unprojectVector = function ( vector, camera ) { 20 | 21 | console.warn( 'THREE.Projector: .unprojectVector() is now vector.unproject().' ); 22 | vector.unproject( camera ); 23 | 24 | }; 25 | 26 | this.pickingRay = function ( vector, camera ) { 27 | 28 | console.error( 'THREE.Projector: .pickingRay() has been removed.' ); 29 | 30 | }; 31 | 32 | }; 33 | -------------------------------------------------------------------------------- /lights/AmbientLight.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author mrdoob / http://mrdoob.com/ 3 | */ 4 | /** 5 | * @classdesc 环境光对象
6 | * 注释内容部分参照 http://blog.csdn.net/omni360 7 | * @param {THREE.Color} color 环境光的颜色 8 | * @extends {THREE.Light} 9 | * @constructor 10 | */ 11 | THREE.AmbientLight = function ( color ) { 12 | 13 | THREE.Light.call( this, color ); 14 | /** 15 | * @default 16 | * @type {string} 17 | */ 18 | this.type = 'AmbientLight'; 19 | 20 | }; 21 | /** 22 | * @desc AmbientLight对象从THREE.Light的原型继承所有属性方法 23 | * @type {THREE.Light} 24 | */ 25 | THREE.AmbientLight.prototype = Object.create( THREE.Light.prototype ); 26 | /** 27 | * @desc AmbientLight克隆函数 28 | * @returns {THREE.AmbientLight} 29 | */ 30 | THREE.AmbientLight.prototype.clone = function () { 31 | 32 | var light = new THREE.AmbientLight(); 33 | 34 | THREE.Light.prototype.clone.call( this, light ); 35 | 36 | return light; 37 | 38 | }; 39 | -------------------------------------------------------------------------------- /scenes/FogExp2.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author mrdoob / http://mrdoob.com/ 3 | * @author alteredq / http://alteredqualia.com/ 4 | */ 5 | /** 6 | * @classdesc 指数雾效对象
7 | * FogExp2.用来在场景内创建指数雾效,指数雾效是雾效浓度递增根据指数(参数density)设定,Fog对象的功能函数采用
8 | * 注释内容部分参照 http://blog.csdn.net/omni360 9 | * @param {THREE.Color} color 雾效的颜色属性,如果雾效颜色设置成黑色,远处的对象将被渲染成黑色 10 | * @param {float} density 雾效强度递增指数属性,可选参数,默认是0.00025 11 | * @constructor 12 | */ 13 | THREE.FogExp2 = function ( color, density ) { 14 | /** 15 | * @desc 雾的名字 16 | * @default '' 17 | * @type {string} 18 | */ 19 | this.name = ''; 20 | /** 21 | * @desc 雾效颜色 22 | * @type {THREE.Color} 23 | */ 24 | this.color = new THREE.Color( color ); 25 | /** 26 | * @desc 雾效强度递增指数 27 | * @default 0.00025 28 | * @type {float} 29 | */ 30 | this.density = ( density !== undefined ) ? density : 0.00025; 31 | 32 | }; 33 | 34 | /** 35 | * @desc 指数雾的克隆 36 | * @returns {THREE.FogExp2} 37 | */ 38 | THREE.FogExp2.prototype.clone = function () { 39 | 40 | return new THREE.FogExp2( this.color.getHex(), this.density ); 41 | 42 | }; 43 | -------------------------------------------------------------------------------- /materials/RawShaderMaterial.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author mrdoob / http://mrdoob.com/ 3 | */ 4 | /** 5 | * @classdesc 自定义着色器材质类型
6 | * 注释内容部分参照 http://blog.csdn.net/omni360 7 | * @desc 自定义着色器材质类型让用户扩充材质类型,有了无限的可能
8 | * 这个类和ShaderMaterial工作方式一样
9 | * 除了自定义的uniforms和attribute属性不会自动追加到GLSL着色器代码中 10 | * 表面有光泽的材质类型,计算每个像素 11 | * @param {String} parameters 材质参数 12 | * @extends {THREE.ShaderMaterial} 13 | * @constructor 14 | */ 15 | THREE.RawShaderMaterial = function ( parameters ) { 16 | 17 | THREE.ShaderMaterial.call( this, parameters ); 18 | /** 19 | * @default 'RawShaderMaterial' 20 | * @type {string} 21 | */ 22 | this.type = 'RawShaderMaterial'; 23 | 24 | }; 25 | /** 26 | * @desc RawShaderMaterial对象从THREE.Material的原型继承所有属性方法 27 | * @type {THREE.ShaderMaterial} 28 | */ 29 | THREE.RawShaderMaterial.prototype = Object.create( THREE.ShaderMaterial.prototype ); 30 | /** 31 | * @desc RawShaderMaterial材质的克隆函数 32 | * @returns {THREE.RawShaderMaterial} 33 | */ 34 | THREE.RawShaderMaterial.prototype.clone = function () { 35 | 36 | var material = new THREE.RawShaderMaterial(); 37 | 38 | THREE.ShaderMaterial.prototype.clone.call( this, material ); 39 | 40 | return material; 41 | 42 | }; 43 | -------------------------------------------------------------------------------- /scenes/Fog.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author mrdoob / http://mrdoob.com/ 3 | * @author alteredq / http://alteredqualia.com/ 4 | */ 5 | /** 6 | * @classdesc 线性雾效对象
7 | * Fog对象的构造函数.用来在场景内创建线性雾效,线性雾效就是从雾效的起始点参数near,到结束点参数far,雾效强度线性递增
8 | * 注释内容部分参照 http://blog.csdn.net/omni360 9 | * @param {THREE.Color} color 雾的颜色 10 | * @param {float} near 雾效的起始点,雾效的near属性大于当前相机的near属性,当前相机才不会受相机影响,可选参数,默认是1 11 | * @param {float} far 雾效的结束点,雾效的far属性小于当前相机的far属性,当前相机才不会受相机影响,可选参数,默认是1000 12 | * @constructor 13 | */ 14 | THREE.Fog = function ( color, near, far ) { 15 | /** 16 | * @desc 雾的名字 17 | * @default '' 18 | * @type {string} 19 | */ 20 | this.name = ''; 21 | /** 22 | * @desc 雾效颜色 23 | * @type {THREE.Color} 24 | */ 25 | this.color = new THREE.Color( color ); 26 | /** 27 | * @desc 雾的最近距离 28 | * @default 1 29 | * @type {float} 30 | */ 31 | this.near = ( near !== undefined ) ? near : 1; 32 | /** 33 | * @desc 雾的最远距离 34 | * @default 1000 35 | * @type {float} 36 | */ 37 | this.far = ( far !== undefined ) ? far : 1000; 38 | 39 | }; 40 | /** 41 | * @desc 雾对象的克隆 42 | * @returns {THREE.Fog} 43 | */ 44 | THREE.Fog.prototype.clone = function () { 45 | 46 | return new THREE.Fog( this.color.getHex(), this.near, this.far ); 47 | 48 | }; 49 | -------------------------------------------------------------------------------- /extras/GeometryUtils.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author mrdoob / http://mrdoob.com/ 3 | */ 4 | /** 5 | * @classdesc 几何对象工具集
6 | * 注释内容部分参照 http://blog.csdn.net/omni360 7 | * @ignore 8 | * @constructor 9 | */ 10 | THREE.GeometryUtils = { 11 | /** 12 | * @desc 合并几何对象 13 | * @param {THREE.Geometry} geometry1 几何对象1 14 | * @param {THREE.Geometry} geometry2 几何对象2 15 | * @param {float} materialIndexOffset 材质索引偏移量 16 | */ 17 | merge: function ( geometry1, geometry2, materialIndexOffset ) { 18 | 19 | console.warn( 'THREE.GeometryUtils: .merge() has been moved to Geometry. Use geometry.merge( geometry2, matrix, materialIndexOffset ) instead.' ); 20 | 21 | var matrix; 22 | 23 | if ( geometry2 instanceof THREE.Mesh ) { 24 | 25 | geometry2.matrixAutoUpdate && geometry2.updateMatrix(); 26 | 27 | matrix = geometry2.matrix; 28 | geometry2 = geometry2.geometry; 29 | 30 | } 31 | 32 | geometry1.merge( geometry2, matrix, materialIndexOffset ); 33 | 34 | }, 35 | /** 36 | * @desc 计算几何对象的中心 37 | * @param {THREE.Geometry} geometry 38 | * @returns {*} 39 | */ 40 | center: function ( geometry ) { 41 | 42 | console.warn( 'THREE.GeometryUtils: .center() has been moved to Geometry. Use geometry.center() instead.' ); 43 | return geometry.center(); 44 | 45 | } 46 | 47 | }; 48 | -------------------------------------------------------------------------------- /lights/Light.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author mrdoob / http://mrdoob.com/ 3 | * @author alteredq / http://alteredqualia.com/ 4 | */ 5 | /** 6 | * @classdesc 灯光对象的抽象基类
7 | * 注释内容部分参照 http://blog.csdn.net/omni360 8 | * @desc 在WebGL的三维空间中,存在点光源PointLight和聚光灯SpotLight两种类型,还有作为点光源的一种特例
9 | * 平行光DirectionLight,和环境光AmbientLight.在3D场景中,基本上是这几种光源的组合,创建各种各样的效果 10 | * @param {THREE.Color} color 灯光颜色值 11 | * @extends {THREE.Object3D} 12 | * @constructor 13 | */ 14 | THREE.Light = function ( color ) { 15 | 16 | THREE.Object3D.call( this ); 17 | /** 18 | * @default 19 | * @type {string} 20 | */ 21 | this.type = 'Light'; 22 | 23 | /** 24 | * @desc //设置灯光的颜色属性 25 | * @type {THREE.Color} 26 | */ 27 | this.color = new THREE.Color( color ); 28 | 29 | }; 30 | /** 31 | * @desc Light对象从THREE.Objec3D的原型继承所有属性方法 32 | * @type {THREE.Object3D} 33 | */ 34 | THREE.Light.prototype = Object.create( THREE.Object3D.prototype ); 35 | /** 36 | * @desc Light克隆函数 37 | * @param {THREE.Light} light 38 | * @returns {THREE.Light} 39 | */ 40 | THREE.Light.prototype.clone = function ( light ) { 41 | 42 | if ( light === undefined ) light = new THREE.Light(); 43 | 44 | THREE.Object3D.prototype.clone.call( this, light ); 45 | 46 | light.color.copy( this.color ); 47 | 48 | return light; 49 | 50 | }; 51 | -------------------------------------------------------------------------------- /textures/VideoTexture.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author mrdoob / http://mrdoob.com/ 3 | */ 4 | /** 5 | * @classdesc 视频纹理对象
6 | * 注释内容部分参照 http://blog.csdn.net/omni360 7 | * @extends {THREE.Texture} 8 | * @param {*} video 视频对象 9 | * @param {number} mapping 映射模式 10 | * @param {number} wrapS S方向覆盖模式 11 | * @param {number} wrapT T方向覆盖模式 12 | * @param {number} magFilter 纹理在放大时的过滤方式 13 | * @param {number} minFilter 纹理在缩小时的过滤方式 14 | * @param {number} format 像素数据的颜色格式 15 | * @param {number} type 数据类型 16 | * @param {number} anisotropy 各向异性 17 | * @constructor 18 | */ 19 | THREE.VideoTexture = function ( video, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ) { 20 | 21 | THREE.Texture.call( this, video, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ); 22 | /** 23 | * @default 24 | * @type {boolean} 25 | */ 26 | this.generateMipmaps = false; 27 | 28 | // 视频运行 29 | var scope = this; 30 | 31 | var update = function () { 32 | 33 | requestAnimationFrame( update ); 34 | 35 | if ( video.readyState === video.HAVE_ENOUGH_DATA ) { 36 | 37 | scope.needsUpdate = true; 38 | 39 | } 40 | 41 | }; 42 | 43 | update(); 44 | 45 | }; 46 | /** 47 | * @desc 数据纹理从THREE.Texture的原型继承所有属性方法 48 | * @type {THREE.Object3D} 49 | */ 50 | THREE.VideoTexture.prototype = Object.create( THREE.Texture.prototype ); 51 | -------------------------------------------------------------------------------- /textures/CubeTexture.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author mrdoob / http://mrdoob.com/ 3 | */ 4 | /** 5 | * @classdesc 立方体纹理对象
6 | * 注释内容部分参照 http://blog.csdn.net/omni360 7 | * @extends {THREE.Texture} 8 | * @param {Image} images 图像对象 9 | * @param {number} mapping 映射模式 10 | * @param {number} wrapS S方向覆盖模式 11 | * @param {number} wrapT T方向覆盖模式 12 | * @param {number} magFilter 纹理在放大时的过滤方式 13 | * @param {number} minFilter 纹理在缩小时的过滤方式 14 | * @param {number} format 像素数据的颜色格式 15 | * @param {number} type 数据类型 16 | * @param {number} anisotropy 各向异性 17 | * @constructor 18 | */ 19 | THREE.CubeTexture = function ( images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ) { 20 | 21 | THREE.Texture.call( this, images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ); 22 | 23 | this.images = images; 24 | 25 | }; 26 | /** 27 | * @desc 数据纹理从THREE.Texture的原型继承所有属性方法 28 | * @type {THREE.Object3D} 29 | */ 30 | THREE.CubeTexture.prototype = Object.create( THREE.Texture.prototype ); 31 | /** 32 | * @desc 克隆函数 33 | * @returns {THREE.DataTexture} 34 | */ 35 | THREE.CubeTexture.clone = function ( texture ) { 36 | 37 | if ( texture === undefined ) texture = new THREE.CubeTexture(); 38 | 39 | THREE.Texture.prototype.clone.call( this, texture ); 40 | 41 | texture.images = this.images; 42 | 43 | return texture; 44 | 45 | }; 46 | -------------------------------------------------------------------------------- /renderers/webgl/WebGLShader.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @classdesc webglshader 对象 3 | * @param {*} gl gl上下文对象 4 | * @param {number} type 类型 5 | * @param {string} string shader字符串 6 | * @constructor 7 | */ 8 | THREE.WebGLShader = ( function () { 9 | /** 10 | * @desc 格式化行对象 11 | * @param {string} string shader指令 12 | * @returns {string} 13 | */ 14 | var addLineNumbers = function ( string ) { 15 | 16 | var lines = string.split( '\n' ); 17 | 18 | for ( var i = 0; i < lines.length; i ++ ) { 19 | 20 | lines[ i ] = ( i + 1 ) + ': ' + lines[ i ]; 21 | 22 | } 23 | 24 | return lines.join( '\n' ); 25 | 26 | }; 27 | 28 | return function ( gl, type, string ) { 29 | 30 | var shader = gl.createShader( type ); 31 | 32 | gl.shaderSource( shader, string ); 33 | gl.compileShader( shader ); 34 | 35 | if ( gl.getShaderParameter( shader, gl.COMPILE_STATUS ) === false ) { 36 | 37 | console.error( 'THREE.WebGLShader: Shader couldn\'t compile.' ); 38 | 39 | } 40 | 41 | if ( gl.getShaderInfoLog( shader ) !== '' ) { 42 | 43 | console.warn( 'THREE.WebGLShader: gl.getShaderInfoLog()', gl.getShaderInfoLog( shader ) ); 44 | console.warn( addLineNumbers( string ) ); 45 | 46 | } 47 | 48 | // --enable-privileged-webgl-extension 49 | // console.log( type, gl.getExtension( 'WEBGL_debug_shaders' ).getTranslatedShaderSource( shader ) ); 50 | 51 | return shader; 52 | 53 | }; 54 | 55 | } )(); 56 | -------------------------------------------------------------------------------- /textures/DataTexture.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author alteredq / http://alteredqualia.com/ 3 | */ 4 | /** 5 | * @classdesc 由二进制数据生成的纹理对象
6 | * 注释内容部分参照 http://blog.csdn.net/omni360 7 | * @extends {THREE.Texture} 8 | * @param {*} data 图像数据 9 | * @param {number} width 图像宽度 10 | * @param {number} height 图像高度 11 | * @param {number} format 像素数据的颜色格式 12 | * @param {number} type 数据类型 13 | * @param {number} mapping 映射模式 14 | * @param {number} wrapS S方向覆盖模式 15 | * @param {number} wrapT T方向覆盖模式 16 | * @param {number} magFilter 纹理在放大时的过滤方式 17 | * @param {number} minFilter 纹理在缩小时的过滤方式 18 | * @param {number} anisotropy 各向异性 19 | * @constructor 20 | */ 21 | THREE.DataTexture = function ( data, width, height, format, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy ) { 22 | 23 | THREE.Texture.call( this, null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ); 24 | 25 | this.image = { data: data, width: width, height: height }; 26 | 27 | }; 28 | /** 29 | * @desc 数据纹理从THREE.Texture的原型继承所有属性方法 30 | * @type {THREE.Object3D} 31 | */ 32 | THREE.DataTexture.prototype = Object.create( THREE.Texture.prototype ); 33 | 34 | /** 35 | * @desc 克隆函数 36 | * @returns {THREE.DataTexture} 37 | */ 38 | THREE.DataTexture.prototype.clone = function () { 39 | 40 | var texture = new THREE.DataTexture(); 41 | 42 | THREE.Texture.prototype.clone.call( this, texture ); 43 | 44 | return texture; 45 | 46 | }; 47 | -------------------------------------------------------------------------------- /extras/SceneUtils.js: -------------------------------------------------------------------------------- 1 | /** * @author alteredq / http://alteredqualia.com/ */ /** * @classdesc 场景对象工具集
* 注释内容部分参照 http://blog.csdn.net/omni360 * @constructor */ THREE.SceneUtils = { /** * @desc 创建一种新的Objec3D对象,每个网格对象对应一种材质
* 这里和一个网格的每个面使用Meshfacematerial 材质不同.这种方式适用于网格对象在线框和着色几种材质之间变换频繁 * @param {THREE.Geometry} geometry 几何对象 * @param {THREE.Material} materials 材质对象 * @returns {THREE.Object3D} */ createMultiMaterialObject: function ( geometry, materials ) { var group = new THREE.Object3D(); for ( var i = 0, l = materials.length; i < l; i ++ ) { group.add( new THREE.Mesh( geometry, materials[ i ] ) ); } return group; }, /** * @desc 将子对象(参数child)从父对象中删除(参数parent),并重新将子对象添加到场景中. * @param {THREE.Object3D} child 子对象 * @param {THREE.Object3D} parent 父对象 * @param {THREE.Scene} scene 场景对象 */ detach: function ( child, parent, scene ) { child.applyMatrix( parent.matrixWorld ); parent.remove( child ); scene.add( child ); }, /** * @desc 将子对象冲场景中移除,加入父对象中 * @param {THREE.Object3D} child 子对象 * @param {THREE.Scene} scene 场景对象 * @param {THREE.Object3D} parent 父对象 */ attach: function ( child, scene, parent ) { var matrixWorldInverse = new THREE.Matrix4(); matrixWorldInverse.getInverse( parent.matrixWorld ); child.applyMatrix( matrixWorldInverse ); scene.remove( child ); parent.add( child ); } }; -------------------------------------------------------------------------------- /lights/PointLight.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author mrdoob / http://mrdoob.com/ 3 | */ 4 | /** 5 | * @classdesc 点光源对象
6 | * 注释内容部分参照 http://blog.csdn.net/omni360 7 | * @desc 点光源目前不支持阴影 8 | * @param {THREE.Color} color 点光源颜色 9 | * @param {float} intensity 光的强度,默认是1 10 | * @param {float} distance 光的长度,从光的position位置,开始衰减,衰减到distance的长度,默认是0 11 | * @extends {THREE.Light} 12 | * @example var light = new THREE.PointLight(0xff0000,1,100);
13 | * light.position.set(50,50,30); //设置位置
14 | * scene.add(lignt); //加入场景
15 | * @constructor 16 | */ 17 | THREE.PointLight = function ( color, intensity, distance ) { 18 | 19 | THREE.Light.call( this, color ); 20 | /** 21 | * @default 22 | * @type {string} 23 | */ 24 | this.type = 'PointLight'; 25 | /** 26 | * @desc 光的强度 27 | * @default 1 28 | * @type {float} 29 | */ 30 | this.intensity = ( intensity !== undefined ) ? intensity : 1; 31 | /** 32 | * @desc 光的长度 33 | * @default 0 34 | * @type {float} 35 | */ 36 | this.distance = ( distance !== undefined ) ? distance : 0; 37 | 38 | }; 39 | /** 40 | * @desc PointLight对象从THREE.Light的原型继承所有属性方法 41 | * @type {THREE.Light} 42 | */ 43 | THREE.PointLight.prototype = Object.create( THREE.Light.prototype ); 44 | /** 45 | * @desc PointLight克隆函数 46 | * @returns {THREE.PointLight} 47 | */ 48 | THREE.PointLight.prototype.clone = function () { 49 | 50 | var light = new THREE.PointLight(); 51 | 52 | THREE.Light.prototype.clone.call( this, light ); 53 | 54 | light.intensity = this.intensity; 55 | light.distance = this.distance; 56 | 57 | return light; 58 | 59 | }; 60 | -------------------------------------------------------------------------------- /lights/HemisphereLight.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author alteredq / http://alteredqualia.com/ 3 | */ 4 | /** 5 | * @classdesc 半球光对象
6 | * 注释内容部分参照 http://blog.csdn.net/omni360 7 | * @desc HemisphereLight类是在场景中创建半球光,就是天光效果
8 | * 经常用在室外,将各个位置的物体都照亮,室内的光线大多是方向性的
9 | * 半球光不支持阴影 10 | * @param {THREE.Color} skyColor 半球光的颜色(天光的颜色) 11 | * @param {THREE.Color} groundColor 半球光的地面颜色 12 | * @param {float} intensity 灯光的强度,默认是1 13 | * @extends {THREE.Light} 14 | * @constructor 15 | */ 16 | THREE.HemisphereLight = function ( skyColor, groundColor, intensity ) { 17 | 18 | THREE.Light.call( this, skyColor ); 19 | /** 20 | * @default 21 | * @type {string} 22 | */ 23 | this.type = 'HemisphereLight'; 24 | 25 | /** 26 | * @desc 灯光初始化位置为(0,100,0) 27 | */ 28 | this.position.set( 0, 100, 0 ); 29 | 30 | /** 31 | * @desc 半球光的地面颜色 32 | * @type {THREE.Color} 33 | */ 34 | this.groundColor = new THREE.Color( groundColor ); 35 | /** 36 | * @desc 灯光的强度 37 | * @default 1 38 | * @type {number} 39 | */ 40 | this.intensity = ( intensity !== undefined ) ? intensity : 1; 41 | 42 | }; 43 | /** 44 | * @desc HemisphereLight对象从THREE.Light的原型继承所有属性方法 45 | * @type {THREE.Light} 46 | */ 47 | THREE.HemisphereLight.prototype = Object.create( THREE.Light.prototype ); 48 | /** 49 | * @desc HemisphereLight克隆函数 50 | * @returns {THREE.HemisphereLight} 51 | */ 52 | THREE.HemisphereLight.prototype.clone = function () { 53 | 54 | var light = new THREE.HemisphereLight(); 55 | 56 | THREE.Light.prototype.clone.call( this, light ); 57 | 58 | light.groundColor.copy( this.groundColor ); 59 | light.intensity = this.intensity; 60 | 61 | return light; 62 | 63 | }; 64 | -------------------------------------------------------------------------------- /materials/MeshFaceMaterial.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author mrdoob / http://mrdoob.com/ 3 | */ 4 | /** 5 | * @classdesc mesh(网格)的网格复合材质
6 | * 注释内容部分参照 http://blog.csdn.net/omni360 7 | * @desc 多材质,支持材质的列表
8 | * 离相机越近,材质越亮(白),离相机越远,材质越暗(黑) 9 | * @param {String} parameters 材质参数 10 | * @extends {THREE.Material} 11 | * @constructor 12 | */ 13 | THREE.MeshFaceMaterial = function ( materials ) { 14 | 15 | this.uuid = THREE.Math.generateUUID(); 16 | /** 17 | * @default 'MeshFaceMaterial' 18 | * @type {string} 19 | */ 20 | this.type = 'MeshFaceMaterial'; 21 | 22 | /** 23 | * @desc 材质列表 24 | */ 25 | this.materials = materials instanceof Array ? materials : []; 26 | 27 | }; 28 | 29 | THREE.MeshFaceMaterial.prototype = { 30 | 31 | constructor: THREE.MeshFaceMaterial, 32 | /** 33 | * @desc 材质列表转换JSON格式 34 | * @returns {*} 35 | */ 36 | toJSON: function () { 37 | 38 | var output = { 39 | metadata: { 40 | version: 4.2, 41 | type: 'material', 42 | generator: 'MaterialExporter' 43 | }, 44 | uuid: this.uuid, 45 | type: this.type, 46 | materials: [] 47 | }; 48 | 49 | for ( var i = 0, l = this.materials.length; i < l; i ++ ) { 50 | 51 | output.materials.push( this.materials[ i ].toJSON() ); 52 | 53 | } 54 | 55 | return output; 56 | 57 | }, 58 | /** 59 | * @desc MeshFaceMaterial材质的克隆函数 60 | * @returns {THREE.MeshFaceMaterial} 61 | */ 62 | clone: function () { 63 | 64 | var material = new THREE.MeshFaceMaterial(); 65 | 66 | for ( var i = 0; i < this.materials.length; i ++ ) { 67 | 68 | material.materials.push( this.materials[ i ].clone() ); 69 | 70 | } 71 | 72 | return material; 73 | 74 | } 75 | 76 | }; 77 | -------------------------------------------------------------------------------- /renderers/shaders/UniformsUtils.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Uniform Utilities 3 | */ 4 | /** 5 | * @classdesc Uniforms操作 6 | * @memberof THREE 7 | * @constructor 8 | */ 9 | THREE.UniformsUtils = { 10 | /** 11 | * @desc 合并uniform参数 12 | * @param {array} uniforms 13 | * @returns {array} 14 | */ 15 | merge: function ( uniforms ) { 16 | 17 | var merged = {}; 18 | 19 | for ( var u = 0; u < uniforms.length; u ++ ) { 20 | 21 | var tmp = this.clone( uniforms[ u ] ); 22 | 23 | for ( var p in tmp ) { 24 | 25 | merged[ p ] = tmp[ p ]; 26 | 27 | } 28 | 29 | } 30 | 31 | return merged; 32 | 33 | }, 34 | /** 35 | * @desc THREE.UniformsUtils 克隆函数 36 | * @param {THREE.UniformsUtils} uniforms_src 37 | * @returns {THREE.UniformsUtils} 38 | */ 39 | clone: function ( uniforms_src ) { 40 | 41 | var uniforms_dst = {}; 42 | 43 | for ( var u in uniforms_src ) { 44 | 45 | uniforms_dst[ u ] = {}; 46 | 47 | for ( var p in uniforms_src[ u ] ) { 48 | 49 | var parameter_src = uniforms_src[ u ][ p ]; 50 | 51 | if ( parameter_src instanceof THREE.Color || 52 | parameter_src instanceof THREE.Vector2 || 53 | parameter_src instanceof THREE.Vector3 || 54 | parameter_src instanceof THREE.Vector4 || 55 | parameter_src instanceof THREE.Matrix4 || 56 | parameter_src instanceof THREE.Texture ) { 57 | 58 | uniforms_dst[ u ][ p ] = parameter_src.clone(); 59 | 60 | } else if ( parameter_src instanceof Array ) { 61 | 62 | uniforms_dst[ u ][ p ] = parameter_src.slice(); 63 | 64 | } else { 65 | 66 | uniforms_dst[ u ][ p ] = parameter_src; 67 | 68 | } 69 | 70 | } 71 | 72 | } 73 | 74 | return uniforms_dst; 75 | 76 | } 77 | 78 | }; 79 | -------------------------------------------------------------------------------- /scenes/Scene.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author mrdoob / http://mrdoob.com/ 3 | */ 4 | 5 | /** 6 | * @classdesc Scene是场景对象,所有的对象,灯光,动画,骨骼等都需要放置在场景内.Scene对象的功能函数采用定义构造的函数原型对象来实现.
7 | * 注释内容部分参照 http://blog.csdn.net/omni360 8 | * @desc 场景对象构造函数 9 | * @class 10 | * @extends {THREE.Object3D} 11 | */ 12 | THREE.Scene = function () { 13 | 14 | // 调用Object3D对象的call方法,将原本属于Object3D的方法交给当前对象Scene来使用. 15 | THREE.Object3D.call( this ); 16 | 17 | /** 18 | * @desc 场景的类型定义 19 | * @default 20 | * @type {string} 21 | */ 22 | this.type = 'Scene'; 23 | /** 24 | * @desc 场景的雾效属性 25 | * @default 26 | * @type {THREE.fog} 27 | */ 28 | this.fog = null; 29 | /** 30 | * @desc 场景的材质属性,默认为null,如果设置了这个属性,场景中的所有对象渲染成这个材质. 31 | * @default 32 | * @type {THREE.Material} 33 | */ 34 | this.overrideMaterial = null; 35 | 36 | /** 37 | * @desc 默认为true,表示渲染器每一帧都会检查场景和场景中的对象的矩阵的是否更新,如果为false,场景中的对象将不会被自动更新 38 | * @default 39 | * @type {boolean} 40 | */ 41 | this.autoUpdate = true; // checked by the renderer 42 | 43 | }; 44 | 45 | /** 46 | * @desc Scene对象从THREE.Objec3D的原型继承所有属性方法 47 | * @type {THREE.Object3D} 48 | */ 49 | THREE.Scene.prototype = Object.create( THREE.Object3D.prototype ); 50 | 51 | /** 52 | * @desc Three.Scene 拷贝函数,将属性数组分别复制 53 | * @param {THREE.Scene} object - 源Scene 54 | * @returns {THREE.Scene} 55 | */ 56 | THREE.Scene.prototype.clone = function ( object ) { 57 | 58 | if ( object === undefined ) object = new THREE.Scene(); 59 | 60 | THREE.Object3D.prototype.clone.call( this, object ); 61 | 62 | if ( this.fog !== null ) object.fog = this.fog.clone(); 63 | if ( this.overrideMaterial !== null ) object.overrideMaterial = this.overrideMaterial.clone(); 64 | 65 | object.autoUpdate = this.autoUpdate; 66 | object.matrixAutoUpdate = this.matrixAutoUpdate; 67 | 68 | return object; 69 | 70 | }; 71 | -------------------------------------------------------------------------------- /materials/SpriteMaterial.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author alteredq / http://alteredqualia.com/ 3 | * 4 | * parameters = { 5 | * color: , 6 | * opacity: , 7 | * map: new THREE.Texture( ), 8 | * 9 | * blending: THREE.NormalBlending, 10 | * depthTest: , 11 | * depthWrite: , 12 | * 13 | * uvOffset: new THREE.Vector2(), 14 | * uvScale: new THREE.Vector2(), 15 | * 16 | * fog: 17 | * } 18 | */ 19 | /** 20 | * @classdesc Sprite(点精灵)的材质
21 | * 注释内容部分参照 http://blog.csdn.net/omni360 22 | * @param {String} parameters 材质参数 23 | * @extends {THREE.Material} 24 | * @constructor 25 | */ 26 | THREE.SpriteMaterial = function ( parameters ) { 27 | 28 | THREE.Material.call( this ); 29 | /** 30 | * @default 'SpriteMaterial' 31 | * @type {string} 32 | */ 33 | this.type = 'SpriteMaterial'; 34 | /** 35 | * @desc 材质颜色 36 | * @default 0xffffff 白色 37 | * @type {THREE.Color} 38 | */ 39 | this.color = new THREE.Color( 0xffffff ); 40 | /** 41 | * @desc 纹理贴图 42 | * @default 43 | * @type {THREE.Texture} 44 | */ 45 | this.map = null; 46 | /** 47 | * @desc 旋转角度,粒子系统的贴图的旋转角度 48 | * @type {float} 49 | */ 50 | this.rotation = 0; 51 | /** 52 | * @desc 雾效,默认关闭 53 | * @default 54 | * @type {boolean} 55 | */ 56 | this.fog = false; 57 | 58 | // set parameters 59 | 60 | this.setValues( parameters ); 61 | 62 | }; 63 | 64 | THREE.SpriteMaterial.prototype = Object.create( THREE.Material.prototype ); 65 | 66 | THREE.SpriteMaterial.prototype.clone = function () { 67 | 68 | var material = new THREE.SpriteMaterial(); 69 | 70 | THREE.Material.prototype.clone.call( this, material ); 71 | 72 | material.color.copy( this.color ); 73 | material.map = this.map; 74 | 75 | material.rotation = this.rotation; 76 | 77 | material.fog = this.fog; 78 | 79 | return material; 80 | 81 | }; 82 | -------------------------------------------------------------------------------- /materials/MeshDepthMaterial.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author mrdoob / http://mrdoob.com/ 3 | * @author alteredq / http://alteredqualia.com/ 4 | * 5 | * parameters = { 6 | * opacity: , 7 | * 8 | * blending: THREE.NormalBlending, 9 | * depthTest: , 10 | * depthWrite: , 11 | * 12 | * wireframe: , 13 | * wireframeLinewidth: 14 | * } 15 | */ 16 | /** 17 | * @classdesc mesh(网格)的网格深度材质
18 | * 注释内容部分参照 http://blog.csdn.net/omni360 19 | * @desc 基于相机远近裁切面自动变换亮度(明暗度)的mesh(网格)的材质
20 | * 离相机越近,材质越亮(白),离相机越远,材质越暗(黑) 21 | * @param {String} parameters 材质参数 22 | * @extends {THREE.Material} 23 | * @constructor 24 | */ 25 | THREE.MeshDepthMaterial = function ( parameters ) { 26 | 27 | THREE.Material.call( this ); 28 | /** 29 | * @default 'MeshDepthMaterial' 30 | * @type {string} 31 | */ 32 | this.type = 'MeshDepthMaterial'; 33 | /** 34 | * @desc 定义材质是否设定目标变形动画 35 | * @default 36 | * @type {boolean} 37 | */ 38 | this.morphTargets = false; 39 | /** 40 | * @desc 是否使用线框模式 41 | * @default 42 | * @type {boolean} 43 | */ 44 | this.wireframe = false; 45 | /** 46 | * @default 线框宽度 47 | * @default 48 | * @type {number} 49 | */ 50 | this.wireframeLinewidth = 1; 51 | 52 | this.setValues( parameters ); 53 | 54 | }; 55 | /** 56 | * @desc MeshDepthMaterial对象从THREE.Material的原型继承所有属性方法 57 | * @type {THREE.Material} 58 | */ 59 | THREE.MeshDepthMaterial.prototype = Object.create( THREE.Material.prototype ); 60 | /** 61 | * @desc MeshDepthMaterial材质的克隆函数 62 | * @returns {THREE.MeshDepthMaterial} 63 | */ 64 | THREE.MeshDepthMaterial.prototype.clone = function () { 65 | 66 | var material = new THREE.MeshDepthMaterial(); 67 | 68 | THREE.Material.prototype.clone.call( this, material ); 69 | 70 | material.wireframe = this.wireframe; 71 | material.wireframeLinewidth = this.wireframeLinewidth; 72 | 73 | return material; 74 | 75 | }; 76 | -------------------------------------------------------------------------------- /textures/CompressedTexture.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author alteredq / http://alteredqualia.com/ 3 | */ 4 | /** 5 | * @classdesc 由Mipmaps生成的纹理对象
6 | * 注释内容部分参照 http://blog.csdn.net/omni360 7 | * @extends {THREE.Texture} 8 | * @param {number} mipmaps mipmaps对象,,WebGL不能生成mipmaps,mipmaps只能嵌入到DDS文件 9 | * @param {number} width 图像宽度 10 | * @param {number} height 图像高度 11 | * @param {number} format 像素数据的颜色格式 12 | * @param {number} type 数据类型 13 | * @param {number} mapping 映射模式 14 | * @param {number} wrapS S方向覆盖模式 15 | * @param {number} wrapT T方向覆盖模式 16 | * @param {number} magFilter 纹理在放大时的过滤方式 17 | * @param {number} minFilter 纹理在缩小时的过滤方式 18 | * @param {number} anisotropy 各向异性 19 | * @constructor 20 | */ 21 | THREE.CompressedTexture = function ( mipmaps, width, height, format, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy ) { 22 | 23 | THREE.Texture.call( this, null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ); 24 | 25 | this.image = { width: width, height: height }; 26 | this.mipmaps = mipmaps; 27 | 28 | // no flipping for cube textures 29 | // (also flipping doesn't work for compressed textures ) 30 | // flipping 不能在压缩纹理中生效 31 | /** 32 | * @default 33 | * @type {boolean} 34 | */ 35 | this.flipY = false; 36 | 37 | // can't generate mipmaps for compressed textures 38 | // mips must be embedded in DDS files 39 | // //WebGL不能生成mipmaps,mipmaps只能嵌入到DDS文件 40 | /** 41 | * @default 42 | * @type {boolean} 43 | */ 44 | this.generateMipmaps = false; 45 | 46 | }; 47 | /** 48 | * @desc 数据纹理从THREE.Texture的原型继承所有属性方法 49 | * @type {THREE.Object3D} 50 | */ 51 | THREE.CompressedTexture.prototype = Object.create( THREE.Texture.prototype ); 52 | /** 53 | * @desc 克隆函数 54 | * @returns {THREE.DataTexture} 55 | */ 56 | THREE.CompressedTexture.prototype.clone = function () { 57 | 58 | var texture = new THREE.CompressedTexture(); 59 | 60 | THREE.Texture.prototype.clone.call( this, texture ); 61 | 62 | return texture; 63 | 64 | }; 65 | -------------------------------------------------------------------------------- /materials/MeshNormalMaterial.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author mrdoob / http://mrdoob.com/ 3 | * 4 | * parameters = { 5 | * opacity: , 6 | * 7 | * shading: THREE.FlatShading, 8 | * blending: THREE.NormalBlending, 9 | * depthTest: , 10 | * depthWrite: , 11 | * 12 | * wireframe: , 13 | * wireframeLinewidth: 14 | * } 15 | */ 16 | /** 17 | * @classdesc mesh(网格)的标准材质类型
18 | * 注释内容部分参照 http://blog.csdn.net/omni360 19 | * @param {String} parameters 材质参数 20 | * @extends {THREE.Material} 21 | * @constructor 22 | */ 23 | THREE.MeshNormalMaterial = function ( parameters ) { 24 | 25 | THREE.Material.call( this, parameters ); 26 | /** 27 | * @default 'FlatShading' 28 | * @type {string} 29 | */ 30 | this.type = 'MeshNormalMaterial'; 31 | 32 | /** 33 | * @desc 着色方式
34 | * THREE.SmoothShading平滑着色:用多种颜色进行绘制
35 | * 每个顶点都是单独进行处理的,各顶点和各图元之间采用均匀插值。 36 | * @default 37 | * @type {number} 38 | */ 39 | this.shading = THREE.SmoothShading; 40 | 41 | /** 42 | * @desc 是否以线框方式渲染几何体 43 | * @default 44 | * @type {boolean} 45 | */ 46 | this.wireframe = false; 47 | /** 48 | * @desc 线框宽度 49 | * @default 50 | * @type {float} 51 | */ 52 | this.wireframeLinewidth = 1; 53 | 54 | /** 55 | * @desc 材质是否设定目标变形动画 56 | * @default 57 | * @type {boolean} 58 | */ 59 | this.morphTargets = false; 60 | 61 | this.setValues( parameters ); 62 | 63 | }; 64 | /** 65 | * @desc MeshNormalMaterial对象从THREE.Material的原型继承所有属性方法 66 | * @type {THREE.Material} 67 | */ 68 | THREE.MeshNormalMaterial.prototype = Object.create( THREE.Material.prototype ); 69 | /** 70 | * @desc MeshNormalMaterial材质的克隆函数 71 | * @returns {THREE.MeshNormalMaterial} 72 | */ 73 | THREE.MeshNormalMaterial.prototype.clone = function () { 74 | 75 | var material = new THREE.MeshNormalMaterial(); 76 | 77 | THREE.Material.prototype.clone.call( this, material ); 78 | 79 | material.shading = this.shading; 80 | 81 | material.wireframe = this.wireframe; 82 | material.wireframeLinewidth = this.wireframeLinewidth; 83 | 84 | return material; 85 | 86 | }; 87 | -------------------------------------------------------------------------------- /renderers/webgl/WebGLExtensions.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @classdesc webgl扩展标记 3 | * @param {*} gl webgl上下文对象 4 | * @constructor 5 | */ 6 | THREE.WebGLExtensions = function ( gl ) { 7 | 8 | var extensions = {}; 9 | /** 10 | * @desc 通过名称获得gl的对象值 11 | * @param {string} name 对象名称 12 | * @returns {*} 13 | */ 14 | this.get = function ( name ) { 15 | 16 | if ( extensions[ name ] !== undefined ) { 17 | 18 | return extensions[ name ]; 19 | 20 | } 21 | 22 | var extension; 23 | 24 | switch ( name ) { 25 | 26 | case 'OES_texture_float': 27 | extension = gl.getExtension( 'OES_texture_float' ); 28 | break; 29 | 30 | case 'OES_texture_float_linear': 31 | extension = gl.getExtension( 'OES_texture_float_linear' ); 32 | break; 33 | 34 | case 'OES_standard_derivatives': 35 | extension = gl.getExtension( 'OES_standard_derivatives' ); 36 | break; 37 | 38 | case 'EXT_texture_filter_anisotropic': 39 | extension = gl.getExtension( 'EXT_texture_filter_anisotropic' ) || gl.getExtension( 'MOZ_EXT_texture_filter_anisotropic' ) || gl.getExtension( 'WEBKIT_EXT_texture_filter_anisotropic' ); 40 | break; 41 | 42 | case 'WEBGL_compressed_texture_s3tc': 43 | extension = gl.getExtension( 'WEBGL_compressed_texture_s3tc' ) || gl.getExtension( 'MOZ_WEBGL_compressed_texture_s3tc' ) || gl.getExtension( 'WEBKIT_WEBGL_compressed_texture_s3tc' ); 44 | break; 45 | 46 | case 'WEBGL_compressed_texture_pvrtc': 47 | extension = gl.getExtension( 'WEBGL_compressed_texture_pvrtc' ) || gl.getExtension( 'WEBKIT_WEBGL_compressed_texture_pvrtc' ); 48 | break; 49 | 50 | case 'OES_element_index_uint': 51 | extension = gl.getExtension( 'OES_element_index_uint' ); 52 | break; 53 | 54 | case 'EXT_blend_minmax': 55 | extension = gl.getExtension( 'EXT_blend_minmax' ); 56 | break; 57 | 58 | case 'EXT_frag_depth': 59 | extension = gl.getExtension( 'EXT_frag_depth' ); 60 | break; 61 | 62 | } 63 | 64 | if ( extension === null ) { 65 | 66 | console.log( 'THREE.WebGLRenderer: ' + name + ' extension not supported.' ); 67 | 68 | } 69 | 70 | extensions[ name ] = extension; 71 | 72 | return extension; 73 | 74 | }; 75 | 76 | }; 77 | -------------------------------------------------------------------------------- /core/Clock.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author alteredq / http://alteredqualia.com/ 3 | */ 4 | 5 | /** 6 | * @classdesc 时钟类
7 | * 注释内容部分参照 http://blog.csdn.net/omni360 8 | * @desc 用来记录时间等功能 9 | * @param {boolean} autoStart 是否自动启动,默认为启动 10 | * @constructor 11 | */ 12 | THREE.Clock = function ( autoStart ) { 13 | 14 | /** 15 | * @desc 是否自动启动 16 | * @default true 17 | * @type {boolean} 18 | */ 19 | this.autoStart = ( autoStart !== undefined ) ? autoStart : true; 20 | /** 21 | * @desc 启动时间 22 | * @default 0 23 | * @type {number} 24 | */ 25 | this.startTime = 0; 26 | /** 27 | * @desc 上一次时间 28 | * @default 0 29 | * @type {number} 30 | */ 31 | this.oldTime = 0; 32 | /** 33 | * @desc 运行时间 34 | * @default 0 35 | * @type {number} 36 | */ 37 | this.elapsedTime = 0; 38 | /** 39 | * @desc 是否正在运行 40 | * @default false 41 | * @type {boolean} 42 | */ 43 | this.running = false; 44 | 45 | }; 46 | 47 | THREE.Clock.prototype = { 48 | 49 | constructor: THREE.Clock, 50 | /** 51 | * @desc 开始记录时间,获得开始的时间截 52 | */ 53 | start: function () { 54 | 55 | this.startTime = self.performance !== undefined && self.performance.now !== undefined 56 | ? self.performance.now() 57 | : Date.now(); 58 | 59 | this.oldTime = this.startTime; 60 | this.running = true; 61 | }, 62 | /** 63 | * @desc 停止记录时间,获得结束的时间截 64 | */ 65 | stop: function () { 66 | 67 | this.getElapsedTime(); 68 | this.running = false; 69 | 70 | }, 71 | /** 72 | * @desc 返回从oldTimed到stop之间的时间长度,以秒为单位 73 | * @returns {number} 秒为单位 74 | */ 75 | getElapsedTime: function () { 76 | 77 | this.getDelta(); 78 | return this.elapsedTime; 79 | 80 | }, 81 | /** 82 | * @desc 获oldTimed到现在的时间差值,以秒为单位 83 | * @returns {number} 秒为单位 84 | */ 85 | getDelta: function () { 86 | 87 | var diff = 0; 88 | 89 | if ( this.autoStart && ! this.running ) { 90 | 91 | this.start(); 92 | 93 | } 94 | 95 | if ( this.running ) { 96 | 97 | var newTime = self.performance !== undefined && self.performance.now !== undefined 98 | ? self.performance.now() 99 | : Date.now(); 100 | 101 | diff = 0.001 * ( newTime - this.oldTime ); 102 | this.oldTime = newTime; 103 | 104 | this.elapsedTime += diff; 105 | 106 | } 107 | 108 | return diff; 109 | 110 | } 111 | 112 | }; 113 | -------------------------------------------------------------------------------- /cameras/Camera.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author mrdoob / http://mrdoob.com/ 3 | * @author mikael emtinger / http://gomo.se/ 4 | * @author WestLangley / http://github.com/WestLangley 5 | */ 6 | /** 7 | * @classdesc 相机基类
8 | * 注释内容部分参照 http://blog.csdn.net/omni360 9 | * @constructor 10 | * @extends {THREE.Object3D} 11 | */ 12 | THREE.Camera = function () { 13 | 14 | THREE.Object3D.call( this ); 15 | /** 16 | * @default 17 | * @type {string} 18 | */ 19 | this.type = 'Camera'; 20 | /** 21 | * @desc 这是matrixWorld的逆矩阵,matrixWorld包含相机在世界坐标系的变换矩阵 22 | * @type {THREE.Matrix4} 23 | */ 24 | this.matrixWorldInverse = new THREE.Matrix4(); 25 | /** 26 | * @desc 相机设置属性projectionMatrix,包含相机的投影矩阵 27 | * @type {THREE.Matrix4} 28 | */ 29 | this.projectionMatrix = new THREE.Matrix4(); 30 | 31 | }; 32 | /** 33 | * @desc 相机对象从THREE.Objec3D的原型继承所有属性方法 34 | * @type {THREE.Object3D} 35 | */ 36 | THREE.Camera.prototype = Object.create( THREE.Object3D.prototype ); 37 | /** 38 | * @function 39 | * @desc 获取世界坐标系内的四元数参数 40 | * @param {THREE.Quaternion} optionalTarget 41 | * @return {THREE.Quaternion} 42 | */ 43 | THREE.Camera.prototype.getWorldDirection = function () { 44 | 45 | var quaternion = new THREE.Quaternion(); 46 | 47 | return function ( optionalTarget ) { 48 | 49 | var result = optionalTarget || new THREE.Vector3(); 50 | 51 | this.getWorldQuaternion( quaternion ); 52 | 53 | return result.set( 0, 0, - 1 ).applyQuaternion( quaternion ); 54 | 55 | } 56 | 57 | }(); 58 | /** 59 | * @function 60 | * @desc 用来旋转相机对象,并将对象面对空间中的点(参数vector) 61 | * @param {THREE.Vector3} vector 62 | */ 63 | THREE.Camera.prototype.lookAt = function () { 64 | 65 | // This routine does not support cameras with rotated and/or translated parent(s) 66 | 67 | var m1 = new THREE.Matrix4(); 68 | 69 | return function ( vector ) { 70 | 71 | m1.lookAt( this.position, vector, this.up ); 72 | 73 | this.quaternion.setFromRotationMatrix( m1 ); 74 | 75 | }; 76 | 77 | }(); 78 | /** 79 | * @desc 克隆相机 80 | * @param {THREE.Camera} camera 81 | * @returns {THREE.Camera} 82 | */ 83 | THREE.Camera.prototype.clone = function ( camera ) { 84 | 85 | if ( camera === undefined ) camera = new THREE.Camera(); 86 | 87 | THREE.Object3D.prototype.clone.call( this, camera ); 88 | 89 | camera.matrixWorldInverse.copy( this.matrixWorldInverse ); 90 | camera.projectionMatrix.copy( this.projectionMatrix ); 91 | 92 | return camera; 93 | }; 94 | -------------------------------------------------------------------------------- /lights/AreaLight.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author MPanknin / http://www.redplant.de/ 3 | * @author alteredq / http://alteredqualia.com/ 4 | */ 5 | /** 6 | * @classdesc 面光,区域光对象
7 | * 注释内容部分参照 http://blog.csdn.net/omni360 8 | * @desc 区域光和其他光源不同,是一种二维面积光源,他的亮度不仅和强度有关,而且还和他的面积大小有关.
9 | * 通过变换灯光的width,height,normal属性,区域光可以模拟窗户射入光线 10 | * @param {THREE.Color} color 环境光的颜色 11 | * @param {float} intensity 灯光的强度,默认是1 12 | * @extends {THREE.Light} 13 | * @example var light = new THREE.AreaLight(0xff0000,1); //创建平面灯光对象
14 | * light.position.set(50,50,30); //设置位置
15 | * light.rotation.set(-0.3,0.3,0.002); //设置角度
16 | * light.width = 10; //设置宽度
17 | * light.height = 1; //设置高度
18 | * scene.add(lignt); //加入场景 19 | * @constructor 20 | */ 21 | THREE.AreaLight = function ( color, intensity ) { 22 | 23 | THREE.Light.call( this, color ); 24 | /** 25 | * @default 26 | * @type {string} 27 | */ 28 | this.type = 'AreaLight'; 29 | 30 | /** 31 | * @desc 面法线
32 | * 可以设置或者获得面光的单位向量,确认灯光照射面正确.这是在局部空间计算. 33 | * @default ( 0, - 1, 0 ) 34 | * @type {THREE.Vector3} 35 | */ 36 | this.normal = new THREE.Vector3( 0, - 1, 0 ); 37 | /** 38 | * @desc 灯光的方向 39 | * @default ( 1, 0, 0 ) 40 | * @type {THREE.Vector3} 41 | */ 42 | this.right = new THREE.Vector3( 1, 0, 0 ); 43 | /** 44 | * @desc 灯光的强度 45 | * @default ( 1, 0, 0 ) 46 | * @type {THREE.Vector3} 47 | */ 48 | this.intensity = ( intensity !== undefined ) ? intensity : 1; 49 | /** 50 | * @desc 区域光的宽度,初始化为1.0 51 | * @default 52 | * @type {float} 53 | */ 54 | this.width = 1.0; 55 | /** 56 | * @desc 区域光的宽度,初始化为1.0 57 | * @default 58 | * @type {float} 59 | */ 60 | this.height = 1.0; 61 | //WebGL是通过光强乘以衰减系数来计算衰减光照的, 62 | //attenuation (衰减系数) = 1`/ (this.constantAttenuation + this.distance * this.linearAttenuation + this.quadraticAttenuation * this.distance * this.distance ) 63 | /** 64 | * @desc 常量衰减系数,系数值越大,衰变越快 65 | * @default 66 | * @type {float} 67 | */ 68 | this.constantAttenuation = 1.5; 69 | /** 70 | * @desc 线性衰减系数,系数值越大,衰变越快 71 | * @default 72 | * @type {float} 73 | */ 74 | this.linearAttenuation = 0.5; 75 | /** 76 | * @desc 衰减平方系数,系数值越大,衰变越快 77 | * @default 78 | * @type {float} 79 | */ 80 | this.quadraticAttenuation = 0.1; 81 | 82 | }; 83 | /** 84 | * @desc AreaLight对象从THREE.Light的原型继承所有属性方法 85 | * @type {THREE.Light} 86 | */ 87 | THREE.AreaLight.prototype = Object.create( THREE.Light.prototype ); 88 | 89 | -------------------------------------------------------------------------------- /materials/LineBasicMaterial.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author mrdoob / http://mrdoob.com/ 3 | * @author alteredq / http://alteredqualia.com/ 4 | * 5 | * parameters = { 6 | * color: , 7 | * opacity: , 8 | * 9 | * blending: THREE.NormalBlending, 10 | * depthTest: , 11 | * depthWrite: , 12 | * 13 | * linewidth: , 14 | * linecap: "round", 15 | * linejoin: "round", 16 | * 17 | * vertexColors: 18 | * 19 | * fog: 20 | * } 21 | */ 22 | /** 23 | * @classdesc 线线型材质
24 | * 注释内容部分参照 http://blog.csdn.net/omni360 25 | * @desc 据参数parameters创建线段的线线型材质,参数为JSON格式的属性参数 26 | * @param {String} parameters 材质参数 27 | * @extends {THREE.Material} 28 | * @constructor 29 | */ 30 | THREE.LineBasicMaterial = function ( parameters ) { 31 | 32 | THREE.Material.call( this ); 33 | /** 34 | * @default 'LineBasicMaterial' 35 | * @type {string} 36 | */ 37 | this.type = 'LineBasicMaterial'; 38 | /** 39 | * @desc 线材质颜色 40 | * @default 0xffffff 白色 41 | * @type {THREE.Color} 42 | */ 43 | this.color = new THREE.Color( 0xffffff ); 44 | /** 45 | * @desc 线的宽度 46 | * @default 47 | * @type {float} 48 | */ 49 | this.linewidth = 1; 50 | /** 51 | * @desc 线头类型 "round" 圆角 "butt" 平角 "square" 方角 52 | * @default "round" 圆角 53 | * @type {string} 54 | */ 55 | this.linecap = 'round'; 56 | /** 57 | * @desc 线连接类型 "bevel" 斜角 "round" 圆角 "miter" 尖角 58 | * @default "round" 圆角 59 | * @type {string} 60 | */ 61 | this.linejoin = 'round'; 62 | /** 63 | * @desc 线顶点颜色 64 | * @default THREE.NoColors 65 | * @type {number} 66 | */ 67 | this.vertexColors = THREE.NoColors; 68 | /** 69 | * @desc 雾效 70 | * @default 71 | * @type {boolean} 72 | */ 73 | this.fog = true; 74 | 75 | this.setValues( parameters ); 76 | 77 | }; 78 | /** 79 | * @desc LineBasicMaterial对象从THREE.Material的原型继承所有属性方法 80 | * @type {THREE.Material} 81 | */ 82 | THREE.LineBasicMaterial.prototype = Object.create( THREE.Material.prototype ); 83 | 84 | /** 85 | * @desc 线材质的克隆函数 86 | * @returns {THREE.LineBasicMaterial} 87 | */ 88 | THREE.LineBasicMaterial.prototype.clone = function () { 89 | 90 | var material = new THREE.LineBasicMaterial(); 91 | 92 | THREE.Material.prototype.clone.call( this, material ); 93 | 94 | material.color.copy( this.color ); 95 | 96 | material.linewidth = this.linewidth; 97 | material.linecap = this.linecap; 98 | material.linejoin = this.linejoin; 99 | 100 | material.vertexColors = this.vertexColors; 101 | 102 | material.fog = this.fog; 103 | 104 | return material; 105 | 106 | }; 107 | -------------------------------------------------------------------------------- /materials/LineDashedMaterial.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author alteredq / http://alteredqualia.com/ 3 | * 4 | * parameters = { 5 | * color: , 6 | * opacity: , 7 | * 8 | * blending: THREE.NormalBlending, 9 | * depthTest: , 10 | * depthWrite: , 11 | * 12 | * linewidth: , 13 | * 14 | * scale: , 15 | * dashSize: , 16 | * gapSize: , 17 | * 18 | * vertexColors: 19 | * 20 | * fog: 21 | * } 22 | */ 23 | /** 24 | * @classdesc 虚线线型材质
25 | * 注释内容部分参照 http://blog.csdn.net/omni360 26 | * @desc 据参数parameters创建线段的线线型材质,参数为JSON格式的属性参数 27 | * @param {String} parameters 材质参数 28 | * @extends {THREE.Material} 29 | * @constructor 30 | */ 31 | THREE.LineDashedMaterial = function ( parameters ) { 32 | 33 | THREE.Material.call( this ); 34 | /** 35 | * @default 'LineDashedMaterial' 36 | * @type {string} 37 | */ 38 | this.type = 'LineDashedMaterial'; 39 | /** 40 | * @desc 线材质颜色 41 | * @default 0xffffff 白色 42 | * @type {THREE.Color} 43 | */ 44 | this.color = new THREE.Color( 0xffffff ); 45 | /** 46 | * @desc 线的宽度 47 | * @default 48 | * @type {float} 49 | */ 50 | this.linewidth = 1; 51 | /** 52 | * @desc 虚线的线型比例属性 53 | * @default 54 | * @type {float} 55 | */ 56 | this.scale = 1; 57 | /** 58 | * @desc 虚线(点化线),线段的长度 59 | * @default 60 | * @type {float} 61 | */ 62 | this.dashSize = 3; 63 | /** 64 | * @desc 虚线(点化线)的线段间距长度 65 | * @default 66 | * @type {float} 67 | */ 68 | this.gapSize = 1; 69 | /** 70 | * @desc 线顶点颜色 71 | * @default THREE.NoColors 72 | * @type {number} 73 | */ 74 | this.vertexColors = false; 75 | /** 76 | * @desc 雾效 77 | * @default 78 | * @type {boolean} 79 | */ 80 | this.fog = true; 81 | 82 | this.setValues( parameters ); 83 | 84 | }; 85 | /** 86 | * @desc LineDashedMaterial对象从THREE.Material的原型继承所有属性方法 87 | * @type {THREE.Material} 88 | */ 89 | THREE.LineDashedMaterial.prototype = Object.create( THREE.Material.prototype ); 90 | /** 91 | * @desc 虚线材质的克隆函数 92 | * @returns {THREE.LineDashedMaterial} 93 | */ 94 | THREE.LineDashedMaterial.prototype.clone = function () { 95 | 96 | var material = new THREE.LineDashedMaterial(); 97 | 98 | THREE.Material.prototype.clone.call( this, material ); 99 | 100 | material.color.copy( this.color ); 101 | 102 | material.linewidth = this.linewidth; 103 | 104 | material.scale = this.scale; 105 | material.dashSize = this.dashSize; 106 | material.gapSize = this.gapSize; 107 | 108 | material.vertexColors = this.vertexColors; 109 | 110 | material.fog = this.fog; 111 | 112 | return material; 113 | 114 | }; 115 | -------------------------------------------------------------------------------- /objects/Sprite.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author mikael emtinger / http://gomo.se/ 3 | * @author alteredq / http://alteredqualia.com/ 4 | */ 5 | /** 6 | * @classdesc 点对象,也就是粒子对象
7 | * 注释内容部分参照 http://blog.csdn.net/omni360 8 | * @desc 通过BufferGeometry创建一个正对相机的类似buildborad的粒子点 9 | * @param {THREE.Material} material 材质 10 | * @constructor 11 | */ 12 | THREE.Sprite = ( function () { 13 | 14 | var indices = new Uint16Array( [ 0, 1, 2, 0, 2, 3 ] ); 15 | var vertices = new Float32Array( [ - 0.5, - 0.5, 0, 0.5, - 0.5, 0, 0.5, 0.5, 0, - 0.5, 0.5, 0 ] ); 16 | var uvs = new Float32Array( [ 0, 0, 1, 0, 1, 1, 0, 1 ] ); 17 | 18 | // 使用buffergeometry对象 19 | var geometry = new THREE.BufferGeometry(); 20 | // 索引,顶点,UV 21 | geometry.addAttribute( 'index', new THREE.BufferAttribute( indices, 1 ) ); 22 | geometry.addAttribute( 'position', new THREE.BufferAttribute( vertices, 3 ) ); 23 | geometry.addAttribute( 'uv', new THREE.BufferAttribute( uvs, 2 ) ); 24 | 25 | return function ( material ) { 26 | 27 | THREE.Object3D.call( this ); 28 | 29 | this.type = 'Sprite'; 30 | /** 31 | * @memberof THREE.Sprite 32 | * @desc 粒子对象的几何对象 33 | * @type {THREE.BufferGeometry} 34 | */ 35 | this.geometry = geometry; 36 | /** 37 | * 38 | * @memberof THREE.Sprite 39 | * @desc 粒子对象的材质对象 40 | * @type {THREE.Material} 41 | */ 42 | this.material = ( material !== undefined ) ? material : new THREE.SpriteMaterial(); 43 | 44 | }; 45 | 46 | } )(); 47 | /** 48 | * @desc Sprite从Objec3D的原型继承所有属性方法 49 | * @type {THREE.Object3D} 50 | */ 51 | THREE.Sprite.prototype = Object.create( THREE.Object3D.prototype ); 52 | /** 53 | * @function 54 | * @desc 粒子对象的拾取判断函数 55 | * @param {THREE.Raycaster} raycaster 拾取射线对象 56 | * @param {*} intersects 拾取结果对象数组 57 | */ 58 | THREE.Sprite.prototype.raycast = ( function () { 59 | 60 | var matrixPosition = new THREE.Vector3(); 61 | 62 | return function ( raycaster, intersects ) { 63 | 64 | matrixPosition.setFromMatrixPosition( this.matrixWorld ); 65 | // 点距离判断 66 | var distance = raycaster.ray.distanceToPoint( matrixPosition ); 67 | 68 | if ( distance > this.scale.x ) { 69 | 70 | return; 71 | 72 | } 73 | 74 | intersects.push( { 75 | 76 | distance: distance, 77 | point: this.position, 78 | face: null, 79 | object: this 80 | 81 | } ); 82 | 83 | }; 84 | 85 | }() ); 86 | /** 87 | * @desc Three.Sprite 克隆函数 88 | * @param {THREE.Sprite} object 89 | * @returns {THREE.Sprite} 90 | */ 91 | THREE.Sprite.prototype.clone = function ( object ) { 92 | 93 | if ( object === undefined ) object = new THREE.Sprite( this.material ); 94 | 95 | THREE.Object3D.prototype.clone.call( this, object ); 96 | 97 | return object; 98 | 99 | }; 100 | 101 | // Backwards compatibility 102 | /** 103 | * @classdesc 粒子对象,其实就是Sprite对象 104 | * @constructor 105 | */ 106 | THREE.Particle = THREE.Sprite; 107 | -------------------------------------------------------------------------------- /cameras/OrthographicCamera.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author alteredq / http://alteredqualia.com/ 3 | */ 4 | /** 5 | * @classdesc 正交投影相机
6 | * 注释内容部分参照 http://blog.csdn.net/omni360 7 | * @desc 根据 left, right, top, bottom, near, far 生成正交投影相 8 | * @constructor 9 | * @param {float} left 垂直平面的左侧坐标位置 10 | * @param {float} right 垂直平面的右侧坐标位置 11 | * @param {float} top 垂直平面的顶部坐标位置 12 | * @param {float} bottom 垂直平面的底部坐标位置 13 | * @param {float} near 相对于深度剪切面的近的距离,必须为正数,可选参数,如果未指定,初始化为0.1 14 | * @param {float} far 相对于深度剪切面的远的距离,必须为正数,可选参数,如果未指定,初始化为2000 15 | * @extends {THREE.Camera} 16 | */ 17 | THREE.OrthographicCamera = function ( left, right, top, bottom, near, far ) { 18 | 19 | THREE.Camera.call( this ); 20 | /** 21 | * @default 22 | * @type {string} 23 | */ 24 | this.type = 'OrthographicCamera'; 25 | /** 26 | * @desc 缩放级别 27 | * @default 28 | * @type {float} 29 | */ 30 | this.zoom = 1; 31 | /** 32 | * @desc 垂直平面的左侧坐标位置 33 | * @type {float} 34 | */ 35 | this.left = left; 36 | /** 37 | * @desc 垂直平面的右侧坐标位置 38 | * @type {float} 39 | */ 40 | this.right = right; 41 | /** 42 | * @desc 垂直平面的顶部坐标位置 43 | * @type {float} 44 | */ 45 | this.top = top; 46 | /** 47 | * @desc 垂直平面的底部坐标位置 48 | * @type {float} 49 | */ 50 | this.bottom = bottom; 51 | /** 52 | * @desc 指明相对于深度剪切面的近的距离,必须为正数,可选参数,如果未指定,初始化为0.1 53 | * @default 0.1 54 | * @type {float} 55 | */ 56 | this.near = ( near !== undefined ) ? near : 0.1; 57 | /** 58 | * @desc 指明相对于深度剪切面的近的距离,必须为正数,可选参数,如果未指定,初始化为0.1 59 | * @default 2000 60 | * @type {float} 61 | */ 62 | this.far = ( far !== undefined ) ? far : 2000; 63 | 64 | this.updateProjectionMatrix(); 65 | 66 | }; 67 | /** 68 | * @desc 正交相机对象从THREE.Camera的原型继承所有属性方法 69 | * @type {THREE.Camera} 70 | */ 71 | THREE.OrthographicCamera.prototype = Object.create( THREE.Camera.prototype ); 72 | 73 | /** 74 | * @desc 返回正交投影相机的可视边界的矩阵 75 | */ 76 | THREE.OrthographicCamera.prototype.updateProjectionMatrix = function () { 77 | 78 | var dx = ( this.right - this.left ) / ( 2 * this.zoom ); 79 | var dy = ( this.top - this.bottom ) / ( 2 * this.zoom ); 80 | var cx = ( this.right + this.left ) / 2; 81 | var cy = ( this.top + this.bottom ) / 2; 82 | 83 | this.projectionMatrix.makeOrthographic( cx - dx, cx + dx, cy + dy, cy - dy, this.near, this.far ); 84 | 85 | }; 86 | 87 | /** 88 | * @desc 克隆正交相机对象 89 | * @returns {THREE.OrthographicCamera} 90 | */ 91 | THREE.OrthographicCamera.prototype.clone = function () { 92 | 93 | var camera = new THREE.OrthographicCamera(); 94 | 95 | THREE.Camera.prototype.clone.call( this, camera ); 96 | 97 | camera.zoom = this.zoom; 98 | 99 | camera.left = this.left; 100 | camera.right = this.right; 101 | camera.top = this.top; 102 | camera.bottom = this.bottom; 103 | 104 | camera.near = this.near; 105 | camera.far = this.far; 106 | 107 | camera.projectionMatrix.copy( this.projectionMatrix ); 108 | 109 | return camera; 110 | }; 111 | -------------------------------------------------------------------------------- /cameras/CubeCamera.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Camera for rendering cube maps 3 | * - renders scene into axis-aligned cube 4 | * 5 | * @author alteredq / http://alteredqualia.com/ 6 | */ 7 | /** 8 | * @classdesc 立方体投影相机
9 | * 注释内容部分参照 http://blog.csdn.net/omni360 10 | * @desc 根据 near, far, cubeResolution 生成立方体投影相机 11 | * @constructor 12 | * @param {float} near 相对于深度剪切面的近的距离,必须为正数,可选参数,如果未指定,初始化为0.1 13 | * @param {float} far 相对于深度剪切面的远的距离,必须为正数,可选参数,如果未指定,初始化为2000 14 | * @param {float} cubeResolution 15 | * @extends {THREE.Camera} 16 | */ 17 | THREE.CubeCamera = function ( near, far, cubeResolution ) { //garreet 18 | 19 | THREE.Object3D.call( this ); 20 | 21 | this.type = 'CubeCamera'; 22 | 23 | var fov = 90, aspect = 1; 24 | 25 | var cameraPX = new THREE.PerspectiveCamera( fov, aspect, near, far ); 26 | cameraPX.up.set( 0, - 1, 0 ); 27 | cameraPX.lookAt( new THREE.Vector3( 1, 0, 0 ) ); 28 | this.add( cameraPX ); 29 | 30 | var cameraNX = new THREE.PerspectiveCamera( fov, aspect, near, far ); 31 | cameraNX.up.set( 0, - 1, 0 ); 32 | cameraNX.lookAt( new THREE.Vector3( - 1, 0, 0 ) ); 33 | this.add( cameraNX ); 34 | 35 | var cameraPY = new THREE.PerspectiveCamera( fov, aspect, near, far ); 36 | cameraPY.up.set( 0, 0, 1 ); 37 | cameraPY.lookAt( new THREE.Vector3( 0, 1, 0 ) ); 38 | this.add( cameraPY ); 39 | 40 | var cameraNY = new THREE.PerspectiveCamera( fov, aspect, near, far ); 41 | cameraNY.up.set( 0, 0, - 1 ); 42 | cameraNY.lookAt( new THREE.Vector3( 0, - 1, 0 ) ); 43 | this.add( cameraNY ); 44 | 45 | var cameraPZ = new THREE.PerspectiveCamera( fov, aspect, near, far ); 46 | cameraPZ.up.set( 0, - 1, 0 ); 47 | cameraPZ.lookAt( new THREE.Vector3( 0, 0, 1 ) ); 48 | this.add( cameraPZ ); 49 | 50 | var cameraNZ = new THREE.PerspectiveCamera( fov, aspect, near, far ); 51 | cameraNZ.up.set( 0, - 1, 0 ); 52 | cameraNZ.lookAt( new THREE.Vector3( 0, 0, - 1 ) ); 53 | this.add( cameraNZ ); 54 | 55 | this.renderTarget = new THREE.WebGLRenderTargetCube( cubeResolution, cubeResolution, { format: THREE.RGBFormat, magFilter: THREE.LinearFilter, minFilter: THREE.LinearFilter } ); 56 | 57 | this.updateCubeMap = function ( renderer, scene ) { 58 | 59 | var renderTarget = this.renderTarget; 60 | var generateMipmaps = renderTarget.generateMipmaps; 61 | 62 | renderTarget.generateMipmaps = false; 63 | 64 | renderTarget.activeCubeFace = 0; 65 | renderer.render( scene, cameraPX, renderTarget ); 66 | 67 | renderTarget.activeCubeFace = 1; 68 | renderer.render( scene, cameraNX, renderTarget ); 69 | 70 | renderTarget.activeCubeFace = 2; 71 | renderer.render( scene, cameraPY, renderTarget ); 72 | 73 | renderTarget.activeCubeFace = 3; 74 | renderer.render( scene, cameraNY, renderTarget ); 75 | 76 | renderTarget.activeCubeFace = 4; 77 | renderer.render( scene, cameraPZ, renderTarget ); 78 | 79 | renderTarget.generateMipmaps = generateMipmaps; 80 | 81 | renderTarget.activeCubeFace = 5; 82 | renderer.render( scene, cameraNZ, renderTarget ); 83 | 84 | }; 85 | 86 | }; 87 | 88 | THREE.CubeCamera.prototype = Object.create( THREE.Object3D.prototype ); 89 | -------------------------------------------------------------------------------- /materials/PointCloudMaterial.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author mrdoob / http://mrdoob.com/ 3 | * @author alteredq / http://alteredqualia.com/ 4 | * 5 | * parameters = { 6 | * color: , 7 | * opacity: , 8 | * map: new THREE.Texture( ), 9 | * 10 | * size: , 11 | * 12 | * blending: THREE.NormalBlending, 13 | * depthTest: , 14 | * depthWrite: , 15 | * 16 | * vertexColors: , 17 | * 18 | * fog: 19 | * } 20 | */ 21 | /** 22 | * @classdesc 点云(粒子系统)材质基类
23 | * 注释内容部分参照 http://blog.csdn.net/omni360 24 | * @param {String} parameters 材质参数 25 | * @extends {THREE.Material} 26 | * @constructor 27 | */ 28 | THREE.PointCloudMaterial = function ( parameters ) { 29 | 30 | THREE.Material.call( this ); 31 | /** 32 | * @default 'PointCloudMaterial' 33 | * @type {string} 34 | */ 35 | this.type = 'PointCloudMaterial'; 36 | /** 37 | * @desc 材质颜色 38 | * @default 0xffffff 白色 39 | * @type {THREE.Color} 40 | */ 41 | this.color = new THREE.Color( 0xffffff ); 42 | /** 43 | * @desc 纹理贴图 44 | * @default 45 | * @type {THREE.Texture} 46 | */ 47 | this.map = null; 48 | /** 49 | * @desc 点云点大小 50 | * @default 51 | * @type {number} 52 | */ 53 | this.size = 1; 54 | /** 55 | * @desc 粒子是否衰减 56 | * @default 57 | * @type {boolean} 58 | */ 59 | this.sizeAttenuation = true; 60 | /** 61 | * @desc 材质顶点颜色 62 | * @default THREE.NoColors 63 | * @type {number} 64 | */ 65 | this.vertexColors = THREE.NoColors; 66 | /** 67 | * @desc 雾效,默认开启 68 | * @default 69 | * @type {boolean} 70 | */ 71 | this.fog = true; 72 | 73 | this.setValues( parameters ); 74 | 75 | }; 76 | /** 77 | * @desc PointCloudMaterial对象从THREE.Material的原型继承所有属性方法 78 | * @type {THREE.Material} 79 | */ 80 | THREE.PointCloudMaterial.prototype = Object.create( THREE.Material.prototype ); 81 | /** 82 | * @desc PointCloudMaterial材质的克隆函数 83 | * @returns {THREE.PointCloudMaterial} 84 | */ 85 | THREE.PointCloudMaterial.prototype.clone = function () { 86 | 87 | var material = new THREE.PointCloudMaterial(); 88 | 89 | THREE.Material.prototype.clone.call( this, material ); 90 | 91 | material.color.copy( this.color ); 92 | 93 | material.map = this.map; 94 | 95 | material.size = this.size; 96 | material.sizeAttenuation = this.sizeAttenuation; 97 | 98 | material.vertexColors = this.vertexColors; 99 | 100 | material.fog = this.fog; 101 | 102 | return material; 103 | 104 | }; 105 | 106 | // backwards compatibility 107 | /** 108 | * @ignore 109 | */ 110 | THREE.ParticleBasicMaterial = function ( parameters ) { 111 | 112 | console.warn( 'THREE.ParticleBasicMaterial has been renamed to THREE.PointCloudMaterial.' ); 113 | return new THREE.PointCloudMaterial( parameters ); 114 | 115 | }; 116 | /** 117 | * @ignore 118 | */ 119 | THREE.ParticleSystemMaterial = function ( parameters ) { 120 | 121 | console.warn( 'THREE.ParticleSystemMaterial has been renamed to THREE.PointCloudMaterial.' ); 122 | return new THREE.PointCloudMaterial( parameters ); 123 | 124 | }; 125 | -------------------------------------------------------------------------------- /objects/LensFlare.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author mikael emtinger / http://gomo.se/ 3 | * @author alteredq / http://alteredqualia.com/ 4 | */ 5 | /** 6 | * @classdesc 透镜对象 7 | * @param {THREE.Texture} texture 纹理 8 | * @param {number} size 尺寸 9 | * @param {float} distance 距离 10 | * @param {number} blending blend方式 11 | * @param {THREE.Color} color 颜色 12 | * @constructor 13 | */ 14 | THREE.LensFlare = function ( texture, size, distance, blending, color ) { 15 | 16 | THREE.Object3D.call( this ); 17 | /** 18 | * @desc 透镜对象数组 19 | * @type {Array} 20 | */ 21 | this.lensFlares = []; 22 | /** 23 | * @desc 屏幕位置 24 | * @type {THREE.Vector3} 25 | */ 26 | this.positionScreen = new THREE.Vector3(); 27 | /** 28 | * @desc 更新回调函数 29 | * @type {*} 30 | */ 31 | this.customUpdateCallback = undefined; 32 | 33 | if( texture !== undefined ) { 34 | // 初始化 35 | this.add( texture, size, distance, blending, color ); 36 | 37 | } 38 | 39 | }; 40 | /** 41 | * @desc LensFlare从Objec3D的原型继承所有属性方法 42 | * @type {THREE.Object3D} 43 | */ 44 | THREE.LensFlare.prototype = Object.create( THREE.Object3D.prototype ); 45 | 46 | 47 | /* 48 | * Add: adds another flare 49 | */ 50 | /** 51 | * @desc 添加透镜 52 | * @param {THREE.Texture} texture 纹理 53 | * @param {number} size 尺寸 54 | * @param {float} distance 距离 55 | * @param {number} blending blend方式 56 | * @param {THREE.Color} color 颜色 57 | * @param {float} opacity 透明值 58 | */ 59 | THREE.LensFlare.prototype.add = function ( texture, size, distance, blending, color, opacity ) { 60 | 61 | if ( size === undefined ) size = - 1; 62 | if ( distance === undefined ) distance = 0; 63 | if ( opacity === undefined ) opacity = 1; 64 | if ( color === undefined ) color = new THREE.Color( 0xffffff ); 65 | if ( blending === undefined ) blending = THREE.NormalBlending; 66 | 67 | distance = Math.min( distance, Math.max( 0, distance ) ); 68 | 69 | this.lensFlares.push( { 70 | texture: texture, // THREE.Texture 71 | size: size, // size in pixels (-1 = use texture.width) 72 | distance: distance, // distance (0-1) from light source (0=at light source) 73 | x: 0, y: 0, z: 0, // screen position (-1 => 1) z = 0 is ontop z = 1 is back 74 | scale: 1, // scale 75 | rotation: 1, // rotation 76 | opacity: opacity, // opacity 77 | color: color, // color 78 | blending: blending // blending 79 | } ); 80 | 81 | }; 82 | 83 | /* 84 | * Update lens flares update positions on all flares based on the screen position 85 | * Set myLensFlare.customUpdateCallback to alter the flares in your project specific way. 86 | */ 87 | /** 88 | * @desc 更新透镜对象的位置,旋转等参数 89 | */ 90 | THREE.LensFlare.prototype.updateLensFlares = function () { 91 | 92 | var f, fl = this.lensFlares.length; 93 | var flare; 94 | var vecX = - this.positionScreen.x * 2; 95 | var vecY = - this.positionScreen.y * 2; 96 | 97 | for( f = 0; f < fl; f ++ ) { 98 | 99 | flare = this.lensFlares[ f ]; 100 | 101 | flare.x = this.positionScreen.x + vecX * flare.distance; 102 | flare.y = this.positionScreen.y + vecY * flare.distance; 103 | 104 | flare.wantedRotation = flare.x * Math.PI * 0.25; 105 | flare.rotation += ( flare.wantedRotation - flare.rotation ) * 0.25; 106 | 107 | } 108 | 109 | }; 110 | 111 | -------------------------------------------------------------------------------- /core/Face3.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author mrdoob / http://mrdoob.com/ 3 | * @author alteredq / http://alteredqualia.com/ 4 | */ 5 | /** 6 | * @classdesc 三角面对象类(三维空间内)
7 | * 注释内容部分参照 http://blog.csdn.net/omni360 8 | * @param {THREE.Vector3} a 三角面角点a的索引 9 | * @param {THREE.Vector3} b 三角面角点b的索引 10 | * @param {THREE.Vector3} c 三角面角点c的索引 11 | * @param {THREE.Vector3[]} normal 三角面法线向量,或顶点法线向量数组 12 | * @param {THREE.Color[]} color 三角面颜色值,或顶点颜色值数组 13 | * @param {number[]} materialIndex 材质索引数组 14 | * @example 用法: 创建一个颜色为0xffaa00,0x00aaff,0x00ffaa的a,b,c三点组成的,法线指向normal,材质索引为0的三角面对象
15 | * var a=0,b=1,c=2;
16 | * var normal1 = new THREE.Vector3( 0, 1, 0 ), normal2 = new THREE.Vector3( 0, 1, 0 ), normal3 = new THREE.Vector3( 0, 1, 0 );
17 | * normal = new Array(normal1,normal2,normal3);
18 | * var color1 = new THREE.Color( 0xffaa00 ), color2 = new THREE.Color( 0x00aaff ), color3 = new THREE.Color( 0x00ffaa );
19 | * var color = new Array(color1,color2,color3);
20 | * var face = new THREE.Face3( a, b, c, normal, color, 0 );
21 | * 创建一个颜色为0xffaa00,0x00aaff,0x00ffaa的a,b,c三点组成的,法线指向normal,材质索引为0的三角面对象 22 | * @constructor 23 | */ 24 | THREE.Face3 = function ( a, b, c, normal, color, materialIndex ) { 25 | 26 | /** 27 | * @desc 顶点a 28 | * @type {THREE.Vector3} 29 | */ 30 | this.a = a; 31 | /** 32 | * @desc 顶点b 33 | * @type {THREE.Vector3} 34 | */ 35 | this.b = b; 36 | /** 37 | * @desc 顶点c 38 | * @type {THREE.Vector3} 39 | */ 40 | this.c = c; 41 | 42 | /** 43 | * @desc 面法线 44 | * @type {THREE.Vector3} 45 | */ 46 | this.normal = normal instanceof THREE.Vector3 ? normal : new THREE.Vector3(); 47 | /** 48 | * @desc 顶点法线 49 | * @type {THREE.Vector3[]} 50 | */ 51 | this.vertexNormals = normal instanceof Array ? normal : []; 52 | 53 | /** 54 | * @desc 面颜色 55 | * @type {THREE.Color} 56 | */ 57 | this.color = color instanceof THREE.Color ? color : new THREE.Color(); 58 | /** 59 | * @desc 顶点颜色 60 | * @type {THREE.Color[]} 61 | */ 62 | this.vertexColors = color instanceof Array ? color : []; 63 | 64 | /** 65 | * @desc 顶点正切数组 66 | * @type {Array} 67 | */ 68 | this.vertexTangents = []; 69 | 70 | /** 71 | * @desc 三角面的材质索引 72 | * @type {number} 73 | */ 74 | this.materialIndex = materialIndex !== undefined ? materialIndex : 0; 75 | 76 | }; 77 | 78 | THREE.Face3.prototype = { 79 | 80 | constructor: THREE.Face3, 81 | /** 82 | * @desc 克隆三角面对象 83 | * @returns {THREE.Face3} 84 | */ 85 | clone: function () { 86 | 87 | var face = new THREE.Face3( this.a, this.b, this.c ); 88 | 89 | face.normal.copy( this.normal ); 90 | face.color.copy( this.color ); 91 | 92 | face.materialIndex = this.materialIndex; 93 | 94 | for ( var i = 0, il = this.vertexNormals.length; i < il; i ++ ) { 95 | 96 | face.vertexNormals[ i ] = this.vertexNormals[ i ].clone(); 97 | 98 | } 99 | 100 | for ( var i = 0, il = this.vertexColors.length; i < il; i ++ ) { 101 | 102 | face.vertexColors[ i ] = this.vertexColors[ i ].clone(); 103 | 104 | } 105 | 106 | for ( var i = 0, il = this.vertexTangents.length; i < il; i ++ ) { 107 | 108 | face.vertexTangents[ i ] = this.vertexTangents[ i ].clone(); 109 | 110 | } 111 | 112 | return face; 113 | 114 | } 115 | 116 | }; 117 | -------------------------------------------------------------------------------- /core/EventDispatcher.js: -------------------------------------------------------------------------------- 1 | /** 2 | * https://github.com/mrdoob/eventdispatcher.js/ 3 | */ 4 | /** 5 | * @classdesc 事件调度类
6 | * 注释内容部分参照 http://blog.csdn.net/omni360 7 | * @desc 用来管理侦听函数,被嵌入Object3D对象之上.当Object3D发生事件时,这个方法就会自动被触发.
8 | * 可以通过调用调度该事件的对象的 addEventListener() 方法来注册函数以处理运行时事件 9 | * @constructor 10 | */ 11 | THREE.EventDispatcher = function () {} 12 | 13 | THREE.EventDispatcher.prototype = { 14 | 15 | constructor: THREE.EventDispatcher, 16 | /** 17 | * @desc 将当前基类绑定到参数Object对象之上,将基类的方法添加到object对象内 18 | * @param {THREE.Object3D} object 19 | */ 20 | apply: function ( object ) { 21 | 22 | object.addEventListener = THREE.EventDispatcher.prototype.addEventListener; 23 | object.hasEventListener = THREE.EventDispatcher.prototype.hasEventListener; 24 | object.removeEventListener = THREE.EventDispatcher.prototype.removeEventListener; 25 | object.dispatchEvent = THREE.EventDispatcher.prototype.dispatchEvent; 26 | 27 | }, 28 | /** 29 | * @desc 使用 EventDispatcher 对象注册事件侦听器对象,以使侦听器能够接收事件通知 30 | * @param {String} type 事件类型 31 | * @param {requestCallback} listener 监听回调函数 32 | */ 33 | addEventListener: function ( type, listener ) { 34 | 35 | if ( this._listeners === undefined ) this._listeners = {}; 36 | 37 | var listeners = this._listeners; 38 | 39 | if ( listeners[ type ] === undefined ) { 40 | 41 | listeners[ type ] = []; 42 | 43 | } 44 | 45 | if ( listeners[ type ].indexOf( listener ) === - 1 ) { 46 | 47 | listeners[ type ].push( listener ); 48 | 49 | } 50 | 51 | }, 52 | /** 53 | * @desc 检查 EventDispatcher 对象是否为特定事件类型注册了任何侦听器 54 | * @param {String} type 事件类型 55 | * @param {requestCallback} listener 56 | * @returns {boolean} 监听回调函数 57 | */ 58 | hasEventListener: function ( type, listener ) { 59 | 60 | if ( this._listeners === undefined ) return false; 61 | 62 | var listeners = this._listeners; 63 | 64 | if ( listeners[ type ] !== undefined && listeners[ type ].indexOf( listener ) !== - 1 ) { 65 | 66 | return true; 67 | 68 | } 69 | 70 | return false; 71 | 72 | }, 73 | 74 | /** 75 | * @desc 从 EventDispatcher 对象中删除为特定事件类型注册了任何侦听器 76 | * @param {String} type 事件类型 77 | * @param {requestCallback} listener 78 | */ 79 | removeEventListener: function ( type, listener ) { 80 | 81 | if ( this._listeners === undefined ) return; 82 | 83 | var listeners = this._listeners; 84 | var listenerArray = listeners[ type ]; 85 | 86 | if ( listenerArray !== undefined ) { 87 | 88 | var index = listenerArray.indexOf( listener ); 89 | 90 | if ( index !== - 1 ) { 91 | 92 | listenerArray.splice( index, 1 ); 93 | 94 | } 95 | 96 | } 97 | 98 | }, 99 | /** 100 | * @desc 将事件调度到事件流中
101 | * 事件目标是对其调用 dispatchEvent() 方法的 EventDispatcher 对象
102 | * 如果正在重新调度事件,则会自动创建此事件的一个克隆
103 | * 在调度了事件后,其 target 属性将无法更改,因此您必须创建此事件的一个新副本以能够重新调度 104 | * @param event 事件 105 | */ 106 | dispatchEvent: function ( event ) { 107 | 108 | if ( this._listeners === undefined ) return; 109 | 110 | var listeners = this._listeners; 111 | var listenerArray = listeners[ event.type ]; 112 | 113 | if ( listenerArray !== undefined ) { 114 | 115 | event.target = this; 116 | 117 | var array = []; 118 | var length = listenerArray.length; 119 | 120 | for ( var i = 0; i < length; i ++ ) { 121 | 122 | array[ i ] = listenerArray[ i ]; 123 | 124 | } 125 | 126 | for ( var i = 0; i < length; i ++ ) { 127 | 128 | array[ i ].call( this, event ); 129 | 130 | } 131 | 132 | } 133 | 134 | } 135 | 136 | }; 137 | -------------------------------------------------------------------------------- /renderers/shaders/UniformsLib.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Uniforms library for shared webgl shaders 3 | */ 4 | /** 5 | * @classdesc Uniforms库,包含各种定义的shader的uniform组成 6 | * @memberof THREE 7 | * @constructor 8 | */ 9 | THREE.UniformsLib = { 10 | 11 | /** 12 | * @desc 普通渲染参数 13 | */ 14 | common: { 15 | 16 | "diffuse" : { type: "c", value: new THREE.Color( 0xeeeeee ) }, 17 | "opacity" : { type: "f", value: 1.0 }, 18 | 19 | "map" : { type: "t", value: null }, 20 | "offsetRepeat" : { type: "v4", value: new THREE.Vector4( 0, 0, 1, 1 ) }, 21 | 22 | "lightMap" : { type: "t", value: null }, 23 | "specularMap" : { type: "t", value: null }, 24 | "alphaMap" : { type: "t", value: null }, 25 | 26 | "envMap" : { type: "t", value: null }, 27 | "flipEnvMap" : { type: "f", value: - 1 }, 28 | "useRefract" : { type: "i", value: 0 }, 29 | "reflectivity" : { type: "f", value: 1.0 }, 30 | "refractionRatio" : { type: "f", value: 0.98 }, 31 | "combine" : { type: "i", value: 0 }, 32 | 33 | "morphTargetInfluences" : { type: "f", value: 0 } 34 | 35 | }, 36 | 37 | /** 38 | * @desc 碰撞参数 39 | */ 40 | bump: { 41 | 42 | "bumpMap" : { type: "t", value: null }, 43 | "bumpScale" : { type: "f", value: 1 } 44 | 45 | }, 46 | /** 47 | * @desc 法线贴图参数 48 | */ 49 | normalmap: { 50 | 51 | "normalMap" : { type: "t", value: null }, 52 | "normalScale" : { type: "v2", value: new THREE.Vector2( 1, 1 ) } 53 | }, 54 | /** 55 | * @desc 雾效果参数 56 | */ 57 | fog : { 58 | 59 | "fogDensity" : { type: "f", value: 0.00025 }, 60 | "fogNear" : { type: "f", value: 1 }, 61 | "fogFar" : { type: "f", value: 2000 }, 62 | "fogColor" : { type: "c", value: new THREE.Color( 0xffffff ) } 63 | 64 | }, 65 | /** 66 | * @desc 光照效果参数 67 | */ 68 | lights: { 69 | 70 | "ambientLightColor" : { type: "fv", value: [] }, 71 | 72 | "directionalLightDirection" : { type: "fv", value: [] }, 73 | "directionalLightColor" : { type: "fv", value: [] }, 74 | 75 | "hemisphereLightDirection" : { type: "fv", value: [] }, 76 | "hemisphereLightSkyColor" : { type: "fv", value: [] }, 77 | "hemisphereLightGroundColor" : { type: "fv", value: [] }, 78 | 79 | "pointLightColor" : { type: "fv", value: [] }, 80 | "pointLightPosition" : { type: "fv", value: [] }, 81 | "pointLightDistance" : { type: "fv1", value: [] }, 82 | 83 | "spotLightColor" : { type: "fv", value: [] }, 84 | "spotLightPosition" : { type: "fv", value: [] }, 85 | "spotLightDirection" : { type: "fv", value: [] }, 86 | "spotLightDistance" : { type: "fv1", value: [] }, 87 | "spotLightAngleCos" : { type: "fv1", value: [] }, 88 | "spotLightExponent" : { type: "fv1", value: [] } 89 | 90 | }, 91 | /** 92 | * @desc 粒子效果参数 93 | */ 94 | particle: { 95 | 96 | "psColor" : { type: "c", value: new THREE.Color( 0xeeeeee ) }, 97 | "opacity" : { type: "f", value: 1.0 }, 98 | "size" : { type: "f", value: 1.0 }, 99 | "scale" : { type: "f", value: 1.0 }, 100 | "map" : { type: "t", value: null }, 101 | 102 | "fogDensity" : { type: "f", value: 0.00025 }, 103 | "fogNear" : { type: "f", value: 1 }, 104 | "fogFar" : { type: "f", value: 2000 }, 105 | "fogColor" : { type: "c", value: new THREE.Color( 0xffffff ) } 106 | 107 | }, 108 | /** 109 | * @desc 阴影贴图效果参数 110 | */ 111 | shadowmap: { 112 | 113 | "shadowMap": { type: "tv", value: [] }, 114 | "shadowMapSize": { type: "v2v", value: [] }, 115 | 116 | "shadowBias" : { type: "fv1", value: [] }, 117 | "shadowDarkness": { type: "fv1", value: [] }, 118 | 119 | "shadowMatrix" : { type: "m4v", value: [] } 120 | 121 | } 122 | 123 | }; 124 | -------------------------------------------------------------------------------- /renderers/WebGLRenderTarget.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author szimek / https://github.com/szimek/ 3 | * @author alteredq / http://alteredqualia.com/ 4 | */ 5 | /** 6 | * @classdesc 渲染目标对象 7 | * @desc 通过options设置渲染目标对象,参数见对象的成员变量 8 | * @param {number} width 宽度 9 | * @param {number} height 高度 10 | * @param {*} options 参数列表 11 | * @constructor 12 | */ 13 | THREE.WebGLRenderTarget = function ( width, height, options ) { 14 | /** 15 | * @desc 宽度 16 | * @type {number} 17 | */ 18 | this.width = width; 19 | /** 20 | * @desc 高度 21 | * @type {number} 22 | */ 23 | this.height = height; 24 | 25 | options = options || {}; 26 | /** 27 | * @desc 纹理横轴覆盖模式 28 | * @type {number} 29 | */ 30 | this.wrapS = options.wrapS !== undefined ? options.wrapS : THREE.ClampToEdgeWrapping; 31 | /** 32 | * @desc 纹理纵轴覆盖模式 33 | * @type {number} 34 | */ 35 | this.wrapT = options.wrapT !== undefined ? options.wrapT : THREE.ClampToEdgeWrapping; 36 | /** 37 | * @desc 纹理扩大插值模式 38 | * @type {number} 39 | */ 40 | this.magFilter = options.magFilter !== undefined ? options.magFilter : THREE.LinearFilter; 41 | /** 42 | * @desc 纹理缩小插值模式 43 | * @type {number} 44 | */ 45 | this.minFilter = options.minFilter !== undefined ? options.minFilter : THREE.LinearMipMapLinearFilter; 46 | /** 47 | * @desc 各向异性参数 48 | * @type {number} 49 | */ 50 | this.anisotropy = options.anisotropy !== undefined ? options.anisotropy : 1; 51 | /** 52 | * @desc 纹理起始偏移 53 | * @type {number} 54 | */ 55 | this.offset = new THREE.Vector2( 0, 0 ); 56 | /** 57 | * @desc 纹理重复参数 58 | * @type {number} 59 | */ 60 | this.repeat = new THREE.Vector2( 1, 1 ); 61 | /** 62 | * @desc 纹理颜色格式 63 | * @type {number} 64 | */ 65 | this.format = options.format !== undefined ? options.format : THREE.RGBAFormat; 66 | /** 67 | * @desc 纹理数据字节大小 68 | * @type {number} 69 | */ 70 | this.type = options.type !== undefined ? options.type : THREE.UnsignedByteType; 71 | /** 72 | * @desc 是否是深度缓冲 73 | * @type {boolean} 74 | */ 75 | this.depthBuffer = options.depthBuffer !== undefined ? options.depthBuffer : true; 76 | /** 77 | * @desc 是否是模板缓冲 78 | * @type {number} 79 | */ 80 | this.stencilBuffer = options.stencilBuffer !== undefined ? options.stencilBuffer : true; 81 | /** 82 | * @desc 是否生成Mipmap 83 | * @type {boolean} 84 | */ 85 | this.generateMipmaps = true; 86 | /** 87 | * @desc 共享深度连接 88 | * @type {*} 89 | */ 90 | this.shareDepthFrom = null; 91 | 92 | }; 93 | 94 | THREE.WebGLRenderTarget.prototype = { 95 | 96 | constructor: THREE.WebGLRenderTarget, 97 | /** 98 | * @desc 设置渲染目标的尺寸 99 | * @param {number} width 宽度 100 | * @param {number} height 高度 101 | */ 102 | setSize: function ( width, height ) { 103 | 104 | this.width = width; 105 | this.height = height; 106 | 107 | }, 108 | /** 109 | * @desc 渲染目标的克隆 110 | * @returns {THREE.WebGLRenderTarget} 111 | */ 112 | clone: function () { 113 | 114 | var tmp = new THREE.WebGLRenderTarget( this.width, this.height ); 115 | 116 | tmp.wrapS = this.wrapS; 117 | tmp.wrapT = this.wrapT; 118 | 119 | tmp.magFilter = this.magFilter; 120 | tmp.minFilter = this.minFilter; 121 | 122 | tmp.anisotropy = this.anisotropy; 123 | 124 | tmp.offset.copy( this.offset ); 125 | tmp.repeat.copy( this.repeat ); 126 | 127 | tmp.format = this.format; 128 | tmp.type = this.type; 129 | 130 | tmp.depthBuffer = this.depthBuffer; 131 | tmp.stencilBuffer = this.stencilBuffer; 132 | 133 | tmp.generateMipmaps = this.generateMipmaps; 134 | 135 | tmp.shareDepthFrom = this.shareDepthFrom; 136 | 137 | return tmp; 138 | 139 | }, 140 | /** 141 | * @desc WebGLRenderTarget的销毁事件 142 | */ 143 | dispose: function () { 144 | 145 | this.dispatchEvent( { type: 'dispose' } ); 146 | 147 | } 148 | 149 | }; 150 | 151 | THREE.EventDispatcher.prototype.apply( THREE.WebGLRenderTarget.prototype ); 152 | -------------------------------------------------------------------------------- /core/Raycaster.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author mrdoob / http://mrdoob.com/ 3 | * @author bhouston / http://exocortex.com/ 4 | * @author stephomi / http://stephaneginier.com/ 5 | */ 6 | 7 | ( function ( THREE ) { 8 | /** 9 | * @classdesc 射线拾取对象
10 | * 注释内容部分参照 http://blog.csdn.net/omni360 11 | * @param {THREE.Vector3} origin 射线起点 12 | * @param {THREE.Vector3} direction 射线方向 13 | * @param {float} near 最近距离 14 | * @param {float} far 最远距离 15 | * @constructor 16 | */ 17 | THREE.Raycaster = function ( origin, direction, near, far ) { 18 | /** 19 | * @desc 射线 20 | * @type {THREE.Ray} 21 | */ 22 | this.ray = new THREE.Ray( origin, direction ); 23 | // direction is assumed to be normalized (for accurate distance calculations) 24 | /** 25 | * @desc 最近距离 26 | * @default 0 27 | * @type {float} 28 | */ 29 | this.near = near || 0; 30 | /** 31 | * @desc 最远距离 32 | * @default Infinity 33 | * @type {float} 34 | */ 35 | this.far = far || Infinity; 36 | /** 37 | * @desc 拾取结果 38 | * @type {*} 39 | */ 40 | this.params = { 41 | Sprite: {}, 42 | Mesh: {}, 43 | PointCloud: { threshold: 1 }, 44 | LOD: {}, 45 | Line: {} 46 | }; 47 | 48 | }; 49 | /** 50 | * @desc 距离降序排序方法 51 | * @param {THREE.Object3D} a 52 | * @param {THREE.Object3D} b 53 | * @returns {float} 54 | */ 55 | var descSort = function ( a, b ) { 56 | 57 | return a.distance - b.distance; 58 | 59 | }; 60 | /** 61 | * @desc 插入对象 62 | * @param {THREE.Object3D} object 63 | * @param {THREE.Raycaster} raycaster 64 | * @param {*} intersects 拾取结果对象数组,结果添加至数组 65 | * @param {boolean} recursive 是否递归判断子对象 66 | */ 67 | var intersectObject = function ( object, raycaster, intersects, recursive ) { 68 | 69 | object.raycast( raycaster, intersects ); 70 | 71 | if ( recursive === true ) { 72 | 73 | var children = object.children; 74 | 75 | for ( var i = 0, l = children.length; i < l; i ++ ) { 76 | 77 | intersectObject( children[ i ], raycaster, intersects, true ); 78 | 79 | } 80 | 81 | } 82 | 83 | }; 84 | 85 | // 86 | 87 | THREE.Raycaster.prototype = { 88 | 89 | constructor: THREE.Raycaster, 90 | /** 91 | * @desc 拾取精度 92 | * @default 93 | * @type {float} 94 | */ 95 | precision: 0.0001, 96 | /** 97 | * @desc 线的精度 98 | * @default 99 | * @type {float} 100 | */ 101 | linePrecision: 1, 102 | /** 103 | * @desc 设置拾取对象 104 | * @param {THREE.Ray} origin 射线起点 105 | * @param {THREE.Vector3} direction 射线方向 106 | */ 107 | set: function ( origin, direction ) { 108 | 109 | this.ray.set( origin, direction ); 110 | // direction is assumed to be normalized (for accurate distance calculations) 111 | 112 | }, 113 | /** 114 | * @desc 拾取相交判断 115 | * @param {THREE.Object3D} object 需要判断对象 116 | * @param {boolean} recursive 是否递归 117 | * @returns {*} 被拾取对象数组 118 | */ 119 | intersectObject: function ( object, recursive ) { 120 | 121 | var intersects = []; 122 | 123 | intersectObject( object, this, intersects, recursive ); 124 | 125 | intersects.sort( descSort ); 126 | 127 | return intersects; 128 | 129 | }, 130 | /** 131 | * @desc 拾取相交判断 132 | * @param {THREE.Object3D} objects 需要判断对象数组 133 | * @param {boolean} recursive 是否递归 134 | * @returns {*} 被拾取对象数组 135 | */ 136 | intersectObjects: function ( objects, recursive ) { 137 | 138 | var intersects = []; 139 | 140 | if ( objects instanceof Array === false ) { 141 | 142 | console.log( 'THREE.Raycaster.intersectObjects: objects is not an Array.' ); 143 | return intersects; 144 | 145 | } 146 | 147 | for ( var i = 0, l = objects.length; i < l; i ++ ) { 148 | 149 | intersectObject( objects[ i ], this, intersects, recursive ); 150 | 151 | } 152 | 153 | intersects.sort( descSort ); 154 | 155 | return intersects; 156 | 157 | } 158 | 159 | }; 160 | 161 | }( THREE ) ); 162 | -------------------------------------------------------------------------------- /objects/LOD.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author mikael emtinger / http://gomo.se/ 3 | * @author alteredq / http://alteredqualia.com/ 4 | * @author mrdoob / http://mrdoob.com/ 5 | */ 6 | /** 7 | * @classdesc LOD对象
8 | * 注释内容部分参照 http://blog.csdn.net/omni360 9 | * @desc LOD技术即Levels of Detail的简称,意为多细节层次。
10 | * LOD技术指根据物体模型的节点在显示环境中所处的位置和重要度
11 | * 决定物体渲染的资源分配,降低非重要物体的面数和细节度,从而获得高效率的渲染运算。 12 | * @constructor 13 | */ 14 | THREE.LOD = function () { 15 | 16 | THREE.Object3D.call( this ); 17 | /** 18 | * @desc 对象数组 19 | * @type {Array} 20 | */ 21 | this.objects = []; 22 | 23 | }; 24 | 25 | /** 26 | * @desc LOD.Objec3D的原型继承所有属性方法 27 | * @type {THREE.Object3D} 28 | */ 29 | THREE.LOD.prototype = Object.create( THREE.Object3D.prototype ); 30 | /** 31 | * @desc 将对象(参数object)根据参数distance插入到存放层次细节展示的对象集合中(LOD.Objects) 32 | * @param {THREE.Object3D} object 3D对象 33 | * @param {float} distance 层次距离 34 | */ 35 | THREE.LOD.prototype.addLevel = function ( object, distance ) { 36 | 37 | if ( distance === undefined ) distance = 0; 38 | 39 | distance = Math.abs( distance ); 40 | 41 | for ( var l = 0; l < this.objects.length; l ++ ) { 42 | 43 | if ( distance < this.objects[ l ].distance ) { 44 | 45 | break; 46 | 47 | } 48 | 49 | } 50 | 51 | this.objects.splice( l, 0, { distance: distance, object: object } ); 52 | this.add( object ); 53 | 54 | }; 55 | /** 56 | * @desc 根据距离返回对应层次的对象 57 | * @param {float} distance 层次距离 58 | * @returns {THREE.Object3D} 59 | */ 60 | THREE.LOD.prototype.getObjectForDistance = function ( distance ) { 61 | //排序由小到大遍历 62 | for ( var i = 1, l = this.objects.length; i < l; i ++ ) { 63 | 64 | if ( distance < this.objects[ i ].distance ) { 65 | 66 | break; 67 | 68 | } 69 | 70 | } 71 | 72 | return this.objects[ i - 1 ].object; 73 | 74 | }; 75 | /** 76 | * @function 77 | * @desc LOD的拾取判断函数 78 | * @param {THREE.Raycaster} raycaster 拾取射线对象 79 | * @param {*} intersects 拾取结果对象数组 80 | */ 81 | THREE.LOD.prototype.raycast = ( function () { 82 | 83 | var matrixPosition = new THREE.Vector3(); 84 | 85 | return function ( raycaster, intersects ) { 86 | 87 | matrixPosition.setFromMatrixPosition( this.matrixWorld ); 88 | 89 | var distance = raycaster.ray.origin.distanceTo( matrixPosition ); 90 | 91 | //将当前层次的对象,进行光线跟踪计算. 92 | this.getObjectForDistance( distance ).raycast( raycaster, intersects ); 93 | 94 | }; 95 | 96 | }() ); 97 | /** 98 | * @function 99 | * @desc 根据相机的位置更新显示的层次 100 | * @param {THREE.Camera} camera 相机 101 | * @return {THREE.Lod} 新的LOD对象 102 | */ 103 | THREE.LOD.prototype.update = function () { 104 | 105 | var v1 = new THREE.Vector3(); 106 | var v2 = new THREE.Vector3(); 107 | 108 | return function ( camera ) { 109 | 110 | if ( this.objects.length > 1 ) { 111 | 112 | v1.setFromMatrixPosition( camera.matrixWorld ); 113 | v2.setFromMatrixPosition( this.matrixWorld ); 114 | 115 | // 重新计算相机的位置到当前层次的距离 116 | var distance = v1.distanceTo( v2 ); 117 | 118 | this.objects[ 0 ].object.visible = true; 119 | 120 | for ( var i = 1, l = this.objects.length; i < l; i ++ ) { 121 | // 如果计算相机的位置到当前层次的距离大于当前对象的距离 122 | if ( distance >= this.objects[ i ].distance ) { 123 | // 计算相机的位置到当前层次的距离之前的对象不显示 124 | this.objects[ i - 1 ].object.visible = false; 125 | // 计算相机的位置到当前层次的距离之后的对象显示. 126 | this.objects[ i ].object.visible = true; 127 | 128 | } else { 129 | 130 | break; 131 | 132 | } 133 | 134 | } 135 | 136 | for ( ; i < l; i ++ ) { 137 | 138 | this.objects[ i ].object.visible = false; 139 | 140 | } 141 | 142 | } 143 | 144 | }; 145 | 146 | }(); 147 | /** 148 | * @desc Three.LOD 拷贝函数 149 | * @param {THREE.LOD} object 150 | * @returns {THREE.LOD} 151 | */ 152 | THREE.LOD.prototype.clone = function ( object ) { 153 | 154 | if ( object === undefined ) object = new THREE.LOD(); 155 | 156 | THREE.Object3D.prototype.clone.call( this, object ); 157 | 158 | for ( var i = 0, l = this.objects.length; i < l; i ++ ) { 159 | var x = this.objects[ i ].object.clone(); 160 | x.visible = i === 0; 161 | object.addLevel( x, this.objects[ i ].distance ); 162 | } 163 | 164 | return object; 165 | 166 | }; 167 | -------------------------------------------------------------------------------- /objects/Line.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author mrdoob / http://mrdoob.com/ 3 | */ 4 | /** 5 | * @classdesc 线对象
6 | * 注释内容部分参照 http://blog.csdn.net/omni360 7 | * @desc WebGL中好像线不能设置宽度 8 | * @param {THREE.Geometry} geometry 几何信息 9 | * @param {THREE.Material} material 材质信息 10 | * @param {number} mode 线型 11 | * @extends {THREE.Object3D} 12 | * @constructor 13 | */ 14 | THREE.Line = function ( geometry, material, mode ) { 15 | 16 | THREE.Object3D.call( this ); 17 | /** 18 | * @default 'Line' 19 | * @type {string} 20 | */ 21 | this.type = 'Line'; 22 | 23 | /** 24 | * @desc 几何信息 25 | * @default THREE.Geometry() 26 | * @type {THREE.Geometry} 27 | */ 28 | this.geometry = geometry !== undefined ? geometry : new THREE.Geometry(); 29 | /** 30 | * @desc 材质信息 31 | * @default THREE.LineBasicMaterial() 随机颜色的线 32 | * @type {THREE.Geometry} 33 | */ 34 | this.material = material !== undefined ? material : new THREE.LineBasicMaterial( { color: Math.random() * 0xffffff } ); 35 | /** 36 | * @desc 线的绘制方式 37 | * @default THREE.LineStrip 38 | * @type {number} 39 | */ 40 | this.mode = ( mode !== undefined ) ? mode : THREE.LineStrip; 41 | 42 | }; 43 | /** 44 | * @memberof THREE 45 | * @desc 线型定义 46 | * @default 47 | * @type {number} 48 | */ 49 | THREE.LineStrip = 0; 50 | /** 51 | * @memberof THREE 52 | * @desc 线型定义 53 | * @default 54 | * @type {number} 55 | */ 56 | THREE.LinePieces = 1; 57 | /** 58 | * @desc Line对象从THREE.Objec3D的原型继承所有属性方法 59 | * @type {THREE.Object3D} 60 | */ 61 | THREE.Line.prototype = Object.create( THREE.Object3D.prototype ); 62 | /** 63 | * @function 64 | * @desc 线的拾取判断函数 65 | * @param {THREE.Raycaster} raycaster 拾取射线对象 66 | * @param {*} intersects 拾取结果对象数组 67 | */ 68 | THREE.Line.prototype.raycast = ( function () { 69 | 70 | var inverseMatrix = new THREE.Matrix4(); 71 | var ray = new THREE.Ray(); 72 | var sphere = new THREE.Sphere(); 73 | 74 | return function ( raycaster, intersects ) { 75 | 76 | var precision = raycaster.linePrecision; 77 | var precisionSq = precision * precision; 78 | 79 | var geometry = this.geometry; 80 | 81 | if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere(); 82 | 83 | // Checking boundingSphere distance to ray 84 | // 先进行外包围球体判断 85 | sphere.copy( geometry.boundingSphere ); 86 | sphere.applyMatrix4( this.matrixWorld ); 87 | 88 | if ( raycaster.ray.isIntersectionSphere( sphere ) === false ) { 89 | 90 | return; 91 | 92 | } 93 | 94 | inverseMatrix.getInverse( this.matrixWorld ); 95 | ray.copy( raycaster.ray ).applyMatrix4( inverseMatrix ); 96 | 97 | /* if ( geometry instanceof THREE.BufferGeometry ) { 98 | 99 | } else */ if ( geometry instanceof THREE.Geometry ) { 100 | 101 | var vertices = geometry.vertices; 102 | var nbVertices = vertices.length; 103 | var interSegment = new THREE.Vector3(); 104 | var interRay = new THREE.Vector3(); 105 | var step = this.mode === THREE.LineStrip ? 1 : 2; 106 | 107 | // 三角面判断 108 | for ( var i = 0; i < nbVertices - 1; i = i + step ) { 109 | 110 | var distSq = ray.distanceSqToSegment( vertices[ i ], vertices[ i + 1 ], interRay, interSegment ); 111 | 112 | if ( distSq > precisionSq ) continue; 113 | 114 | var distance = ray.origin.distanceTo( interRay ); 115 | 116 | if ( distance < raycaster.near || distance > raycaster.far ) continue; 117 | 118 | // 加入结果数组内 119 | intersects.push( { 120 | 121 | distance: distance, 122 | // What do we want? intersection point on the ray or on the segment?? 123 | // point: raycaster.ray.at( distance ), 124 | point: interSegment.clone().applyMatrix4( this.matrixWorld ), 125 | face: null, 126 | faceIndex: null, 127 | object: this 128 | 129 | } ); 130 | 131 | } 132 | 133 | } 134 | 135 | }; 136 | 137 | }() ); 138 | /** 139 | * @desc Three.Line 克隆函数 140 | * @param {THREE.Line} object 141 | * @returns {THREE.Line} 142 | */ 143 | THREE.Line.prototype.clone = function ( object ) { 144 | 145 | if ( object === undefined ) object = new THREE.Line( this.geometry, this.material, this.mode ); 146 | 147 | THREE.Object3D.prototype.clone.call( this, object ); 148 | 149 | return object; 150 | 151 | }; 152 | -------------------------------------------------------------------------------- /math/Line3.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author bhouston / http://exocortex.com 3 | */ 4 | /** 5 | * @classdesc 3维线段
6 | * 注释内容部分参照 http://blog.csdn.net/omni360 7 | * @param {THREE.Vector3} start 8 | * @param {THREE.Vector3} end 9 | * @class 10 | * @example var start = new Vector3(0,0,0),end = new Vector3(1,1,1); var line = new Line3(start,end); 11 | */ 12 | THREE.Line3 = function ( start, end ) { 13 | /** 14 | * @desc 线段起点 15 | * @type {THREE.Vector3} 16 | */ 17 | this.start = ( start !== undefined ) ? start : new THREE.Vector3(); 18 | /** 19 | * @desc 线段终点 20 | * @type {THREE.Vector3} 21 | */ 22 | this.end = ( end !== undefined ) ? end : new THREE.Vector3(); 23 | 24 | }; 25 | 26 | THREE.Line3.prototype = { 27 | 28 | constructor: THREE.Line3, 29 | 30 | /** 31 | * @desc 根据start,end坐标值设置3维线段 32 | * @param {THREE.Vector3} start 33 | * @param {THREE.Vector3} end 34 | * @returns {THREE.Line3} 35 | */ 36 | set: function ( start, end ) { 37 | 38 | this.start.copy( start ); 39 | this.end.copy( end ); 40 | 41 | return this; 42 | 43 | }, 44 | /** 45 | * @desc 拷贝3维线段 46 | * @param {THREE.Line3} line 47 | * @returns {THREE.Line3} 48 | */ 49 | copy: function ( line ) { 50 | 51 | this.start.copy( line.start ); 52 | this.end.copy( line.end ); 53 | 54 | return this; 55 | 56 | }, 57 | 58 | /** 59 | * @desc 返回3维线段中点 60 | * @param {THREE.Line3} optionalTarget 61 | * @returns {THREE.Vector3} 62 | */ 63 | center: function ( optionalTarget ) { 64 | 65 | var result = optionalTarget || new THREE.Vector3(); 66 | return result.addVectors( this.start, this.end ).multiplyScalar( 0.5 ); 67 | 68 | }, 69 | 70 | /** 71 | * @desc 获得线段的向量 72 | * @param {THREE.Line3} optionalTarget 73 | * @returns {THREE.Vector3} 74 | */ 75 | delta: function ( optionalTarget ) { 76 | 77 | var result = optionalTarget || new THREE.Vector3(); 78 | return result.subVectors( this.end, this.start ); 79 | 80 | }, 81 | /** 82 | * @desc 获得当前三维线段起始点到端点的点积 83 | * @returns {float} 84 | */ 85 | distanceSq: function () { 86 | 87 | return this.start.distanceToSquared( this.end ); 88 | 89 | }, 90 | /** 91 | * @desc 获得当前三维线段起始点到端点的距离 92 | * @returns {float} 93 | */ 94 | distance: function () { 95 | 96 | return this.start.distanceTo( this.end ); 97 | 98 | }, 99 | /** 100 | * @desc 当前三维线段方向的任意向量
101 | * @param {float} t [0,1] 当t=0,返回起点向量,当t=1返回结束点向量 102 | * @param {THREE.Vector3} optionalTarget 103 | * @returns {THREE.Vector3} 104 | */ 105 | at: function ( t, optionalTarget ) { 106 | 107 | var result = optionalTarget || new THREE.Vector3(); 108 | 109 | return this.delta( result ).multiplyScalar( t ).add( this.start ); 110 | 111 | }, 112 | /** 113 | * @function 114 | * @desc 返回一个基于点投影到线段上点的参数(就是参数point投影到线段的位置) 115 | * @param {THREE.Vector3} point 116 | * @param {boolean} clampToLine 为true,那么返回值将是0和1之间 117 | * @return {float} 118 | */ 119 | closestPointToPointParameter: function () { 120 | 121 | var startP = new THREE.Vector3(); 122 | var startEnd = new THREE.Vector3(); 123 | 124 | return function ( point, clampToLine ) { 125 | 126 | startP.subVectors( point, this.start ); 127 | startEnd.subVectors( this.end, this.start ); 128 | 129 | var startEnd2 = startEnd.dot( startEnd ); 130 | var startEnd_startP = startEnd.dot( startP ); 131 | 132 | var t = startEnd_startP / startEnd2; 133 | 134 | if ( clampToLine ) { 135 | 136 | t = THREE.Math.clamp( t, 0, 1 ); 137 | 138 | } 139 | 140 | return t; 141 | 142 | }; 143 | 144 | }(), 145 | 146 | /** 147 | * @desc 返回一个基于点投影到线段上的向量 148 | * @param {THREE.Vector3} point 149 | * @param {boolean} clampToLine 为true,那么返回的向量在线段起始点和结束点之间。 150 | * @param {THREE.Vector3} optionalTarget 151 | * @returns {*|THREE.Vector3} 152 | */ 153 | closestPointToPoint: function ( point, clampToLine, optionalTarget ) { 154 | 155 | var t = this.closestPointToPointParameter( point, clampToLine ); 156 | 157 | var result = optionalTarget || new THREE.Vector3(); 158 | 159 | return this.delta( result ).multiplyScalar( t ).add( this.start ); 160 | 161 | }, 162 | /** 163 | * @desc 线段的起始点,结束点应用矩阵变换.达到旋转,缩放,移动的目的 164 | * @param {THREE.Matrix3} matrix 165 | * @returns {THREE.Line3} 166 | */ 167 | applyMatrix4: function ( matrix ) { 168 | 169 | this.start.applyMatrix4( matrix ); 170 | this.end.applyMatrix4( matrix ); 171 | 172 | return this; 173 | 174 | }, 175 | /** 176 | * @desc 3维线段等号 177 | * @param {THREE.Line3} line 178 | * @returns {boolean} 179 | */ 180 | equals: function ( line ) { 181 | 182 | return line.start.equals( this.start ) && line.end.equals( this.end ); 183 | 184 | }, 185 | 186 | /** 187 | * @desc 克隆3维线段 188 | * @returns {THREE.Line3} 189 | */ 190 | clone: function () { 191 | 192 | return new THREE.Line3().copy( this ); 193 | 194 | } 195 | 196 | }; 197 | -------------------------------------------------------------------------------- /materials/ShaderMaterial.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author alteredq / http://alteredqualia.com/ 3 | * 4 | * parameters = { 5 | * defines: { "label" : "value" }, 6 | * uniforms: { "parameter1": { type: "f", value: 1.0 }, "parameter2": { type: "i" value2: 2 } }, 7 | * 8 | * fragmentShader: , 9 | * vertexShader: , 10 | * 11 | * shading: THREE.SmoothShading, 12 | * blending: THREE.NormalBlending, 13 | * depthTest: , 14 | * depthWrite: , 15 | * 16 | * wireframe: , 17 | * wireframeLinewidth: , 18 | * 19 | * lights: , 20 | * 21 | * vertexColors: THREE.NoColors / THREE.VertexColors / THREE.FaceColors, 22 | * 23 | * skinning: , 24 | * morphTargets: , 25 | * morphNormals: , 26 | * 27 | * fog: 28 | * } 29 | */ 30 | /** 31 | * @classdesc 自定义着色器创建材质类型
32 | * 注释内容部分参照 http://blog.csdn.net/omni360 33 | * @desc 这样的材质对象让用户扩充材质类型,有了无限的可能 34 | * @param {String} parameters 材质参数 35 | * @extends {THREE.Material} 36 | * @constructor 37 | */ 38 | THREE.ShaderMaterial = function ( parameters ) { 39 | 40 | THREE.Material.call( this ); 41 | /** 42 | * @default 'ShaderMaterial' 43 | * @type {string} 44 | */ 45 | this.type = 'ShaderMaterial'; 46 | /** 47 | * @desc 用户自定义defines变量 48 | * @default 49 | * @type {*} 50 | */ 51 | this.defines = {}; 52 | /** 53 | * @desc 用户自定义uniforms变量 54 | * @default 55 | * @type {*} 56 | */ 57 | this.uniforms = {}; 58 | /** 59 | * @desc 用户自定义attributes变量 60 | * @default 61 | * @type {*} 62 | */ 63 | this.attributes = null; 64 | /** 65 | * @desc 自定义顶点着色器 66 | * @type {string} 67 | */ 68 | this.vertexShader = 'void main() {\n\tgl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n}'; 69 | /** 70 | * @desc 自定义片段着色器 71 | * @type {string} 72 | */ 73 | this.fragmentShader = 'void main() {\n\tgl_FragColor = vec4( 1.0, 0.0, 0.0, 1.0 );\n}'; 74 | /** 75 | * @desc 着色方式
76 | * THREE.SmoothShading平滑着色:用多种颜色进行绘制
77 | * 每个顶点都是单独进行处理的,各顶点和各图元之间采用均匀插值。 78 | * @default 79 | * @type {number} 80 | */ 81 | this.shading = THREE.SmoothShading; 82 | /** 83 | * @desc 线的宽度 84 | * @default 85 | * @type {float} 86 | */ 87 | this.linewidth = 1; 88 | /** 89 | * @desc 是否以线框方式渲染几何体 90 | * @default 91 | * @type {boolean} 92 | */ 93 | this.wireframe = false; 94 | /** 95 | * @desc 线框宽度 96 | * @default 97 | * @type {float} 98 | */ 99 | this.wireframeLinewidth = 1; 100 | /** 101 | * @desc 雾效,默认关闭 102 | * @default 103 | * @type {boolean} 104 | */ 105 | this.fog = false; // set to use scene fog 106 | /** 107 | * @desc 是否使用场景内的灯光,默认关闭 108 | * @default 109 | * @type {boolean} 110 | */ 111 | this.lights = false; // set to use scene lights 112 | /** 113 | * @desc 材质顶点颜色 114 | * @default THREE.NoColors 115 | * @type {number} 116 | */ 117 | this.vertexColors = THREE.NoColors; // set to use "color" attribute stream 118 | /** 119 | * @desc 材质是否使用蒙皮 120 | * @default 121 | * @type {boolean} 122 | */ 123 | this.skinning = false; // set to use skinning attribute streams 124 | 125 | /** 126 | * @desc 材质是否设定目标变形动画 127 | * @default 128 | * @type {boolean} 129 | */ 130 | this.morphTargets = false; 131 | /** 132 | * @desc 材质是否反转(变换)法线 133 | * @default 134 | * @type {boolean} 135 | */ 136 | this.morphNormals = false; 137 | 138 | // When rendered geometry doesn't include these attributes but the material does, 139 | // use these default values in WebGL. This avoids errors when buffer data is missing. 140 | // 当渲染几何体不包含这些属性,但是材质中包含,在WEBGL中使用这些默认的值,可以避免缓存数据丢失发生错误. 141 | /** 142 | * @des 默认渲染属性 143 | * @type {*} 144 | */ 145 | this.defaultAttributeValues = { 146 | 'color': [ 1, 1, 1 ], 147 | 'uv': [ 0, 0 ], 148 | 'uv2': [ 0, 0 ] 149 | }; 150 | /** 151 | * @desc 用来接收索引为0的属性 152 | * @type {String} 153 | */ 154 | this.index0AttributeName = undefined; 155 | 156 | this.setValues( parameters ); 157 | 158 | }; 159 | /** 160 | * @desc ShaderMaterial对象从THREE.Material的原型继承所有属性方法 161 | * @type {THREE.Material} 162 | */ 163 | THREE.ShaderMaterial.prototype = Object.create( THREE.Material.prototype ); 164 | /** 165 | * @desc ShaderMaterial材质的克隆函数 166 | * @returns {THREE.ShaderMaterial} 167 | */ 168 | THREE.ShaderMaterial.prototype.clone = function () { 169 | 170 | var material = new THREE.ShaderMaterial(); 171 | 172 | THREE.Material.prototype.clone.call( this, material ); 173 | 174 | material.fragmentShader = this.fragmentShader; 175 | material.vertexShader = this.vertexShader; 176 | 177 | material.uniforms = THREE.UniformsUtils.clone( this.uniforms ); 178 | 179 | material.attributes = this.attributes; 180 | material.defines = this.defines; 181 | 182 | material.shading = this.shading; 183 | 184 | material.wireframe = this.wireframe; 185 | material.wireframeLinewidth = this.wireframeLinewidth; 186 | 187 | material.fog = this.fog; 188 | 189 | material.lights = this.lights; 190 | 191 | material.vertexColors = this.vertexColors; 192 | 193 | material.skinning = this.skinning; 194 | 195 | material.morphTargets = this.morphTargets; 196 | material.morphNormals = this.morphNormals; 197 | 198 | return material; 199 | 200 | }; 201 | -------------------------------------------------------------------------------- /objects/PointCloud.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author alteredq / http://alteredqualia.com/ 3 | */ 4 | /** 5 | * @classdesc 点云对象
6 | * 注释内容部分参照 http://blog.csdn.net/omni360 7 | * @param {THREE.Geometry} geometry 点云对象的几何对象 8 | * @param {THREE.Material} material 点云对象的材质对象 9 | * @constructor 10 | */ 11 | THREE.PointCloud = function ( geometry, material ) { 12 | 13 | THREE.Object3D.call( this ); 14 | 15 | this.type = 'PointCloud'; 16 | /** 17 | * @desc 点云对象的几何对象 18 | * @type {THREE.Geometry} 19 | */ 20 | this.geometry = geometry !== undefined ? geometry : new THREE.Geometry(); 21 | /** 22 | * @desc 点云对象的材质对象 23 | * @type {THREE.Material} 24 | */ 25 | this.material = material !== undefined ? material : new THREE.PointCloudMaterial( { color: Math.random() * 0xffffff } ); 26 | /** 27 | * @desc 是否对点云排序 28 | * @type {boolean} 29 | */ 30 | this.sortParticles = false; 31 | 32 | }; 33 | /** 34 | * @desc PointCloud从Objec3D的原型继承所有属性方法 35 | * @type {THREE.Object3D} 36 | */ 37 | THREE.PointCloud.prototype = Object.create( THREE.Object3D.prototype ); 38 | 39 | /** 40 | * @function 41 | * @desc 点云的拾取判断函数 42 | * @param {THREE.Raycaster} raycaster 拾取射线对象 43 | * @param {*} intersects 拾取结果对象数组 44 | */ 45 | THREE.PointCloud.prototype.raycast = ( function () { 46 | 47 | var inverseMatrix = new THREE.Matrix4(); 48 | var ray = new THREE.Ray(); 49 | 50 | return function ( raycaster, intersects ) { 51 | 52 | var object = this; 53 | var geometry = object.geometry; 54 | var threshold = raycaster.params.PointCloud.threshold; 55 | 56 | inverseMatrix.getInverse( this.matrixWorld ); 57 | ray.copy( raycaster.ray ).applyMatrix4( inverseMatrix ); 58 | // 外包围盒碰撞判断 59 | if ( geometry.boundingBox !== null ) { 60 | 61 | if ( ray.isIntersectionBox( geometry.boundingBox ) === false ) { 62 | 63 | return; 64 | 65 | } 66 | 67 | } 68 | 69 | var localThreshold = threshold / ( ( this.scale.x + this.scale.y + this.scale.z ) / 3 ); 70 | var position = new THREE.Vector3(); 71 | //检查射线与点云元素是否碰撞的具体实现. 72 | var testPoint = function ( point, index ) { 73 | 74 | var rayPointDistance = ray.distanceToPoint( point ); 75 | 76 | if ( rayPointDistance < localThreshold ) { 77 | 78 | var intersectPoint = ray.closestPointToPoint( point ); 79 | intersectPoint.applyMatrix4( object.matrixWorld ); 80 | 81 | var distance = raycaster.ray.origin.distanceTo( intersectPoint ); 82 | 83 | intersects.push( { 84 | 85 | distance: distance, 86 | distanceToRay: rayPointDistance, 87 | point: intersectPoint.clone(), 88 | index: index, 89 | face: null, 90 | object: object 91 | 92 | } ); 93 | 94 | } 95 | 96 | }; 97 | // 如果geometry对象是BufferGeometry对象 98 | if ( geometry instanceof THREE.BufferGeometry ) { 99 | 100 | var attributes = geometry.attributes; 101 | var positions = attributes.position.array; 102 | // 下面对三种数据格式的pointCloud对象的元素进行检测. 103 | if ( attributes.index !== undefined ) { 104 | 105 | var indices = attributes.index.array; 106 | var offsets = geometry.offsets; 107 | 108 | if ( offsets.length === 0 ) { 109 | 110 | var offset = { 111 | start: 0, 112 | count: indices.length, 113 | index: 0 114 | }; 115 | 116 | offsets = [ offset ]; 117 | 118 | } 119 | 120 | for ( var oi = 0, ol = offsets.length; oi < ol; ++oi ) { 121 | 122 | var start = offsets[ oi ].start; 123 | var count = offsets[ oi ].count; 124 | var index = offsets[ oi ].index; 125 | 126 | for ( var i = start, il = start + count; i < il; i ++ ) { 127 | 128 | var a = index + indices[ i ]; 129 | 130 | position.fromArray( positions, a * 3 ); 131 | 132 | testPoint( position, a ); 133 | 134 | } 135 | 136 | } 137 | 138 | } else { 139 | 140 | var pointCount = positions.length / 3; 141 | 142 | for ( var i = 0; i < pointCount; i ++ ) { 143 | 144 | position.set( 145 | positions[ 3 * i ], 146 | positions[ 3 * i + 1 ], 147 | positions[ 3 * i + 2 ] 148 | ); 149 | 150 | testPoint( position, i ); 151 | 152 | } 153 | 154 | } 155 | 156 | } else { 157 | 158 | var vertices = this.geometry.vertices; 159 | 160 | for ( var i = 0; i < vertices.length; i ++ ) { 161 | 162 | testPoint( vertices[ i ], i ); 163 | 164 | } 165 | 166 | } 167 | 168 | }; 169 | 170 | }() ); 171 | /** 172 | * @desc Three.PointCloud 克隆函数 173 | * @param {THREE.PointCloud} object 174 | * @returns {THREE.PointCloud} 175 | */ 176 | THREE.PointCloud.prototype.clone = function ( object ) { 177 | 178 | if ( object === undefined ) object = new THREE.PointCloud( this.geometry, this.material ); 179 | 180 | object.sortParticles = this.sortParticles; 181 | 182 | THREE.Object3D.prototype.clone.call( this, object ); 183 | 184 | return object; 185 | 186 | }; 187 | 188 | // Backwards compatibility 189 | /** 190 | * @ignore 191 | * @param geometry 192 | * @param material 193 | * @returns {THREE.PointCloud} 194 | * @constructor 195 | */ 196 | THREE.ParticleSystem = function ( geometry, material ) { 197 | 198 | console.warn( 'THREE.ParticleSystem has been renamed to THREE.PointCloud.' ); 199 | return new THREE.PointCloud( geometry, material ); 200 | 201 | }; 202 | -------------------------------------------------------------------------------- /materials/MeshBasicMaterial.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author mrdoob / http://mrdoob.com/ 3 | * @author alteredq / http://alteredqualia.com/ 4 | * 5 | * parameters = { 6 | * color: , 7 | * opacity: , 8 | * map: new THREE.Texture( ), 9 | * 10 | * lightMap: new THREE.Texture( ), 11 | * 12 | * specularMap: new THREE.Texture( ), 13 | * 14 | * alphaMap: new THREE.Texture( ), 15 | * 16 | * envMap: new THREE.TextureCube( [posx, negx, posy, negy, posz, negz] ), 17 | * combine: THREE.Multiply, 18 | * reflectivity: , 19 | * refractionRatio: , 20 | * 21 | * shading: THREE.SmoothShading, 22 | * blending: THREE.NormalBlending, 23 | * depthTest: , 24 | * depthWrite: , 25 | * 26 | * wireframe: , 27 | * wireframeLinewidth: , 28 | * 29 | * vertexColors: THREE.NoColors / THREE.VertexColors / THREE.FaceColors, 30 | * 31 | * skinning: , 32 | * morphTargets: , 33 | * 34 | * fog: 35 | * } 36 | */ 37 | /** 38 | * @classdesc mesh(网格)的基本材质材质
39 | * 注释内容部分参照 http://blog.csdn.net/omni360 40 | * @desc 据参数parameters创建线段的线线型材质,参数为JSON格式的属性参数 41 | * @param {String} parameters 材质参数 42 | * @extends {THREE.Material} 43 | * @constructor 44 | */ 45 | THREE.MeshBasicMaterial = function ( parameters ) { 46 | 47 | THREE.Material.call( this ); 48 | /** 49 | * @default 'MeshBasicMaterial' 50 | * @type {string} 51 | */ 52 | this.type = 'MeshBasicMaterial'; 53 | /** 54 | * @desc 材质颜色 55 | * @default 0xffffff 白色 56 | * @type {THREE.Color} 57 | */ 58 | this.color = new THREE.Color( 0xffffff ); // emissive 59 | /** 60 | * @desc 纹理贴图 61 | * @default 62 | * @type {THREE.Texture} 63 | */ 64 | this.map = null; 65 | /** 66 | * @desc 光照贴图 67 | * @default 68 | * @type {THREE.Texture} 69 | */ 70 | this.lightMap = null; 71 | /** 72 | * @desc 高光贴图 73 | * @default 74 | * @type {THREE.Texture} 75 | */ 76 | this.specularMap = null; 77 | /** 78 | * @desc 透明贴图 79 | * @default 80 | * @type {THREE.Texture} 81 | */ 82 | this.alphaMap = null; 83 | /** 84 | * @desc 环境贴图 85 | * @default 86 | * @type {THREE.Texture} 87 | */ 88 | this.envMap = null; 89 | /** 90 | * @desc 材质混合模式 91 | * @default THREE.MultiplyOperation 92 | * @type {number} 93 | */ 94 | this.combine = THREE.MultiplyOperation; 95 | /** 96 | * @desc 反射率 97 | * @default 98 | * @type {float} 99 | */ 100 | this.reflectivity = 1; 101 | /** 102 | * @desc 折射率 103 | * @default 104 | * @type {float} 105 | */ 106 | this.refractionRatio = 0.98; 107 | /** 108 | * @desc 雾效,默认开启 109 | * @default 110 | * @type {boolean} 111 | */ 112 | this.fog = true; 113 | /** 114 | * @desc 着色方式
115 | * THREE.SmoothShading平滑着色:用多种颜色进行绘制
116 | * 每个顶点都是单独进行处理的,各顶点和各图元之间采用均匀插值。 117 | * @default 118 | * @type {number} 119 | */ 120 | this.shading = THREE.SmoothShading; 121 | /** 122 | * @desc 是否以线框方式渲染几何体 123 | * @default 124 | * @type {boolean} 125 | */ 126 | this.wireframe = false; 127 | /** 128 | * @desc 线框宽度 129 | * @default 130 | * @type {float} 131 | */ 132 | this.wireframeLinewidth = 1; 133 | /** 134 | * @desc 线框端点类型,参照LineBasicMaterial的定义 135 | * @default 'round' 136 | * @type {string} 137 | */ 138 | this.wireframeLinecap = 'round'; 139 | /** 140 | * @desc 线框连接类型,参照LineBasicMaterial的定义 141 | * @default 'round' 142 | * @type {string} 143 | */ 144 | this.wireframeLinejoin = 'round'; 145 | /** 146 | * @desc 材质顶点颜色 147 | * @default THREE.NoColors 148 | * @type {number} 149 | */ 150 | this.vertexColors = THREE.NoColors; 151 | /** 152 | * @desc 材质是否使用蒙皮 153 | * @default 154 | * @type {boolean} 155 | */ 156 | this.skinning = false; 157 | /** 158 | * @desc 材质是否设定目标变形动画 159 | * @default 160 | * @type {boolean} 161 | */ 162 | this.morphTargets = false; 163 | 164 | this.setValues( parameters ); 165 | 166 | }; 167 | /** 168 | * @desc MeshBasicMaterial对象从THREE.Material的原型继承所有属性方法 169 | * @type {THREE.Material} 170 | */ 171 | THREE.MeshBasicMaterial.prototype = Object.create( THREE.Material.prototype ); 172 | /** 173 | * @desc 面材质的克隆函数 174 | * @returns {THREE.MeshBasicMaterial} 175 | */ 176 | THREE.MeshBasicMaterial.prototype.clone = function () { 177 | 178 | var material = new THREE.MeshBasicMaterial(); 179 | 180 | THREE.Material.prototype.clone.call( this, material ); 181 | 182 | material.color.copy( this.color ); 183 | 184 | material.map = this.map; 185 | 186 | material.lightMap = this.lightMap; 187 | 188 | material.specularMap = this.specularMap; 189 | 190 | material.alphaMap = this.alphaMap; 191 | 192 | material.envMap = this.envMap; 193 | material.combine = this.combine; 194 | material.reflectivity = this.reflectivity; 195 | material.refractionRatio = this.refractionRatio; 196 | 197 | material.fog = this.fog; 198 | 199 | material.shading = this.shading; 200 | 201 | material.wireframe = this.wireframe; 202 | material.wireframeLinewidth = this.wireframeLinewidth; 203 | material.wireframeLinecap = this.wireframeLinecap; 204 | material.wireframeLinejoin = this.wireframeLinejoin; 205 | 206 | material.vertexColors = this.vertexColors; 207 | 208 | material.skinning = this.skinning; 209 | material.morphTargets = this.morphTargets; 210 | 211 | return material; 212 | 213 | }; 214 | -------------------------------------------------------------------------------- /math/Sphere.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author bhouston / http://exocortex.com 3 | * @author mrdoob / http://mrdoob.com/ 4 | */ 5 | /** 6 | * @classdesc 球体类
7 | * 注释内容部分参照 http://blog.csdn.net/omni360 8 | * @desc center,半径为radius的球体 9 | * @param {THREE.Vector3} center 中心点坐标 10 | * @param {float} radius 半径 11 | * @constructor 12 | */ 13 | THREE.Sphere = function ( center, radius ) { 14 | /** 15 | * @desc 球体中心点 16 | * @type {THREE.Vector3} 17 | */ 18 | this.center = ( center !== undefined ) ? center : new THREE.Vector3(); 19 | /** 20 | * @desc 球体半径 21 | * @default 0 22 | * @type {float} 23 | */ 24 | this.radius = ( radius !== undefined ) ? radius : 0; 25 | 26 | }; 27 | 28 | THREE.Sphere.prototype = { 29 | 30 | constructor: THREE.Sphere, 31 | /** 32 | * @desc 根据圆心和半径设置球体 33 | * @param center 34 | * @param radius 35 | * @returns {THREE.Sphere} 36 | */ 37 | set: function ( center, radius ) { 38 | 39 | this.center.copy( center ); 40 | this.radius = radius; 41 | 42 | return this; 43 | }, 44 | /** 45 | * @function 46 | * @desc Vector3对象组成的points数组中的到圆心距离最大的值重新设置球体的半径 47 | * @param {THREE.Vector3[]} points 48 | * @param {THREE.Vector3} optionalCenter 球体中心 49 | * @returns {THREE.Sphere} 50 | */ 51 | setFromPoints: function () { 52 | 53 | var box = new THREE.Box3(); 54 | 55 | return function ( points, optionalCenter ) { 56 | 57 | var center = this.center; 58 | 59 | if ( optionalCenter !== undefined ) { 60 | 61 | center.copy( optionalCenter ); 62 | 63 | } else { 64 | 65 | box.setFromPoints( points ).center( center ); 66 | 67 | } 68 | 69 | var maxRadiusSq = 0; 70 | 71 | for ( var i = 0, il = points.length; i < il; i ++ ) { 72 | 73 | maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( points[ i ] ) ); 74 | 75 | } 76 | 77 | this.radius = Math.sqrt( maxRadiusSq ); 78 | 79 | return this; 80 | 81 | }; 82 | 83 | }(), 84 | 85 | /** 86 | * @desc 拷贝球体 87 | * @param {THREE.Sphere} sphere 88 | * @returns {THREE.Sphere} 89 | */ 90 | copy: function ( sphere ) { 91 | 92 | this.center.copy( sphere.center ); 93 | this.radius = sphere.radius; 94 | 95 | return this; 96 | 97 | }, 98 | /** 99 | * @desc 判断球体是否合法 100 | * @returns {boolean} 101 | */ 102 | empty: function () { 103 | 104 | return ( this.radius <= 0 ); 105 | 106 | }, 107 | 108 | /** 109 | * @desc 判断点是否在球体内 110 | * @param {THREE.Vector3} point 111 | * @returns {boolean} 112 | */ 113 | containsPoint: function ( point ) { 114 | 115 | return ( point.distanceToSquared( this.center ) <= ( this.radius * this.radius ) ); 116 | 117 | }, 118 | 119 | /** 120 | * @desc 点到球心的距离 121 | * @param {THREE.Vector3} point 122 | * @returns {float} 123 | */ 124 | distanceToPoint: function ( point ) { 125 | 126 | return ( point.distanceTo( this.center ) - this.radius ); 127 | 128 | }, 129 | /** 130 | * @desc 两个球体是否相交 131 | * @param {THREE.Sphere} sphere 132 | * @returns {boolean} 133 | */ 134 | intersectsSphere: function ( sphere ) { 135 | 136 | var radiusSum = this.radius + sphere.radius; 137 | 138 | return sphere.center.distanceToSquared( this.center ) <= ( radiusSum * radiusSum ); 139 | 140 | }, 141 | /** 142 | * @desc 根据点来重新定义球体半径
143 | * 如果point在球体外,强制将point设置到球体表面,如果point在球体内,重新设置球体半径为point到当前球体半径的距离 144 | * @param {THREE.Vector3} point 145 | * @param {THREE.Vector3} optionalTarget 146 | * @returns {THREE.Vector3} 147 | */ 148 | clampPoint: function ( point, optionalTarget ) { 149 | 150 | var deltaLengthSq = this.center.distanceToSquared( point ); 151 | 152 | var result = optionalTarget || new THREE.Vector3(); 153 | result.copy( point ); 154 | 155 | if ( deltaLengthSq > ( this.radius * this.radius ) ) { 156 | 157 | result.sub( this.center ).normalize(); 158 | result.multiplyScalar( this.radius ).add( this.center ); 159 | 160 | } 161 | 162 | return result; 163 | 164 | }, 165 | 166 | /** 167 | * @desc 计算球体的外包围盒 168 | * @param {THREE.Box3} optionalTarget 169 | * @returns {THREE.Box3} 170 | */ 171 | getBoundingBox: function ( optionalTarget ) { 172 | 173 | var box = optionalTarget || new THREE.Box3(); 174 | 175 | box.set( this.center, this.center ); 176 | box.expandByScalar( this.radius ); 177 | 178 | return box; 179 | 180 | }, 181 | /** 182 | * @desc 球体的投影变换
183 | * 平移相对于球心,缩放相对于半径 184 | * @param {THREE.Matrix4} matrix 185 | * @returns {THREE.Sphere} 186 | */ 187 | applyMatrix4: function ( matrix ) { 188 | 189 | this.center.applyMatrix4( matrix ); 190 | this.radius = this.radius * matrix.getMaxScaleOnAxis(); 191 | 192 | return this; 193 | 194 | }, 195 | /** 196 | * @desc 球体平移 197 | * @param {THREE.Vector3} offset 198 | * @returns {THREE.Sphere} 199 | */ 200 | translate: function ( offset ) { 201 | 202 | this.center.add( offset ); 203 | 204 | return this; 205 | 206 | }, 207 | /** 208 | * @desc 球体是否相等 209 | * @param {THREE.Sphere} sphere 210 | * @returns {boolean} 211 | */ 212 | equals: function ( sphere ) { 213 | 214 | return sphere.center.equals( this.center ) && ( sphere.radius === this.radius ); 215 | 216 | }, 217 | 218 | /** 219 | * @desc 球体克隆 220 | * @returns {THREE.Sphere} 221 | */ 222 | clone: function () { 223 | 224 | return new THREE.Sphere().copy( this ); 225 | 226 | } 227 | 228 | }; 229 | -------------------------------------------------------------------------------- /math/Math.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author alteredq / http://alteredqualia.com/ 3 | * @author mrdoob / http://mrdoob.com/ 4 | */ 5 | /** 6 | * @classdesc 数学类
7 | * 注释内容部分参照 http://blog.csdn.net/omni360 8 | * @desc 数学相关函数 9 | * @class 10 | */ 11 | THREE.Math = { 12 | 13 | /** 14 | * @function 15 | * @desc 生成36位的UUID 16 | * @return {char[]} 17 | */ 18 | generateUUID: function () { 19 | 20 | // http://www.broofa.com/Tools/Math.uuid.htm 21 | 22 | var chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split( '' ); 23 | var uuid = new Array( 36 ); 24 | var rnd = 0, r; 25 | 26 | return function () { 27 | 28 | for ( var i = 0; i < 36; i ++ ) { 29 | 30 | if ( i == 8 || i == 13 || i == 18 || i == 23 ) { 31 | 32 | uuid[ i ] = '-'; 33 | 34 | } else if ( i == 14 ) { 35 | 36 | uuid[ i ] = '4'; 37 | 38 | } else { 39 | 40 | if ( rnd <= 0x02 ) rnd = 0x2000000 + ( Math.random() * 0x1000000 ) | 0; 41 | r = rnd & 0xf; 42 | rnd = rnd >> 4; 43 | uuid[ i ] = chars[ ( i == 19 ) ? ( r & 0x3 ) | 0x8 : r ]; 44 | 45 | } 46 | } 47 | 48 | return uuid.join( '' ); 49 | 50 | }; 51 | 52 | }(), 53 | 54 | // Clamp value to range 55 | 56 | /** 57 | * @desc 限制x的值在a和b之间
58 | * 如果x小于a,返回a。 如果x大于b,返回b,否则返回x 59 | * @param {float} x 60 | * @param {float} a 61 | * @param {float} b 62 | * @returns {float} 63 | */ 64 | clamp: function ( x, a, b ) { 65 | 66 | return ( x < a ) ? a : ( ( x > b ) ? b : x ); 67 | 68 | }, 69 | 70 | // Clamp value to range 73 | * 如果x小于a,返回a。 否则返回x 74 | * @param {float} x 75 | * @param {float} a 76 | * @returns {float} 77 | */ 78 | clampBottom: function ( x, a ) { 79 | 80 | return x < a ? a : x; 81 | 82 | }, 83 | 84 | // Linear mapping from range to range 85 | /** 86 | * @desc 参数x在range到range的线性映射 87 | * @param {float} x 88 | * @param {float} a1 89 | * @param {float} a2 90 | * @param {float} b1 91 | * @param {float} b2 92 | * @returns {*} 93 | */ 94 | mapLinear: function ( x, a1, a2, b1, b2 ) { 95 | 96 | return b1 + ( x - a1 ) * ( b2 - b1 ) / ( a2 - a1 ); 97 | 98 | }, 99 | 100 | // http://en.wikipedia.org/wiki/Smoothstep 101 | 102 | /** 103 | * @desc 最小和最大值之间的插值,并在限制处渐入渐出。三次平滑插值 104 | * @param {float} x 105 | * @param {float} min 106 | * @param {float} max 107 | * @returns {float} 108 | */ 109 | smoothstep: function ( x, min, max ) { 110 | 111 | if ( x <= min ) return 0; 112 | if ( x >= max ) return 1; 113 | 114 | x = ( x - min ) / ( max - min ); 115 | 116 | return x * x * ( 3 - 2 * x ); 117 | 118 | }, 119 | /** 120 | * @desc 在最小和最大值之间的插值,并在限制处渐入渐出。五次平滑插值 121 | * @param {float} x 122 | * @param {float} min 123 | * @param {float} max 124 | * @returns {float} 125 | */ 126 | smootherstep: function ( x, min, max ) { 127 | 128 | if ( x <= min ) return 0; 129 | if ( x >= max ) return 1; 130 | 131 | x = ( x - min ) / ( max - min ); 132 | 133 | return x * x * x * ( x * ( x * 6 - 15 ) + 10 ); 134 | 135 | }, 136 | 137 | // Random float from <0, 1> with 16 bits of randomness 138 | // (standard Math.random() creates repetitive patterns when applied over larger space) 139 | 140 | /** 141 | * @desc 生成0,到1的随机浮点数,有16位大小选择范围 142 | * @returns {float} 143 | */ 144 | random16: function () { 145 | 146 | return ( 65280 * Math.random() + 255 * Math.random() ) / 65535; 147 | 148 | }, 149 | 150 | // Random integer from interval 151 | /** 152 | * @desc 通过参数low,high定义的取值范围生成随机整数 153 | * @param {number} vfhgplow 154 | * @param {number} vfhgphigh 155 | * @returns {number} 156 | */ 157 | randInt: function ( low, high ) { 158 | 159 | return low + Math.floor( Math.random() * ( high - low + 1 ) ); 160 | 161 | }, 162 | 163 | // Random float from interval 164 | /** 165 | * @desc 通过参数low,high定义的取值范围生成随机浮点数 166 | * @param {float} vfhgplow 167 | * @param {float} vfhgphigh 168 | * @returns {float} 169 | */ 170 | randFloat: function ( low, high ) { 171 | 172 | return low + Math.random() * ( high - low ); 173 | 174 | }, 175 | 176 | // Random float from <-range/2, range/2> interval 177 | 178 | /** 179 | * @desc 生成[-range/2,range/2]区间随机浮点数 180 | * @param {float} range 181 | * @returns {float} 182 | */ 183 | randFloatSpread: function ( range ) { 184 | 185 | return range * ( 0.5 - Math.random() ); 186 | 187 | }, 188 | 189 | /** 190 | * @function 191 | * @desc 角度转换弧度 192 | * @param {float} degrees 193 | * @return {float} 194 | */ 195 | degToRad: function () { 196 | 197 | var degreeToRadiansFactor = Math.PI / 180; 198 | 199 | return function ( degrees ) { 200 | 201 | return degrees * degreeToRadiansFactor; 202 | 203 | }; 204 | 205 | }(), 206 | /** 207 | * @function 208 | * @desc 弧度转换角度 209 | * @param {float} radians 210 | * @return {float} 211 | */ 212 | radToDeg: function () { 213 | 214 | var radianToDegreesFactor = 180 / Math.PI; 215 | 216 | return function ( radians ) { 217 | 218 | return radians * radianToDegreesFactor; 219 | 220 | }; 221 | 222 | }(), 223 | 224 | /** 225 | * @desc 是否2的幂,如果该值是2的幂,返回true 226 | * @param {number} value 227 | * @returns {boolean} 228 | */ 229 | isPowerOfTwo: function ( value ) { 230 | 231 | return ( value & ( value - 1 ) ) === 0 && value !== 0; 232 | 233 | } 234 | 235 | }; 236 | -------------------------------------------------------------------------------- /objects/SkinnedMesh.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author mikael emtinger / http://gomo.se/ 3 | * @author alteredq / http://alteredqualia.com/ 4 | * @author ikerr / http://verold.com 5 | */ 6 | /** 7 | * @classdesc 蒙皮网格对象
8 | * 注释内容部分参照 http://blog.csdn.net/omni360 9 | * @desc 蒙皮网格用于渲染人物。人物动画使用的骨骼,而且每个骨骼影响网格的一部分. 10 | * @param {THREE.Geometry} geometry 几何对象 11 | * @param {THREE.Material} material 材质对象 12 | * @param {boolean} useVertexTexture 是否使用顶点纹理,对象构建后不能修改 13 | * @constructor 14 | */ 15 | THREE.SkinnedMesh = function ( geometry, material, useVertexTexture ) { 16 | 17 | THREE.Mesh.call( this, geometry, material ); 18 | 19 | this.type = 'SkinnedMesh'; 20 | /** 21 | * @desc 绑定模式 22 | * @default "attached" 23 | * @type {string} 24 | */ 25 | this.bindMode = "attached"; 26 | /** 27 | * @desc 绑定矩阵 28 | * @type {THREE.Matrix4} 29 | */ 30 | this.bindMatrix = new THREE.Matrix4(); 31 | /** 32 | * @desc 绑定矩阵的逆矩阵 33 | * @type {THREE.Matrix4} 34 | */ 35 | this.bindMatrixInverse = new THREE.Matrix4(); 36 | 37 | // init bones 38 | // 初始化骨骼 39 | // TODO: remove bone creation as there is no reason (other than 40 | // convenience) for THREE.SkinnedMesh to do this. 41 | // 存储骨骼的数组,这个属性在构造函数中设置. 42 | var bones = []; 43 | 44 | if ( this.geometry && this.geometry.bones !== undefined ) { 45 | 46 | var bone, gbone, p, q, s; 47 | 48 | for ( var b = 0, bl = this.geometry.bones.length; b < bl; ++b ) { 49 | 50 | gbone = this.geometry.bones[ b ]; 51 | 52 | p = gbone.pos; 53 | q = gbone.rotq; 54 | s = gbone.scl; 55 | 56 | bone = new THREE.Bone( this ); 57 | bones.push( bone ); 58 | 59 | bone.name = gbone.name; 60 | // 位置属性 61 | bone.position.set( p[ 0 ], p[ 1 ], p[ 2 ] ); 62 | // 四元数旋转属性 63 | bone.quaternion.set( q[ 0 ], q[ 1 ], q[ 2 ], q[ 3 ] ); 64 | // 缩放属性 65 | if ( s !== undefined ) { 66 | 67 | bone.scale.set( s[ 0 ], s[ 1 ], s[ 2 ] ); 68 | 69 | } else { 70 | 71 | bone.scale.set( 1, 1, 1 ); 72 | 73 | } 74 | 75 | } 76 | 77 | for ( var b = 0, bl = this.geometry.bones.length; b < bl; ++b ) { 78 | 79 | gbone = this.geometry.bones[ b ]; 80 | 81 | if ( gbone.parent !== - 1 ) { 82 | 83 | bones[ gbone.parent ].add( bones[ b ] ); 84 | 85 | } else { 86 | 87 | this.add( bones[ b ] ); 88 | 89 | } 90 | 91 | } 92 | 93 | } 94 | // 构造SkinnedMesh对象时调用normalizeSkinWeights方法 95 | // 确保skinWeights的各元素是归一化的. 96 | this.normalizeSkinWeights(); 97 | // 对当前对象及其子对象的matrix属性应用全局位移,旋转,缩放变换 98 | this.updateMatrixWorld( true ); 99 | // 调用bind方法,绑定骨骼对象. 100 | this.bind( new THREE.Skeleton( bones, undefined, useVertexTexture ) ); 101 | 102 | }; 103 | 104 | /** 105 | * @desc SkinnedMesh从Mesh的原型继承所有属性方法 106 | * @type {THREE.Mesh} 107 | */ 108 | THREE.SkinnedMesh.prototype = Object.create( THREE.Mesh.prototype ); 109 | /** 110 | * @desc 将蒙皮网格对象根据绑定矩阵绑定骨架 111 | * @param {THREE.Skeleton[]} skeleton 112 | * @param {THREE.Matrix4} bindMatrix 113 | */ 114 | THREE.SkinnedMesh.prototype.bind = function( skeleton, bindMatrix ) { 115 | 116 | this.skeleton = skeleton; 117 | 118 | // 如果没有指定绑定矩阵 119 | if ( bindMatrix === undefined ) { 120 | 121 | this.updateMatrixWorld( true ); 122 | // 使用蒙皮网格对象的世界坐标矩阵 123 | bindMatrix = this.matrixWorld; 124 | 125 | } 126 | 127 | this.bindMatrix.copy( bindMatrix ); 128 | this.bindMatrixInverse.getInverse( bindMatrix ); 129 | 130 | }; 131 | /** 132 | * @desc 重新计算蒙皮网格对象的骨架的计算本地矩阵,位置,旋转缩放属性 133 | */ 134 | THREE.SkinnedMesh.prototype.pose = function () { 135 | // 调用骨架对象的pose方法 136 | this.skeleton.pose(); 137 | 138 | }; 139 | /** 140 | * @desc 归一化蒙皮网格对象的蒙皮权重 141 | */ 142 | THREE.SkinnedMesh.prototype.normalizeSkinWeights = function () { 143 | 144 | if ( this.geometry instanceof THREE.Geometry ) { 145 | // 遍历蒙皮指数数组. 146 | for ( var i = 0; i < this.geometry.skinIndices.length; i ++ ) { 147 | // 蒙皮权重数组 148 | var sw = this.geometry.skinWeights[ i ]; 149 | // 求和sw的x,y,z分量 150 | var scale = 1.0 / sw.lengthManhattan(); 151 | // scale不等于正无穷大 152 | if ( scale !== Infinity ) { 153 | // sw的每个分量乘以scale 154 | sw.multiplyScalar( scale ); 155 | 156 | } else { 157 | // sw将被着色器归一化 158 | sw.set( 1 ); // this will be normalized by the shader anyway 159 | 160 | } 161 | 162 | } 163 | 164 | } else { 165 | 166 | // skinning weights assumed to be normalized for THREE.BufferGeometry 167 | // 蒙皮权重确保是归一化的 ,供THREE.BufferGeometry使用 168 | } 169 | 170 | }; 171 | /** 172 | * @desc 方法对当前对象及其子对象的matrix属性应用全局位移,旋转,缩放变换 173 | * @param {boolean} force 是否强制将子对象做同样的全局变换 174 | */ 175 | THREE.SkinnedMesh.prototype.updateMatrixWorld = function( force ) { 176 | 177 | THREE.Mesh.prototype.updateMatrixWorld.call( this, true ); 178 | 179 | if ( this.bindMode === "attached" ) { 180 | 181 | this.bindMatrixInverse.getInverse( this.matrixWorld ); 182 | 183 | } else if ( this.bindMode === "detached" ) { 184 | 185 | this.bindMatrixInverse.getInverse( this.bindMatrix ); 186 | 187 | } else { 188 | 189 | console.warn( 'THREE.SkinnedMesh unreckognized bindMode: ' + this.bindMode ); 190 | 191 | } 192 | 193 | }; 194 | /** 195 | * @desc Three.SkinnedMesh 克隆函数 196 | * @param {THREE.SkinnedMesh} object 197 | * @returns {THREE.SkinnedMesh} 198 | */ 199 | THREE.SkinnedMesh.prototype.clone = function( object ) { 200 | 201 | if ( object === undefined ) { 202 | 203 | object = new THREE.SkinnedMesh( this.geometry, this.material, this.useVertexTexture ); 204 | 205 | } 206 | 207 | THREE.Mesh.prototype.clone.call( this, object ); 208 | 209 | return object; 210 | 211 | }; 212 | 213 | -------------------------------------------------------------------------------- /lights/SpotLight.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author alteredq / http://alteredqualia.com/ 3 | */ 4 | /** 5 | * @classdesc 聚光灯光源对象
6 | * 注释内容部分参照 http://blog.csdn.net/omni360 7 | * @desc 根据设置灯光的颜属性color, 强度属性intensity,距离属性 distance,灯光的照射角度 angle,衰减速度 exponent 创建聚光灯光源(射灯)
8 | * SpotLight类型灯光实现了阴影,但是需要在场景中使用MeshLambertMaterial或者MeshPhongMaterial 9 | * @param {THREE.Color} color 灯光的颜色属性 10 | * @param {float} intensity 灯光的强度,默认是1 11 | * @param {float} distance 灯光的长度属性,从灯光的position位置,开始衰减,衰减到distance的长度,默认是0 12 | * @param {float} angle 聚光灯的灯光照射角度属性,单位是弧度,默认是60度角的弧度 13 | * @param {float} exponent 聚光灯的从照射点的衰减速度属性,默认是10 14 | * @extends {THREE.Light} 15 | * @example var light = new THREE.SpotLight(0xff0000,1,100,Math.PI /2,5); //创建灯光对象
16 | * light.position.set(50,50,30); //设置位置
17 | * light.castShadow = true; //开启阴影
18 | * light.shadowMapWidth = 1024; //阴影贴图宽度设置为1024像素
19 | * light.shadowMapHeight = 1024; //阴影贴图高度设置为1024像素
20 | * light.shadowCameraNear = 500; //阴影的平截头体区域near属性
21 | * light.shadowCameraFar = 4000; //阴影的平截头体区域far属性
22 | * light.shadowCameraFov = 30; //阴影的平截头体区域fov属性
23 | * scene.add(lignt); //加入场景 24 | * @constructor 25 | */ 26 | THREE.SpotLight = function ( color, intensity, distance, angle, exponent ) { 27 | 28 | THREE.Light.call( this, color ); 29 | /** 30 | * @default 31 | * @type {string} 32 | */ 33 | this.type = 'SpotLight'; 34 | /** 35 | * @desc 灯光的位置属性初始化为,0,1,0 36 | */ 37 | this.position.set( 0, 1, 0 ); 38 | /** 39 | * @desc 创建一个目标点对象,目标点对象是一个Object3D对象 40 | * @type {THREE.Object3D} 41 | */ 42 | this.target = new THREE.Object3D(); 43 | /** 44 | * desc 灯光的强度
45 | * (光线的密度,默认为1。因为RGB的三个值均在0~255之间,
46 | * 不能反映出光照的强度变化,光照越强,物体表面就更明亮。) 47 | * @default 1 48 | * @type {float} 49 | */ 50 | this.intensity = ( intensity !== undefined ) ? intensity : 1; 51 | /** 52 | * desc 灯光的长度度
53 | * 如果不指定,初始化为1.
54 | * (衰减距离,默认值为0,光照无衰减;如果是非0值,光照会从position位置
55 | * (实际上是position所处的那个平面)开始衰减,衰减到distance距离之后,光照强度intensity为0) 56 | * @default 0 57 | * @type {float} 58 | */ 59 | this.distance = ( distance !== undefined ) ? distance : 0; 60 | /** 61 | * desc 聚光灯的灯光照射角度属性
62 | * 单位是弧度,默认是60度角的弧度 63 | * @default Math.PI / 3 64 | * @type {float} 65 | */ 66 | this.angle = ( angle !== undefined ) ? angle : Math.PI / 3; 67 | /** 68 | * desc 光灯的从照射点的衰减速度指数 69 | * @default 10 70 | * @type {float} 71 | */ 72 | this.exponent = ( exponent !== undefined ) ? exponent : 10; 73 | /** 74 | * @desc 是否对于所有表面都会逐像元地计算其在光照方向上是否被遮挡,这会消耗大量的计算 75 | * @default 76 | * @type {boolean} 77 | */ 78 | this.castShadow = false; 79 | /** 80 | * @desc 控制是否只产生阴影而不“照亮”物体 81 | * @default 82 | * @type {boolean} 83 | */ 84 | this.onlyShadow = false; 85 | 86 | // 87 | /** 88 | * @desc 平截头体近端,定义一个范围(平截头体),不计算在范围之外的物体的阴影 89 | * @default 90 | * @type {float} 91 | */ 92 | this.shadowCameraNear = 50; 93 | /** 94 | * @desc 平截头体远端,定义一个范围(平截头体),不计算在范围之外的物体的阴影 95 | * @default 96 | * @type {float} 97 | */ 98 | this.shadowCameraFar = 5000; 99 | /** 100 | * @desc 平截头体视野,定义一个范围(平截头体),不计算在范围之外的物体的阴影 101 | * @default 102 | * @type {float} 103 | */ 104 | this.shadowCameraFov = 50; 105 | /** 106 | * @desc 会在场景中显示灯光的框架,方便调试 107 | * @default 108 | * @type {boolean} 109 | */ 110 | this.shadowCameraVisible = false; 111 | /** 112 | * @desc 阴影贴图的偏移 113 | * @default 114 | * @type {float} 115 | */ 116 | this.shadowBias = 0; 117 | /** 118 | * @desc 阴影对物体亮度的影响 119 | * @default 120 | * @type {float} 121 | */ 122 | this.shadowDarkness = 0.5; 123 | /** 124 | * @desc 阴影贴图宽度 125 | * @default 126 | * @type {float} 127 | */ 128 | this.shadowMapWidth = 512; 129 | /** 130 | * @desc 阴影贴图高度 131 | * @default 132 | * @type {float} 133 | */ 134 | this.shadowMapHeight = 512; 135 | 136 | // 137 | /** 138 | * @desc 指定阴影贴图 139 | * @default 140 | * @type {null} 141 | */ 142 | this.shadowMap = null; 143 | /** 144 | * @desc 指定阴影贴图大小 145 | * @default 146 | * @type {number} 147 | */ 148 | this.shadowMapSize = null; 149 | /** 150 | * @desc 指定阴影相机 151 | * @default 152 | * @type {THREE.Camera} 153 | */ 154 | this.shadowCamera = null; 155 | /** 156 | * @desc 指定阴影矩阵 157 | * @default 158 | * @type {THREE.Matrix4} 159 | */ 160 | this.shadowMatrix = null; 161 | 162 | }; 163 | /** 164 | * @desc SpotLight对象从THREE.Light的原型继承所有属性方法 165 | * @type {THREE.Light} 166 | */ 167 | THREE.SpotLight.prototype = Object.create( THREE.Light.prototype ); 168 | /** 169 | * @desc SpotLight克隆函数 170 | * @returns {THREE.SpotLight} 171 | */ 172 | THREE.SpotLight.prototype.clone = function () { 173 | 174 | var light = new THREE.SpotLight(); 175 | 176 | THREE.Light.prototype.clone.call( this, light ); 177 | 178 | light.target = this.target.clone(); 179 | 180 | light.intensity = this.intensity; 181 | light.distance = this.distance; 182 | light.angle = this.angle; 183 | light.exponent = this.exponent; 184 | 185 | light.castShadow = this.castShadow; 186 | light.onlyShadow = this.onlyShadow; 187 | 188 | // 189 | 190 | light.shadowCameraNear = this.shadowCameraNear; 191 | light.shadowCameraFar = this.shadowCameraFar; 192 | light.shadowCameraFov = this.shadowCameraFov; 193 | 194 | light.shadowCameraVisible = this.shadowCameraVisible; 195 | 196 | light.shadowBias = this.shadowBias; 197 | light.shadowDarkness = this.shadowDarkness; 198 | 199 | light.shadowMapWidth = this.shadowMapWidth; 200 | light.shadowMapHeight = this.shadowMapHeight; 201 | 202 | return light; 203 | 204 | }; 205 | -------------------------------------------------------------------------------- /math/Spline.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Spline from Tween.js, slightly optimized (and trashed) 3 | * http://sole.github.com/tween.js/examples/05_spline.html 4 | * 5 | * @author mrdoob / http://mrdoob.com/ 6 | * @author alteredq / http://alteredqualia.com/ 7 | */ 8 | /** 9 | * @classdesc 曲线对象类
10 | * 注释内容部分参照 http://blog.csdn.net/omni360 11 | * @desc 由Vector3数组(points)组成的曲线 12 | * @param {THREE.Vector3[]} points 13 | * @constructor 14 | */ 15 | THREE.Spline = function ( points ) { 16 | /** 17 | * @desc 曲线控制点 18 | * @type {THREE.Vector3[]} 19 | */ 20 | this.points = points; 21 | 22 | var c = [], v3 = { x: 0, y: 0, z: 0 }, 23 | point, intPoint, weight, w2, w3, 24 | pa, pb, pc, pd; 25 | 26 | /** 27 | * @desc 从数组初始化曲线 28 | * @param {THREE.Vector3} a 29 | */ 30 | this.initFromArray = function ( a ) { 31 | 32 | this.points = []; 33 | 34 | for ( var i = 0; i < a.length; i ++ ) { 35 | 36 | this.points[ i ] = { x: a[ i ][ 0 ], y: a[ i ][ 1 ], z: a[ i ][ 2 ] }; 37 | 38 | } 39 | 40 | }; 41 | /** 42 | * @desc 当前样条曲线作为一个整体,返回位于当前样条曲线k位置上的点坐标. 43 | * @param {float} k 44 | * @returns {{x: float, y: float, z: float}} 45 | */ 46 | this.getPoint = function ( k ) { 47 | 48 | point = ( this.points.length - 1 ) * k; 49 | intPoint = Math.floor( point ); 50 | weight = point - intPoint; 51 | 52 | c[ 0 ] = intPoint === 0 ? intPoint : intPoint - 1; 53 | c[ 1 ] = intPoint; 54 | c[ 2 ] = intPoint > this.points.length - 2 ? this.points.length - 1 : intPoint + 1; 55 | c[ 3 ] = intPoint > this.points.length - 3 ? this.points.length - 1 : intPoint + 2; 56 | 57 | pa = this.points[ c[ 0 ] ]; 58 | pb = this.points[ c[ 1 ] ]; 59 | pc = this.points[ c[ 2 ] ]; 60 | pd = this.points[ c[ 3 ] ]; 61 | 62 | w2 = weight * weight; 63 | w3 = weight * w2; 64 | 65 | v3.x = interpolate( pa.x, pb.x, pc.x, pd.x, weight, w2, w3 ); 66 | v3.y = interpolate( pa.y, pb.y, pc.y, pd.y, weight, w2, w3 ); 67 | v3.z = interpolate( pa.z, pb.z, pc.z, pd.z, weight, w2, w3 ); 68 | 69 | return v3; 70 | 71 | }; 72 | 73 | /** 74 | * @desc 返回当前样条曲线节点坐标构成的数组 75 | * @returns {THREE.Vector3[]} 76 | */ 77 | this.getControlPointsArray = function () { 78 | 79 | var i, p, l = this.points.length, 80 | coords = []; 81 | 82 | for ( i = 0; i < l; i ++ ) { 83 | 84 | p = this.points[ i ]; 85 | coords[ i ] = [ p.x, p.y, p.z ]; 86 | 87 | } 88 | 89 | return coords; 90 | 91 | }; 92 | 93 | // approximate length by summing linear segments 94 | /** 95 | * @desc 被参数nSubDivisions(将当前样条曲线等分成多少段)等分当前样条曲线的长度数组和总长度组成的对象. 96 | * @param {number} nSubDivisions 97 | * @returns {{chunks: Array, total: number}} 98 | */ 99 | this.getLength = function ( nSubDivisions ) { 100 | 101 | var i, index, nSamples, position, 102 | point = 0, intPoint = 0, oldIntPoint = 0, 103 | oldPosition = new THREE.Vector3(), 104 | tmpVec = new THREE.Vector3(), 105 | chunkLengths = [], 106 | totalLength = 0; 107 | 108 | // first point has 0 length 109 | 110 | chunkLengths[ 0 ] = 0; 111 | 112 | if ( ! nSubDivisions ) nSubDivisions = 100; 113 | 114 | nSamples = this.points.length * nSubDivisions; 115 | 116 | oldPosition.copy( this.points[ 0 ] ); 117 | 118 | for ( i = 1; i < nSamples; i ++ ) { 119 | 120 | index = i / nSamples; 121 | 122 | position = this.getPoint( index ); 123 | tmpVec.copy( position ); 124 | 125 | totalLength += tmpVec.distanceTo( oldPosition ); 126 | 127 | oldPosition.copy( position ); 128 | 129 | point = ( this.points.length - 1 ) * index; 130 | intPoint = Math.floor( point ); 131 | 132 | if ( intPoint != oldIntPoint ) { 133 | 134 | chunkLengths[ intPoint ] = totalLength; 135 | oldIntPoint = intPoint; 136 | 137 | } 138 | 139 | } 140 | 141 | // last point ends with total length 142 | 143 | chunkLengths[ chunkLengths.length ] = totalLength; 144 | 145 | return { chunks: chunkLengths, total: totalLength }; 146 | 147 | }; 148 | 149 | this.reparametrizeByArcLength = function ( samplingCoef ) { 150 | 151 | var i, j, 152 | index, indexCurrent, indexNext, 153 | linearDistance, realDistance, 154 | sampling, position, 155 | newpoints = [], 156 | tmpVec = new THREE.Vector3(), 157 | sl = this.getLength(); 158 | 159 | newpoints.push( tmpVec.copy( this.points[ 0 ] ).clone() ); 160 | 161 | for ( i = 1; i < this.points.length; i ++ ) { 162 | 163 | //tmpVec.copy( this.points[ i - 1 ] ); 164 | //linearDistance = tmpVec.distanceTo( this.points[ i ] ); 165 | 166 | realDistance = sl.chunks[ i ] - sl.chunks[ i - 1 ]; 167 | 168 | sampling = Math.ceil( samplingCoef * realDistance / sl.total ); 169 | 170 | indexCurrent = ( i - 1 ) / ( this.points.length - 1 ); 171 | indexNext = i / ( this.points.length - 1 ); 172 | 173 | for ( j = 1; j < sampling - 1; j ++ ) { 174 | 175 | index = indexCurrent + j * ( 1 / sampling ) * ( indexNext - indexCurrent ); 176 | 177 | position = this.getPoint( index ); 178 | newpoints.push( tmpVec.copy( position ).clone() ); 179 | 180 | } 181 | 182 | newpoints.push( tmpVec.copy( this.points[ i ] ).clone() ); 183 | 184 | } 185 | 186 | this.points = newpoints; 187 | 188 | }; 189 | 190 | // Catmull-Rom 191 | 192 | /** 193 | * @desc 三次样条插值算法,返回计算位于参数值t的曲线点 194 | * @param {float} p0 样条曲线起始点p0 195 | * @param {float} p1 样条曲线起始点p1 196 | * @param {float} p2 样条曲线起始点p2 197 | * @param {float} p3 样条曲线起始点p3 198 | * @param {float} t 参数值 (0,1) 199 | * @param {float} t2 参数值t的平方 200 | * @param {float} t3 参数值t的立方 201 | * @returns {float} 计算位于参数值t的曲线点 202 | */ 203 | function interpolate( p0, p1, p2, p3, t, t2, t3 ) { 204 | 205 | var v0 = ( p2 - p0 ) * 0.5, 206 | v1 = ( p3 - p1 ) * 0.5; 207 | 208 | return ( 2 * ( p1 - p2 ) + v0 + v1 ) * t3 + ( - 3 * ( p1 - p2 ) - 2 * v0 - v1 ) * t2 + v0 * t + p1; 209 | 210 | }; 211 | 212 | }; 213 | -------------------------------------------------------------------------------- /math/Frustum.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author mrdoob / http://mrdoob.com/ 3 | * @author alteredq / http://alteredqualia.com/ 4 | * @author bhouston / http://exocortex.com 5 | */ 6 | /** 7 | * @classdesc 平截头体对象
8 | * 注释内容部分参照 http://blog.csdn.net/omni360 9 | * @param {THREE.Plane} p0 10 | * @param {THREE.Plane} p1 11 | * @param {THREE.Plane} p2 12 | * @param {THREE.Plane} p3 13 | * @param {THREE.Plane} p4 14 | * @param {THREE.Plane} p5 15 | * @constructor 16 | */ 17 | THREE.Frustum = function ( p0, p1, p2, p3, p4, p5 ) { 18 | 19 | this.planes = [ 20 | 21 | ( p0 !== undefined ) ? p0 : new THREE.Plane(), 22 | ( p1 !== undefined ) ? p1 : new THREE.Plane(), 23 | ( p2 !== undefined ) ? p2 : new THREE.Plane(), 24 | ( p3 !== undefined ) ? p3 : new THREE.Plane(), 25 | ( p4 !== undefined ) ? p4 : new THREE.Plane(), 26 | ( p5 !== undefined ) ? p5 : new THREE.Plane() 27 | 28 | ]; 29 | 30 | }; 31 | 32 | THREE.Frustum.prototype = { 33 | 34 | constructor: THREE.Frustum, 35 | /** 36 | * @desc 设置平截头体对象 37 | * @param {THREE.Plane} p0 38 | * @param {THREE.Plane} p1 39 | * @param {THREE.Plane} p2 40 | * @param {THREE.Plane} p3 41 | * @param {THREE.Plane} p4 42 | * @param {THREE.Plane} p5 43 | * @returns {THREE.Frustum} 44 | */ 45 | set: function ( p0, p1, p2, p3, p4, p5 ) { 46 | 47 | var planes = this.planes; 48 | 49 | planes[ 0 ].copy( p0 ); 50 | planes[ 1 ].copy( p1 ); 51 | planes[ 2 ].copy( p2 ); 52 | planes[ 3 ].copy( p3 ); 53 | planes[ 4 ].copy( p4 ); 54 | planes[ 5 ].copy( p5 ); 55 | 56 | return this; 57 | 58 | }, 59 | /** 60 | * @desc 拷贝平截头体对象 61 | * @param {THREE.Frustum} frustum 62 | * @returns {THREE.Frustum} 63 | */ 64 | copy: function ( frustum ) { 65 | 66 | var planes = this.planes; 67 | 68 | for ( var i = 0; i < 6; i ++ ) { 69 | 70 | planes[ i ].copy( frustum.planes[ i ] ); 71 | 72 | } 73 | 74 | return this; 75 | 76 | }, 77 | /** 78 | * @desc 通过对当前平截头体应用变换,返回新的平截头体 79 | * @param {THREE.Matrix4} m 80 | * @returns {THREE.Frustum} 81 | */ 82 | setFromMatrix: function ( m ) { 83 | 84 | var planes = this.planes; 85 | var me = m.elements; 86 | var me0 = me[ 0 ], me1 = me[ 1 ], me2 = me[ 2 ], me3 = me[ 3 ]; 87 | var me4 = me[ 4 ], me5 = me[ 5 ], me6 = me[ 6 ], me7 = me[ 7 ]; 88 | var me8 = me[ 8 ], me9 = me[ 9 ], me10 = me[ 10 ], me11 = me[ 11 ]; 89 | var me12 = me[ 12 ], me13 = me[ 13 ], me14 = me[ 14 ], me15 = me[ 15 ]; 90 | 91 | planes[ 0 ].setComponents( me3 - me0, me7 - me4, me11 - me8, me15 - me12 ).normalize(); 92 | planes[ 1 ].setComponents( me3 + me0, me7 + me4, me11 + me8, me15 + me12 ).normalize(); 93 | planes[ 2 ].setComponents( me3 + me1, me7 + me5, me11 + me9, me15 + me13 ).normalize(); 94 | planes[ 3 ].setComponents( me3 - me1, me7 - me5, me11 - me9, me15 - me13 ).normalize(); 95 | planes[ 4 ].setComponents( me3 - me2, me7 - me6, me11 - me10, me15 - me14 ).normalize(); 96 | planes[ 5 ].setComponents( me3 + me2, me7 + me6, me11 + me10, me15 + me14 ).normalize(); 97 | 98 | return this; 99 | 100 | }, 101 | /** 102 | * @function 103 | * @desc 当前平截头体是否与参数object对象相交 104 | * @param {THREE.Object3D} object 105 | * @return {boolean} 106 | */ 107 | intersectsObject: function () { 108 | 109 | var sphere = new THREE.Sphere(); 110 | 111 | return function ( object ) { 112 | 113 | var geometry = object.geometry; 114 | 115 | if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere(); 116 | 117 | sphere.copy( geometry.boundingSphere ); 118 | sphere.applyMatrix4( object.matrixWorld ); 119 | 120 | return this.intersectsSphere( sphere ); 121 | 122 | }; 123 | 124 | }(), 125 | /** 126 | * @desc 当前平截头体是否与参数sphere球体对象相交 127 | * @param {THREE.Sphere} sphere 128 | * @returns {boolean} 129 | */ 130 | intersectsSphere: function ( sphere ) { 131 | 132 | var planes = this.planes; 133 | var center = sphere.center; 134 | var negRadius = - sphere.radius; 135 | 136 | for ( var i = 0; i < 6; i ++ ) { 137 | 138 | var distance = planes[ i ].distanceToPoint( center ); 139 | 140 | if ( distance < negRadius ) { 141 | 142 | return false; 143 | 144 | } 145 | 146 | } 147 | 148 | return true; 149 | 150 | }, 151 | /** 152 | * 153 | * @function 154 | * @desc 当前平截头体是否与参数box立方体对象相交 155 | * @param {THREE.Box3} box 156 | * @returns {boolean} 157 | */ 158 | intersectsBox: function () { 159 | 160 | var p1 = new THREE.Vector3(), 161 | p2 = new THREE.Vector3(); 162 | 163 | return function ( box ) { 164 | 165 | var planes = this.planes; 166 | 167 | for ( var i = 0; i < 6 ; i ++ ) { 168 | 169 | var plane = planes[ i ]; 170 | 171 | p1.x = plane.normal.x > 0 ? box.min.x : box.max.x; 172 | p2.x = plane.normal.x > 0 ? box.max.x : box.min.x; 173 | p1.y = plane.normal.y > 0 ? box.min.y : box.max.y; 174 | p2.y = plane.normal.y > 0 ? box.max.y : box.min.y; 175 | p1.z = plane.normal.z > 0 ? box.min.z : box.max.z; 176 | p2.z = plane.normal.z > 0 ? box.max.z : box.min.z; 177 | 178 | var d1 = plane.distanceToPoint( p1 ); 179 | var d2 = plane.distanceToPoint( p2 ); 180 | 181 | // if both outside plane, no intersection 182 | 183 | if ( d1 < 0 && d2 < 0 ) { 184 | 185 | return false; 186 | 187 | } 188 | } 189 | 190 | return true; 191 | }; 192 | 193 | }(), 194 | 195 | /** 196 | * @desc 参数point(一个Vector3的三维点坐标)是否在当前平截头体内 197 | * @param {THREE.Vector3} point 198 | * @returns {boolean} 199 | */ 200 | containsPoint: function ( point ) { 201 | 202 | var planes = this.planes; 203 | 204 | for ( var i = 0; i < 6; i ++ ) { 205 | 206 | if ( planes[ i ].distanceToPoint( point ) < 0 ) { 207 | 208 | return false; 209 | 210 | } 211 | 212 | } 213 | 214 | return true; 215 | 216 | }, 217 | /** 218 | * @desc 克隆当前平截头体 219 | * @returns {THREE.Frustum} 220 | */ 221 | clone: function () { 222 | 223 | return new THREE.Frustum().copy( this ); 224 | 225 | } 226 | 227 | }; 228 | -------------------------------------------------------------------------------- /materials/MeshLambertMaterial.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author mrdoob / http://mrdoob.com/ 3 | * @author alteredq / http://alteredqualia.com/ 4 | * 5 | * parameters = { 6 | * color: , 7 | * ambient: , 8 | * emissive: , 9 | * opacity: , 10 | * 11 | * map: new THREE.Texture( ), 12 | * 13 | * lightMap: new THREE.Texture( ), 14 | * 15 | * specularMap: new THREE.Texture( ), 16 | * 17 | * alphaMap: new THREE.Texture( ), 18 | * 19 | * envMap: new THREE.TextureCube( [posx, negx, posy, negy, posz, negz] ), 20 | * combine: THREE.Multiply, 21 | * reflectivity: , 22 | * refractionRatio: , 23 | * 24 | * shading: THREE.SmoothShading, 25 | * blending: THREE.NormalBlending, 26 | * depthTest: , 27 | * depthWrite: , 28 | * 29 | * wireframe: , 30 | * wireframeLinewidth: , 31 | * 32 | * vertexColors: THREE.NoColors / THREE.VertexColors / THREE.FaceColors, 33 | * 34 | * skinning: , 35 | * morphTargets: , 36 | * morphNormals: , 37 | * 38 | * fog: 39 | * } 40 | */ 41 | /** 42 | * @classdesc mesh(网格)的Lambert(兰伯特)材质
43 | * 注释内容部分参照 http://blog.csdn.net/omni360 44 | * @desc 表面有光泽的材质类型,计算每个像素) 45 | * @param {String} parameters 材质参数 46 | * @extends {THREE.Material} 47 | * @constructor 48 | */ 49 | THREE.MeshLambertMaterial = function ( parameters ) { 50 | 51 | THREE.Material.call( this ); 52 | /** 53 | * @default 'MeshLambertMaterial' 54 | * @type {string} 55 | */ 56 | this.type = 'MeshLambertMaterial'; 57 | /** 58 | * @desc 材质颜色 59 | * @default 0xffffff 白色 60 | * @type {THREE.Color} 61 | */ 62 | this.color = new THREE.Color( 0xffffff ); // diffuse 63 | /** 64 | * @desc 环境色 65 | * @default 0xffffff 白色 66 | * @type {THREE.Color} 67 | */ 68 | this.ambient = new THREE.Color( 0xffffff ); 69 | /** 70 | * @desc 自发光(荧光)颜色 71 | * @default 0x000000 黑色 72 | * @type {THREE.Color} 73 | */ 74 | this.emissive = new THREE.Color( 0x000000 ); 75 | /** 76 | * @desc 是否遮罩 77 | * @default 78 | * @type {boolean} 79 | */ 80 | this.wrapAround = false; 81 | /** 82 | * @desc 遮罩颜色 83 | * @default ( 1, 1, 1 ) 84 | * @type {THREE.Vector3} 85 | */ 86 | this.wrapRGB = new THREE.Vector3( 1, 1, 1 ); 87 | /** 88 | * @desc 纹理贴图 89 | * @default 90 | * @type {THREE.Texture} 91 | */ 92 | this.map = null; 93 | /** 94 | * @desc 光照贴图 95 | * @default 96 | * @type {THREE.Texture} 97 | */ 98 | this.lightMap = null; 99 | /** 100 | * @desc 高光贴图 101 | * @default 102 | * @type {THREE.Texture} 103 | */ 104 | this.specularMap = null; 105 | /** 106 | * @desc 透明贴图 107 | * @default 108 | * @type {THREE.Texture} 109 | */ 110 | this.alphaMap = null; 111 | /** 112 | * @desc 环境贴图 113 | * @default 114 | * @type {THREE.Texture} 115 | */ 116 | this.envMap = null; 117 | /** 118 | * @desc 材质混合模式 119 | * @default THREE.MultiplyOperation 120 | * @type {number} 121 | */ 122 | this.combine = THREE.MultiplyOperation; 123 | /** 124 | * @desc 反射率 125 | * @default 126 | * @type {float} 127 | */ 128 | this.reflectivity = 1; 129 | /** 130 | * @desc 折射率 131 | * @default 132 | * @type {float} 133 | */ 134 | this.refractionRatio = 0.98; 135 | 136 | /** 137 | * @desc 雾效,默认开启 138 | * @default 139 | * @type {boolean} 140 | */ 141 | this.fog = true; 142 | /** 143 | * @desc 着色方式
144 | * THREE.SmoothShading平滑着色:用多种颜色进行绘制
145 | * 每个顶点都是单独进行处理的,各顶点和各图元之间采用均匀插值。 146 | * @default 147 | * @type {number} 148 | */ 149 | this.shading = THREE.SmoothShading; 150 | 151 | /** 152 | * @desc 是否以线框方式渲染几何体 153 | * @default 154 | * @type {boolean} 155 | */ 156 | this.wireframe = false; 157 | /** 158 | * @desc 线框宽度 159 | * @default 160 | * @type {float} 161 | */ 162 | this.wireframeLinewidth = 1; 163 | /** 164 | * @desc 线框端点类型,参照LineBasicMaterial的定义 165 | * @default 'round' 166 | * @type {string} 167 | */ 168 | this.wireframeLinecap = 'round'; 169 | /** 170 | * @desc 线框连接类型,参照LineBasicMaterial的定义 171 | * @default 'round' 172 | * @type {string} 173 | */ 174 | this.wireframeLinejoin = 'round'; 175 | 176 | /** 177 | * @desc 材质顶点颜色 178 | * @default THREE.NoColors 179 | * @type {number} 180 | */ 181 | this.vertexColors = THREE.NoColors; 182 | 183 | /** 184 | * @desc 材质是否使用蒙皮 185 | * @default 186 | * @type {boolean} 187 | */ 188 | this.skinning = false; 189 | /** 190 | * @desc 材质是否设定目标变形动画 191 | * @default 192 | * @type {boolean} 193 | */ 194 | this.morphTargets = false; 195 | /** 196 | * @desc 材质是否反转(变换)法线 197 | * @default 198 | * @type {boolean} 199 | */ 200 | this.morphNormals = false; 201 | 202 | this.setValues( parameters ); 203 | 204 | }; 205 | /** 206 | * @desc MeshLambertMaterial对象从THREE.Material的原型继承所有属性方法 207 | * @type {THREE.Material} 208 | */ 209 | THREE.MeshLambertMaterial.prototype = Object.create( THREE.Material.prototype ); 210 | /** 211 | * @desc MeshLambertMaterial材质的克隆函数 212 | * @returns {THREE.MeshLambertMaterial} 213 | */ 214 | THREE.MeshLambertMaterial.prototype.clone = function () { 215 | 216 | var material = new THREE.MeshLambertMaterial(); 217 | 218 | THREE.Material.prototype.clone.call( this, material ); 219 | 220 | material.color.copy( this.color ); 221 | material.ambient.copy( this.ambient ); 222 | material.emissive.copy( this.emissive ); 223 | 224 | material.wrapAround = this.wrapAround; 225 | material.wrapRGB.copy( this.wrapRGB ); 226 | 227 | material.map = this.map; 228 | 229 | material.lightMap = this.lightMap; 230 | 231 | material.specularMap = this.specularMap; 232 | 233 | material.alphaMap = this.alphaMap; 234 | 235 | material.envMap = this.envMap; 236 | material.combine = this.combine; 237 | material.reflectivity = this.reflectivity; 238 | material.refractionRatio = this.refractionRatio; 239 | 240 | material.fog = this.fog; 241 | 242 | material.shading = this.shading; 243 | 244 | material.wireframe = this.wireframe; 245 | material.wireframeLinewidth = this.wireframeLinewidth; 246 | material.wireframeLinecap = this.wireframeLinecap; 247 | material.wireframeLinejoin = this.wireframeLinejoin; 248 | 249 | material.vertexColors = this.vertexColors; 250 | 251 | material.skinning = this.skinning; 252 | material.morphTargets = this.morphTargets; 253 | material.morphNormals = this.morphNormals; 254 | 255 | return material; 256 | 257 | }; 258 | -------------------------------------------------------------------------------- /lights/DirectionalLight.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author mrdoob / http://mrdoob.com/ 3 | * @author alteredq / http://alteredqualia.com/ 4 | */ 5 | /** 6 | * @classdesc 平行光源对象
7 | * 注释内容部分参照 http://blog.csdn.net/omni360 8 | * @desc 平行光支持阴影 9 | * @param {THREE.Color} color 平行光的颜色属性 10 | * @param {float} intensity 平行光的强度,默认是1 11 | * @extends {THREE.Light} 12 | * @constructor 13 | */ 14 | THREE.DirectionalLight = function ( color, intensity ) { 15 | 16 | THREE.Light.call( this, color ); 17 | /** 18 | * @default 19 | * @type {string} 20 | */ 21 | this.type = 'DirectionalLight'; 22 | /** 23 | * @desc 灯光的位置属性初始化为,0,1,0 24 | */ 25 | this.position.set( 0, 1, 0 ); 26 | /** 27 | * @desc 创建一个目标点对象,目标点对象是一个Object3D对象 28 | * @type {THREE.Object3D} 29 | */ 30 | this.target = new THREE.Object3D(); 31 | /** 32 | * desc 灯光的强度
33 | * (光线的密度,默认为1。因为RGB的三个值均在0~255之间,
34 | * 不能反映出光照的强度变化,光照越强,物体表面就更明亮。) 35 | * @default 1 36 | * @type {float} 37 | */ 38 | this.intensity = ( intensity !== undefined ) ? intensity : 1; 39 | /** 40 | * @desc 是否对于所有表面都会逐像元地计算其在光照方向上是否被遮挡,这会消耗大量的计算 41 | * @default 42 | * @type {boolean} 43 | */ 44 | this.castShadow = false; 45 | /** 46 | * @desc 控制是否只产生阴影而不“照亮”物体 47 | * @default 48 | * @type {boolean} 49 | */ 50 | this.onlyShadow = false; 51 | 52 | // 53 | /** 54 | * @desc 平截头体近端,定义一个范围(平截头体),不计算在范围之外的物体的阴影 55 | * @default 56 | * @type {float} 57 | */ 58 | this.shadowCameraNear = 50; 59 | /** 60 | * @desc 平截头体远端,定义一个范围(平截头体),不计算在范围之外的物体的阴影 61 | * @default 62 | * @type {float} 63 | */ 64 | this.shadowCameraFar = 5000; 65 | /** 66 | * @desc 相机左侧距离,不计算在范围之外的物体的阴影 67 | * @default 68 | * @type {float} 69 | */ 70 | this.shadowCameraLeft = - 500; 71 | /** 72 | * @desc 相机右侧距离,不计算在范围之外的物体的阴影 73 | * @default 74 | * @type {float} 75 | */ 76 | this.shadowCameraRight = 500; 77 | /** 78 | * @desc 相机上侧距离,不计算在范围之外的物体的阴影 79 | * @default 80 | * @type {float} 81 | */ 82 | this.shadowCameraTop = 500; 83 | /** 84 | * @desc 相机下侧距离,不计算在范围之外的物体的阴影 85 | * @default 86 | * @type {float} 87 | */ 88 | this.shadowCameraBottom = - 500; 89 | /** 90 | * @desc 会在场景中显示灯光的框架,方便调试 91 | * @default 92 | * @type {boolean} 93 | */ 94 | this.shadowCameraVisible = false; 95 | /** 96 | * @desc 阴影贴图的偏移 97 | * @default 98 | * @type {float} 99 | */ 100 | this.shadowBias = 0; 101 | /** 102 | * @desc 阴影对物体亮度的影响 103 | * @default 104 | * @type {float} 105 | */ 106 | this.shadowDarkness = 0.5; 107 | /** 108 | * @desc 阴影贴图宽度 109 | * @default 110 | * @type {float} 111 | */ 112 | this.shadowMapWidth = 512; 113 | /** 114 | * @desc 阴影贴图高度 115 | * @default 116 | * @type {float} 117 | */ 118 | this.shadowMapHeight = 512; 119 | 120 | // 121 | /** 122 | * @desc 是否支持阴影级联 123 | * @default 124 | * @type {boolean} 125 | */ 126 | this.shadowCascade = false; 127 | /** 128 | * @desc 阴影级联偏移距离 129 | * @default ( 0, 0, - 1000 ) 130 | * @type {THREE.Vector3} 131 | */ 132 | this.shadowCascadeOffset = new THREE.Vector3( 0, 0, - 1000 ); 133 | /** 134 | * @desc 当使用2个阴影级联时,整个阴影距离内,默认被分为两块,靠近观察者较小的块和远处较大的块 135 | * @default 136 | * @type {number} 137 | */ 138 | this.shadowCascadeCount = 2; 139 | /** 140 | * @desc 阴影级联偏移数组 141 | * @default 142 | * @type {number[]} 143 | */ 144 | this.shadowCascadeBias = [ 0, 0, 0 ]; 145 | /** 146 | * @desc 阴影级联宽度数组 147 | * @default 148 | * @type {number[]} 149 | */ 150 | this.shadowCascadeWidth = [ 512, 512, 512 ]; 151 | /** 152 | * @desc 阴影级联高度数组 153 | * @default 154 | * @type {number[]} 155 | */ 156 | this.shadowCascadeHeight = [ 512, 512, 512 ]; 157 | /** 158 | * @desc 阴影级联近处 159 | * @default 160 | * @type {number[]} 161 | */ 162 | this.shadowCascadeNearZ = [ - 1.000, 0.990, 0.998 ]; 163 | /** 164 | * @desc 阴影级联远处 165 | * @default 166 | * @type {number[]} 167 | */ 168 | this.shadowCascadeFarZ = [ 0.990, 0.998, 1.000 ]; 169 | /** 170 | * @desc 阴影级联数组 171 | * @type {Array} 172 | */ 173 | this.shadowCascadeArray = []; 174 | 175 | // 176 | 177 | /** 178 | * @desc 指定阴影贴图 179 | * @default 180 | * @type {null} 181 | */ 182 | this.shadowMap = null; 183 | /** 184 | * @desc 指定阴影贴图大小 185 | * @default 186 | * @type {number} 187 | */ 188 | this.shadowMapSize = null; 189 | /** 190 | * @desc 指定阴影相机 191 | * @default 192 | * @type {THREE.Camera} 193 | */ 194 | this.shadowCamera = null; 195 | /** 196 | * @desc 指定阴影矩阵 197 | * @default 198 | * @type {THREE.Matrix4} 199 | */ 200 | this.shadowMatrix = null; 201 | 202 | }; 203 | /** 204 | * @desc DirectionalLight对象从THREE.Light的原型继承所有属性方法 205 | * @type {THREE.Light} 206 | */ 207 | THREE.DirectionalLight.prototype = Object.create( THREE.Light.prototype ); 208 | /** 209 | * @desc DirectionalLight克隆函数 210 | * @returns {THREE.DirectionalLight} 211 | */ 212 | THREE.DirectionalLight.prototype.clone = function () { 213 | 214 | var light = new THREE.DirectionalLight(); 215 | 216 | THREE.Light.prototype.clone.call( this, light ); 217 | 218 | light.target = this.target.clone(); 219 | 220 | light.intensity = this.intensity; 221 | 222 | light.castShadow = this.castShadow; 223 | light.onlyShadow = this.onlyShadow; 224 | 225 | // 226 | 227 | light.shadowCameraNear = this.shadowCameraNear; 228 | light.shadowCameraFar = this.shadowCameraFar; 229 | 230 | light.shadowCameraLeft = this.shadowCameraLeft; 231 | light.shadowCameraRight = this.shadowCameraRight; 232 | light.shadowCameraTop = this.shadowCameraTop; 233 | light.shadowCameraBottom = this.shadowCameraBottom; 234 | 235 | light.shadowCameraVisible = this.shadowCameraVisible; 236 | 237 | light.shadowBias = this.shadowBias; 238 | light.shadowDarkness = this.shadowDarkness; 239 | 240 | light.shadowMapWidth = this.shadowMapWidth; 241 | light.shadowMapHeight = this.shadowMapHeight; 242 | 243 | // 244 | 245 | light.shadowCascade = this.shadowCascade; 246 | 247 | light.shadowCascadeOffset.copy( this.shadowCascadeOffset ); 248 | light.shadowCascadeCount = this.shadowCascadeCount; 249 | 250 | light.shadowCascadeBias = this.shadowCascadeBias.slice( 0 ); 251 | light.shadowCascadeWidth = this.shadowCascadeWidth.slice( 0 ); 252 | light.shadowCascadeHeight = this.shadowCascadeHeight.slice( 0 ); 253 | 254 | light.shadowCascadeNearZ = this.shadowCascadeNearZ.slice( 0 ); 255 | light.shadowCascadeFarZ = this.shadowCascadeFarZ.slice( 0 ); 256 | 257 | return light; 258 | 259 | }; 260 | -------------------------------------------------------------------------------- /cameras/PerspectiveCamera.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author mrdoob / http://mrdoob.com/ 3 | * @author greggman / http://games.greggman.com/ 4 | * @author zz85 / http://www.lab4games.net/zz85/blog 5 | */ 6 | /** 7 | * @classdesc 透视投影相机
8 | * 注释内容部分参照 http://blog.csdn.net/omni360 9 | * @desc 根据 fov, aspect, near, far 生成透视投影相机 10 | * @constructor 11 | * @param {float} fov 相机的可视角度,可选参数,如果未指定,初始化为50 12 | * @param {float} aspect 相机可视范围的长宽比,可选参数,如果未指定,初始化为1 13 | * @param {float} near 相对于深度剪切面的近的距离,必须为正数,可选参数,如果未指定,初始化为0.1 14 | * @param {float} far 相对于深度剪切面的远的距离,必须为正数,可选参数,如果未指定,初始化为2000 15 | * @extends {THREE.Camera} 16 | */ 17 | THREE.PerspectiveCamera = function ( fov, aspect, near, far ) { 18 | 19 | THREE.Camera.call( this ); 20 | /** 21 | * @default 22 | * @type {string} 23 | */ 24 | this.type = 'PerspectiveCamera'; 25 | 26 | /** 27 | * @desc 缩放比例 28 | * @default 29 | * @type {float} 30 | */ 31 | this.zoom = 1; 32 | /** 33 | * @desc 相机的可视角度,可选参数 34 | * @default 50 35 | * @type {float} 36 | */ 37 | this.fov = fov !== undefined ? fov : 50; 38 | /** 39 | * @desc 相机可视范围的长宽比 40 | * @default 1 41 | * @type {float} 42 | */ 43 | this.aspect = aspect !== undefined ? aspect : 1; 44 | /** 45 | * @desc 相对于深度剪切面的近的距离 46 | * @default 0.1 47 | * @type {float} 48 | */ 49 | this.near = near !== undefined ? near : 0.1; 50 | /** 51 | * @desc 相对于深度剪切面的远的距离 52 | * @default 2000 53 | * @type {float} 54 | */ 55 | this.far = far !== undefined ? far : 2000; 56 | 57 | this.updateProjectionMatrix(); 58 | 59 | }; 60 | /** 61 | * @desc 透视相机对象从THREE.Camera的原型继承所有属性方法 62 | * @type {THREE.Camera} 63 | */ 64 | THREE.PerspectiveCamera.prototype = Object.create( THREE.Camera.prototype ); 65 | 66 | 67 | /** 68 | * Uses Focal Length (in mm) to estimate and set FOV 69 | * 35mm (fullframe) camera is used if frame size is not specified; 70 | * Formula based on http://www.bobatkins.com/photography/technical/field_of_view.html 71 | * 使用焦距(单位毫米)设置相机时,如果画幅大小没有指定,默认使用FOV(视野)35mm(全画幅)相机 72 | */ 73 | /** 74 | * @desc 焦距 focalLength, 画幅大小 frameHeight 更新透视投影相机的视野 75 | * @param {float} focalLength 焦距 76 | * @param {float} frameHeight 画幅大小 77 | */ 78 | THREE.PerspectiveCamera.prototype.setLens = function ( focalLength, frameHeight ) { 79 | 80 | if ( frameHeight === undefined ) frameHeight = 24; 81 | 82 | this.fov = 2 * THREE.Math.radToDeg( Math.atan( frameHeight / ( focalLength * 2 ) ) ); 83 | this.updateProjectionMatrix(); 84 | 85 | }; 86 | 87 | 88 | /** 89 | * Sets an offset in a larger frustum. This is useful for multi-window or 90 | * multi-monitor/multi-machine setups. 91 | * 为一个大的平截头体设置视口偏移,这个方法在多显示器,多台机器,显示器矩阵上应用非常有效 92 | * For example, if you have 3x2 monitors and each monitor is 1920x1080 and 93 | * the monitors are in grid like this 94 | * 比如,你有3x2 个显示器,每个显示器的分辨率是1920x1080,组成的显示器矩阵向下面的网格 95 | * +---+---+---+ 96 | * | A | B | C | 97 | * +---+---+---+ 98 | * | D | E | F | 99 | * +---+---+---+ 100 | * 101 | * then for each monitor you would call it like this 102 | * 然后,你可以向下面这样为每台显示器调用setOffset()方法,让每个显示器显示画布的一部分 103 | * var w = 1920; 104 | * var h = 1080; 105 | * var fullWidth = w * 3; 106 | * var fullHeight = h * 2; 107 | * 108 | * --A-- 109 | * camera.setOffset( fullWidth, fullHeight, w * 0, h * 0, w, h ); 110 | * --B-- 111 | * camera.setOffset( fullWidth, fullHeight, w * 1, h * 0, w, h ); 112 | * --C-- 113 | * camera.setOffset( fullWidth, fullHeight, w * 2, h * 0, w, h ); 114 | * --D-- 115 | * camera.setOffset( fullWidth, fullHeight, w * 0, h * 1, w, h ); 116 | * --E-- 117 | * camera.setOffset( fullWidth, fullHeight, w * 1, h * 1, w, h ); 118 | * --F-- 119 | * camera.setOffset( fullWidth, fullHeight, w * 2, h * 1, w, h ); 120 | * 121 | * Note there is no reason monitors have to be the same size or in a grid. 122 | * 注意,有可能,这些显示器不是同样的尺寸.所以你可以根据需要设置你想要的各种方式 123 | */ 124 | /** 125 | * 一个大的平截头体设置视口偏移,这个方法在多显示器,多台机器,显示器矩阵上应用非常有效 126 | * @param {number} fullWidth 一个超大的摄像机场景的总宽度 127 | * @param {number} fullHeight 一个超大的摄像机场景的总高度 128 | * @param {number} x 当前摄像机左上角点的x坐标在网格内的起始点 129 | * @param {number} y 当前摄像机左上角点的y坐标在网格内的起始点 130 | * @param {number} width 当前摄像机的宽度 131 | * @param {number} height 当前摄像机的高度 132 | */ 133 | THREE.PerspectiveCamera.prototype.setViewOffset = function ( fullWidth, fullHeight, x, y, width, height ) { 134 | /** 135 | * @memberof THREE.PerspectiveCamera 136 | * @type {number} 137 | */ 138 | this.fullWidth = fullWidth; 139 | /** 140 | * @memberof THREE.PerspectiveCamera 141 | * @type {number} 142 | */ 143 | this.fullHeight = fullHeight; 144 | /** 145 | * @memberof THREE.PerspectiveCamera 146 | * @type {number} 147 | */ 148 | this.x = x; 149 | /** 150 | * @memberof THREE.PerspectiveCamera 151 | * @type {number} 152 | */ 153 | this.y = y; 154 | /** 155 | * @memberof THREE.PerspectiveCamera 156 | * @type {number} 157 | */ 158 | this.width = width; 159 | /** 160 | * @memberof THREE.PerspectiveCamera 161 | * @type {number} 162 | */ 163 | this.height = height; 164 | 165 | this.updateProjectionMatrix(); 166 | 167 | }; 168 | 169 | /** 170 | * @desc 返回透视投影相机的可视边界的矩阵.当相机的参数被更改后,必须调用此参数 171 | */ 172 | THREE.PerspectiveCamera.prototype.updateProjectionMatrix = function () { 173 | 174 | var fov = THREE.Math.radToDeg( 2 * Math.atan( Math.tan( THREE.Math.degToRad( this.fov ) * 0.5 ) / this.zoom ) ); 175 | 176 | if ( this.fullWidth ) { 177 | 178 | var aspect = this.fullWidth / this.fullHeight; 179 | var top = Math.tan( THREE.Math.degToRad( fov * 0.5 ) ) * this.near; 180 | var bottom = - top; 181 | var left = aspect * bottom; 182 | var right = aspect * top; 183 | var width = Math.abs( right - left ); 184 | var height = Math.abs( top - bottom ); 185 | 186 | this.projectionMatrix.makeFrustum( 187 | left + this.x * width / this.fullWidth, 188 | left + ( this.x + this.width ) * width / this.fullWidth, 189 | top - ( this.y + this.height ) * height / this.fullHeight, 190 | top - this.y * height / this.fullHeight, 191 | this.near, 192 | this.far 193 | ); 194 | 195 | } else { 196 | 197 | this.projectionMatrix.makePerspective( fov, this.aspect, this.near, this.far ); 198 | 199 | } 200 | 201 | }; 202 | /** 203 | * @desc 克隆透视投影矩阵 204 | * @returns {THREE.PerspectiveCamera} 205 | */ 206 | THREE.PerspectiveCamera.prototype.clone = function () { 207 | 208 | var camera = new THREE.PerspectiveCamera(); 209 | 210 | THREE.Camera.prototype.clone.call( this, camera ); 211 | 212 | camera.zoom = this.zoom; 213 | 214 | camera.fov = this.fov; 215 | camera.aspect = this.aspect; 216 | camera.near = this.near; 217 | camera.far = this.far; 218 | 219 | camera.projectionMatrix.copy( this.projectionMatrix ); 220 | 221 | return camera; 222 | 223 | }; 224 | -------------------------------------------------------------------------------- /objects/Skeleton.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author mikael emtinger / http://gomo.se/ 3 | * @author alteredq / http://alteredqualia.com/ 4 | * @author michael guerrero / http://realitymeltdown.com 5 | * @author ikerr / http://verold.com 6 | */ 7 | /** 8 | * @classdesc 骨架对象
9 | * 注释内容部分参照 http://blog.csdn.net/omni360 10 | * @desc 是骨骼对象的几何,是蒙皮对象的一部分
11 | * 用来制作支持骨骼动画,当前有两种模型动画的方式:
12 | * 顶点动画和骨骼动画。顶点动画中,每帧动画其实就是模型特定姿态的一个“快照”。
13 | * 通过在帧之间插值的方法, 14 | * @param {THREE.Bone[]} bones 骨骼对象数组 15 | * @param {THREE.Matrix4[]} boneInverses 骨骼对象逆矩阵 16 | * @param {boolean} useVertexTexture 是否适应顶点纹理,该属性之后不可以设置 17 | * @constructor 18 | */ 19 | THREE.Skeleton = function ( bones, boneInverses, useVertexTexture ) { 20 | /** 21 | * @desc 是否使用顶点纹理 22 | * @default true 23 | * @type {boolean} 24 | */ 25 | this.useVertexTexture = useVertexTexture !== undefined ? useVertexTexture : true; 26 | /** 27 | * @desc 单位矩阵 28 | * @type {THREE.Matrix4} 29 | */ 30 | this.identityMatrix = new THREE.Matrix4(); 31 | 32 | // copy the bone array 33 | // 拷贝骨骼数组 34 | bones = bones || []; 35 | /** 36 | * @desc 骨骼数组 37 | * @type {Array.} 38 | */ 39 | this.bones = bones.slice( 0 ); 40 | 41 | // create a bone texture or an array of floats 42 | // 创建骨架纹理或者骨架纹理数组 43 | if ( this.useVertexTexture ) { 44 | 45 | // layout (1 matrix = 4 pixels) 46 | // RGBA RGBA RGBA RGBA (=> column1, column2, column3, column4) 47 | // with 8x8 pixel texture max 16 bones (8 * 8 / 4) 48 | // 16x16 pixel texture max 64 bones (16 * 16 / 4) 49 | // 32x32 pixel texture max 256 bones (32 * 32 / 4) 50 | // 64x64 pixel texture max 1024 bones (64 * 64 / 4) 51 | 52 | var size; 53 | 54 | if ( this.bones.length > 256 ) 55 | size = 64; 56 | else if ( this.bones.length > 64 ) 57 | size = 32; 58 | else if ( this.bones.length > 16 ) 59 | size = 16; 60 | else 61 | size = 8; 62 | /** 63 | * @desc 骨骼纹理宽度 64 | * @memberof THREE.Skeleton 65 | */ 66 | this.boneTextureWidth = size; 67 | /** 68 | * @desc 骨骼纹理高度 69 | * @memberof THREE.Skeleton 70 | */ 71 | this.boneTextureHeight = size; 72 | /** 73 | * @desc 骨骼矩阵 74 | * @memberof THREE.Skeleton 75 | * @type {Float32Array} 76 | */ 77 | this.boneMatrices = new Float32Array( this.boneTextureWidth * this.boneTextureHeight * 4 ); // 4 floats per RGBA pixel 78 | /** 79 | * @desc 骨骼纹理 80 | * @memberof THREE.Skeleton 81 | * @type {THREE.DataTexture} 82 | */ 83 | this.boneTexture = new THREE.DataTexture( this.boneMatrices, this.boneTextureWidth, this.boneTextureHeight, THREE.RGBAFormat, THREE.FloatType ); 84 | /** 85 | * @desc 骨骼纹理缩小插值方式 86 | * @memberof THREE.Skeleton 87 | * @type {number} 88 | */ 89 | this.boneTexture.minFilter = THREE.NearestFilter; 90 | /** 91 | * @desc 骨骼纹理放大插值方式 92 | * @memberof THREE.Skeleton 93 | * @type {number} 94 | */ 95 | this.boneTexture.magFilter = THREE.NearestFilter; 96 | /** 97 | * @desc 骨骼纹理是否生成Mipmap 98 | * @memberof THREE.Skeleton 99 | * @type {boolean} 100 | */ 101 | this.boneTexture.generateMipmaps = false; 102 | /** 103 | * @desc 骨骼纹理是否Y反转 104 | * @memberof THREE.Skeleton 105 | * @type {boolean} 106 | */ 107 | this.boneTexture.flipY = false; 108 | 109 | } else { 110 | // 不使用顶点纹理 111 | this.boneMatrices = new Float32Array( 16 * this.bones.length ); 112 | 113 | } 114 | 115 | // use the supplied bone inverses or calculate the inverses 116 | // 使用提供的骨架位置逆矩阵或计算骨架位置逆矩阵 117 | if ( boneInverses === undefined ) { 118 | // 如果没有提供骨架位置逆矩阵 119 | // 计算骨架位置逆矩阵 120 | this.calculateInverses(); 121 | 122 | } else { 123 | // 如果提供了逆矩阵,并和骨骼数量相等 124 | if ( this.bones.length === boneInverses.length ) { 125 | // 复制骨架的逆矩阵 126 | this.boneInverses = boneInverses.slice( 0 ); 127 | 128 | } else { 129 | // 如果提供的骨骼逆矩阵和骨骼数量不一致 130 | // 提示用户骨骼的逆矩阵和骨骼数量不一致 131 | console.warn( 'THREE.Skeleton bonInverses is the wrong length.' ); 132 | // 清空骨骼逆矩阵 133 | this.boneInverses = []; 134 | // 并将骨骼逆矩阵和骨骼数量保持不一致 135 | for ( var b = 0, bl = this.bones.length; b < bl; b ++ ) { 136 | 137 | this.boneInverses.push( new THREE.Matrix4() ); 138 | 139 | } 140 | 141 | } 142 | 143 | } 144 | 145 | }; 146 | /** 147 | * @desc 方法重新计算骨骼的逆矩阵 148 | */ 149 | THREE.Skeleton.prototype.calculateInverses = function () { 150 | 151 | this.boneInverses = []; 152 | 153 | for ( var b = 0, bl = this.bones.length; b < bl; b ++ ) { 154 | 155 | var inverse = new THREE.Matrix4(); 156 | 157 | if ( this.bones[ b ] ) { 158 | // 获得当前骨骼的位置属性的逆矩阵 159 | inverse.getInverse( this.bones[ b ].matrixWorld ); 160 | 161 | } 162 | // 返回包含骨骼逆矩阵的Skeleton骨架对象 163 | this.boneInverses.push( inverse ); 164 | 165 | } 166 | 167 | }; 168 | /** 169 | * @desc 重新计算骨骼的计算本地矩阵,位置,旋转缩放属性 170 | */ 171 | THREE.Skeleton.prototype.pose = function () { 172 | 173 | var bone; 174 | 175 | // recover the bind-time world matrices 176 | // 恢复在绑定时的世界坐标矩阵 177 | for ( var b = 0, bl = this.bones.length; b < bl; b ++ ) { 178 | 179 | bone = this.bones[ b ]; 180 | 181 | if ( bone ) { 182 | // 恢复在绑定时的世界坐标矩阵 183 | bone.matrixWorld.getInverse( this.boneInverses[ b ] ); 184 | 185 | } 186 | 187 | } 188 | 189 | // compute the local matrices, positions, rotations and scales 190 | // 计算本地矩阵,位置,旋转缩放属性 191 | for ( var b = 0, bl = this.bones.length; b < bl; b ++ ) { 192 | 193 | bone = this.bones[ b ]; 194 | 195 | if ( bone ) { 196 | // 如果骨骼有父级对象 197 | if ( bone.parent ) { 198 | // 求逆父级对象的世界坐标矩阵 199 | bone.matrix.getInverse( bone.parent.matrixWorld ); 200 | // 将当前骨骼的矩阵与父级对象的世界坐标矩阵相乘 201 | bone.matrix.multiply( bone.matrixWorld ); 202 | 203 | } else { 204 | // 复制自身的世界坐标矩阵 205 | bone.matrix.copy( bone.matrixWorld ); 206 | 207 | } 208 | // 调用decompose()方法,重新设置骨骼对象的位置,旋转缩放属性. 209 | bone.matrix.decompose( bone.position, bone.quaternion, bone.scale ); 210 | 211 | } 212 | 213 | } 214 | 215 | }; 216 | /** 217 | * @function 218 | * @desc 法更新当前骨架的缓冲区数据,并更新纹理标识设置为true 219 | */ 220 | THREE.Skeleton.prototype.update = ( function () { 221 | 222 | var offsetMatrix = new THREE.Matrix4(); 223 | 224 | return function () { 225 | 226 | // flatten bone matrices to array 227 | // 展开骨骼矩阵到数组 228 | for ( var b = 0, bl = this.bones.length; b < bl; b ++ ) { 229 | 230 | // compute the offset between the current and the original transform 231 | // 计算当前位置到原始位置的偏移距离 232 | var matrix = this.bones[ b ] ? this.bones[ b ].matrixWorld : this.identityMatrix; 233 | 234 | offsetMatrix.multiplyMatrices( matrix, this.boneInverses[ b ] ); 235 | // 调用flattenToArrayOffset方法,通过参数offset(b * 16)指定偏移量,将矩阵展开到数组(参数array)中,返回新的数组. 236 | offsetMatrix.flattenToArrayOffset( this.boneMatrices, b * 16 ); 237 | 238 | } 239 | // 如果使用顶点纹理 240 | if ( this.useVertexTexture ) { 241 | // 将更新标识设置为true. 242 | this.boneTexture.needsUpdate = true; 243 | 244 | } 245 | 246 | }; 247 | 248 | } )(); 249 | 250 | -------------------------------------------------------------------------------- /core/BufferAttribute.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author mrdoob / http://mrdoob.com/ 3 | */ 4 | 5 | /** 6 | * @classdesc 属性对象类
7 | * 注释内容部分参照 http://blog.csdn.net/omni360 8 | * @desc 存储于bufferGeometry相关联的属性数据 9 | * @param {array} array 属性数组 10 | * @param {number} itemSize 数组元素尺寸 11 | * @constructor 12 | */ 13 | THREE.BufferAttribute = function ( array, itemSize ) { 14 | /** 15 | * @desc 属性数组 16 | * @type {array} 17 | */ 18 | this.array = array; 19 | /** 20 | * @desc 数组元素尺寸 21 | * @type {number} 22 | */ 23 | this.itemSize = itemSize; 24 | /** 25 | * @desc 是否需要更新标识 26 | * @type {boolean} 27 | */ 28 | this.needsUpdate = false; 29 | 30 | }; 31 | 32 | THREE.BufferAttribute.prototype = { 33 | 34 | constructor: THREE.BufferAttribute, 35 | /** 36 | * @desc 获得数组长度 37 | * @returns {number} 38 | */ 39 | get length () { 40 | 41 | return this.array.length; 42 | 43 | }, 44 | /** 45 | * @desc 拷贝数组 46 | * @param {number} index1 目标数组起始索引 47 | * @param {THREE.BufferAttribute} attribute 源数组 48 | * @param {number} index2 源数组起始索引 49 | */ 50 | copyAt: function ( index1, attribute, index2 ) { 51 | 52 | index1 *= this.itemSize; 53 | index2 *= attribute.itemSize; 54 | 55 | for ( var i = 0, l = this.itemSize; i < l; i ++ ) { 56 | 57 | this.array[ index1 + i ] = attribute.array[ index2 + i ]; 58 | 59 | } 60 | 61 | }, 62 | /** 63 | * @desc 重新设置BufferAttribute的属性数组 64 | * @param {THREE.BufferAttribute.array} value 属性数组 65 | * @returns {THREE.BufferAttribute} 66 | */ 67 | set: function ( value ) { 68 | 69 | this.array.set( value ); 70 | 71 | return this; 72 | 73 | }, 74 | /** 75 | * @desc 重新设置含有3个属性相的BufferAttribute属性数组的第一个分量
76 | * setX方法中,属性数组的长度是属性相的长度乘以属性的个数
77 | * 比如要存放100个点的坐标,坐标有3个属性相,那么属性数组的长度是300,如果想改变第30个点的x坐标就将index设为30 78 | * @param {number} index 属性数组的索引 79 | * @param {number} x 属性数组的第一个分量的值 80 | * @returns {THREE.BufferAttribute} 81 | */ 82 | setX: function ( index, x ) { 83 | 84 | this.array[ index * this.itemSize ] = x; 85 | 86 | return this; 87 | 88 | }, 89 | /** 90 | * @desc 重新设置含有3个属性相的BufferAttribute属性数组的第二个分量
91 | * @param {number} index 属性数组的索引 92 | * @param {number} y 属性数组的第二个分量的值 93 | * @returns {THREE.BufferAttribute} 94 | */ 95 | setY: function ( index, y ) { 96 | 97 | this.array[ index * this.itemSize + 1 ] = y; 98 | 99 | return this; 100 | 101 | }, 102 | /** 103 | * @desc 重新设置含有3个属性相的BufferAttribute属性数组的第三个分量
104 | * @param {number} index 属性数组的索引 105 | * @param {number} z 属性数组的第三个分量的值 106 | * @returns {THREE.BufferAttribute} 107 | */ 108 | setZ: function ( index, z ) { 109 | 110 | this.array[ index * this.itemSize + 2 ] = z; 111 | 112 | return this; 113 | 114 | }, 115 | /** 116 | * @desc 重新设置含有3个属性相的BufferAttribute属性数组的第1,2个分量
117 | * @param {number} index 属性数组的索引 118 | * @param {number} x 属性数组的第1个分量的值 119 | * @param {number} y 属性数组的第2个分量的值 120 | * @returns {THREE.BufferAttribute} 121 | */ 122 | setXY: function ( index, x, y ) { 123 | 124 | index *= this.itemSize; 125 | 126 | this.array[ index ] = x; 127 | this.array[ index + 1 ] = y; 128 | 129 | return this; 130 | 131 | }, 132 | /** 133 | * @desc 重新设置含有3个属性相的BufferAttribute属性数组的第1,2,3个分量
134 | * @param {number} index 属性数组的索引 135 | * @param {number} x 属性数组的第1个分量的值 136 | * @param {number} y 属性数组的第2个分量的值 137 | * @param {number} z 属性数组的第3个分量的值 138 | * @returns {THREE.BufferAttribute} 139 | */ 140 | setXYZ: function ( index, x, y, z ) { 141 | 142 | index *= this.itemSize; 143 | 144 | this.array[ index ] = x; 145 | this.array[ index + 1 ] = y; 146 | this.array[ index + 2 ] = z; 147 | 148 | return this; 149 | 150 | }, 151 | /** 152 | * @desc 重新设置含有4个属性相的BufferAttribute属性数组的第1,2,3,4个分量
153 | * @param {number} index 属性数组的索引 154 | * @param {number} x 属性数组的第1个分量的值 155 | * @param {number} y 属性数组的第2个分量的值 156 | * @param {number} z 属性数组的第3个分量的值 157 | * @param {number} w 属性数组的第4个分量的值 158 | * @returns {THREE.BufferAttribute} 159 | */ 160 | setXYZW: function ( index, x, y, z, w ) { 161 | 162 | index *= this.itemSize; 163 | 164 | this.array[ index ] = x; 165 | this.array[ index + 1 ] = y; 166 | this.array[ index + 2 ] = z; 167 | this.array[ index + 3 ] = w; 168 | 169 | return this; 170 | 171 | }, 172 | /** 173 | * @desc 克隆属性对象 174 | * @returns {THREE.BufferAttribute} 175 | */ 176 | clone: function () { 177 | 178 | return new THREE.BufferAttribute( new this.array.constructor( this.array ), this.itemSize ); 179 | 180 | } 181 | 182 | }; 183 | 184 | // 185 | /********************************************************************************** 186 | ****下面这些方法是定义不同数据类型的属性,已经在新版本中删除,这里保留是为了向后兼容. 187 | ***********************************************************************************/ 188 | THREE.Int8Attribute = function ( data, itemSize ) { 189 | 190 | console.warn( 'THREE.Int8Attribute has been removed. Use THREE.BufferAttribute( array, itemSize ) instead.' ); 191 | return new THREE.BufferAttribute( data, itemSize ); 192 | 193 | }; 194 | 195 | THREE.Uint8Attribute = function ( data, itemSize ) { 196 | 197 | console.warn( 'THREE.Uint8Attribute has been removed. Use THREE.BufferAttribute( array, itemSize ) instead.' ); 198 | return new THREE.BufferAttribute( data, itemSize ); 199 | 200 | }; 201 | 202 | THREE.Uint8ClampedAttribute = function ( data, itemSize ) { 203 | 204 | console.warn( 'THREE.Uint8ClampedAttribute has been removed. Use THREE.BufferAttribute( array, itemSize ) instead.' ); 205 | return new THREE.BufferAttribute( data, itemSize ); 206 | 207 | 208 | }; 209 | 210 | THREE.Int16Attribute = function ( data, itemSize ) { 211 | 212 | console.warn( 'THREE.Int16Attribute has been removed. Use THREE.BufferAttribute( array, itemSize ) instead.' ); 213 | return new THREE.BufferAttribute( data, itemSize ); 214 | 215 | }; 216 | 217 | THREE.Uint16Attribute = function ( data, itemSize ) { 218 | 219 | console.warn( 'THREE.Uint16Attribute has been removed. Use THREE.BufferAttribute( array, itemSize ) instead.' ); 220 | return new THREE.BufferAttribute( data, itemSize ); 221 | 222 | }; 223 | 224 | THREE.Int32Attribute = function ( data, itemSize ) { 225 | 226 | console.warn( 'THREE.Int32Attribute has been removed. Use THREE.BufferAttribute( array, itemSize ) instead.' ); 227 | return new THREE.BufferAttribute( data, itemSize ); 228 | 229 | }; 230 | 231 | THREE.Uint32Attribute = function ( data, itemSize ) { 232 | 233 | console.warn( 'THREE.Uint32Attribute has been removed. Use THREE.BufferAttribute( array, itemSize ) instead.' ); 234 | return new THREE.BufferAttribute( data, itemSize ); 235 | 236 | }; 237 | 238 | THREE.Float32Attribute = function ( data, itemSize ) { 239 | 240 | console.warn( 'THREE.Float32Attribute has been removed. Use THREE.BufferAttribute( array, itemSize ) instead.' ); 241 | return new THREE.BufferAttribute( data, itemSize ); 242 | 243 | }; 244 | 245 | THREE.Float64Attribute = function ( data, itemSize ) { 246 | 247 | console.warn( 'THREE.Float64Attribute has been removed. Use THREE.BufferAttribute( array, itemSize ) instead.' ); 248 | return new THREE.BufferAttribute( data, itemSize ); 249 | 250 | }; 251 | -------------------------------------------------------------------------------- /extras/ImageUtils.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author alteredq / http://alteredqualia.com/ 3 | * @author mrdoob / http://mrdoob.com/ 4 | * @author Daosheng Mu / https://github.com/DaoshengMu/ 5 | */ 6 | /** 7 | * @classdesc 图片对象工具集
8 | * 注释内容部分参照 http://blog.csdn.net/omni360 9 | * @constructor 10 | */ 11 | THREE.ImageUtils = { 12 | /** 13 | * @desc 跨域加载 14 | */ 15 | crossOrigin: undefined, 16 | /** 17 | * @desc 加载纹理 18 | * @param {string} url 图片url 19 | * @param {number} mapping 图片映射方式 20 | * @param {*} onLoad 加载回调函数 21 | * @param {*} onError 错误回调函数 22 | * @returns {THREE.Texture} 23 | */ 24 | loadTexture: function ( url, mapping, onLoad, onError ) { 25 | // 图片加载器 26 | var loader = new THREE.ImageLoader(); 27 | loader.crossOrigin = this.crossOrigin; 28 | 29 | // 创建纹理 30 | var texture = new THREE.Texture( undefined, mapping ); 31 | 32 | // 加载图片 33 | loader.load( url, function ( image ) { 34 | 35 | texture.image = image; 36 | texture.needsUpdate = true; 37 | // 完成回调 38 | if ( onLoad ) onLoad( texture ); 39 | 40 | }, undefined, function ( event ) { 41 | // 错误回调 42 | if ( onError ) onError( event ); 43 | 44 | } ); 45 | // 图片源路径 46 | texture.sourceFile = url; 47 | 48 | return texture; 49 | 50 | }, 51 | /** 52 | * @desc 加载立方体纹理 53 | * @param {string[]} array 图片url 54 | * @param {number} mapping 图片映射方式 55 | * @param {*} onLoad 加载回调函数 56 | * @param {*} onError 错误回调函数 57 | * @returns {THREE.CubeTexture} 58 | */ 59 | loadTextureCube: function ( array, mapping, onLoad, onError ) { 60 | 61 | var images = []; 62 | 63 | var loader = new THREE.ImageLoader(); 64 | loader.crossOrigin = this.crossOrigin; 65 | 66 | var texture = new THREE.CubeTexture( images, mapping ); 67 | 68 | // no flipping needed for cube textures 69 | 70 | texture.flipY = false; 71 | 72 | var loaded = 0; 73 | 74 | var loadTexture = function ( i ) { 75 | 76 | loader.load( array[ i ], function ( image ) { 77 | 78 | texture.images[ i ] = image; 79 | 80 | loaded += 1; 81 | 82 | if ( loaded === 6 ) { 83 | 84 | texture.needsUpdate = true; 85 | 86 | if ( onLoad ) onLoad( texture ); 87 | 88 | } 89 | 90 | } ); 91 | 92 | } 93 | 94 | for ( var i = 0, il = array.length; i < il; ++ i ) { 95 | 96 | loadTexture( i ); 97 | 98 | } 99 | 100 | return texture; 101 | 102 | }, 103 | /** 104 | * @ignore 105 | */ 106 | loadCompressedTexture: function () { 107 | 108 | console.error( 'THREE.ImageUtils.loadCompressedTexture has been removed. Use THREE.DDSLoader instead.' ) 109 | 110 | }, 111 | /** 112 | * @ignore 113 | */ 114 | loadCompressedTextureCube: function () { 115 | 116 | console.error( 'THREE.ImageUtils.loadCompressedTextureCube has been removed. Use THREE.DDSLoader instead.' ) 117 | 118 | }, 119 | /** 120 | * @desc 通过参数image(图像对象),参数(深度信息),获得法线贴图 121 | * @param {Image} image 图片对象 122 | * @param {float} depth 深度信息 [0 ,1] 123 | * @returns {THREE.Texture} 124 | */ 125 | getNormalMap: function ( image, depth ) { 126 | 127 | // Adapted from http://www.paulbrunt.co.uk/lab/heightnormal/ 128 | 129 | var cross = function ( a, b ) { 130 | 131 | return [ a[ 1 ] * b[ 2 ] - a[ 2 ] * b[ 1 ], a[ 2 ] * b[ 0 ] - a[ 0 ] * b[ 2 ], a[ 0 ] * b[ 1 ] - a[ 1 ] * b[ 0 ] ]; 132 | 133 | } 134 | 135 | var subtract = function ( a, b ) { 136 | 137 | return [ a[ 0 ] - b[ 0 ], a[ 1 ] - b[ 1 ], a[ 2 ] - b[ 2 ] ]; 138 | 139 | } 140 | 141 | var normalize = function ( a ) { 142 | 143 | var l = Math.sqrt( a[ 0 ] * a[ 0 ] + a[ 1 ] * a[ 1 ] + a[ 2 ] * a[ 2 ] ); 144 | return [ a[ 0 ] / l, a[ 1 ] / l, a[ 2 ] / l ]; 145 | 146 | } 147 | 148 | depth = depth | 1; 149 | 150 | var width = image.width; 151 | var height = image.height; 152 | 153 | var canvas = document.createElement( 'canvas' ); 154 | canvas.width = width; 155 | canvas.height = height; 156 | 157 | var context = canvas.getContext( '2d' ); 158 | context.drawImage( image, 0, 0 ); 159 | 160 | var data = context.getImageData( 0, 0, width, height ).data; 161 | var imageData = context.createImageData( width, height ); 162 | var output = imageData.data; 163 | 164 | for ( var x = 0; x < width; x ++ ) { 165 | 166 | for ( var y = 0; y < height; y ++ ) { 167 | 168 | var ly = y - 1 < 0 ? 0 : y - 1; 169 | var uy = y + 1 > height - 1 ? height - 1 : y + 1; 170 | var lx = x - 1 < 0 ? 0 : x - 1; 171 | var ux = x + 1 > width - 1 ? width - 1 : x + 1; 172 | 173 | var points = []; 174 | var origin = [ 0, 0, data[ ( y * width + x ) * 4 ] / 255 * depth ]; 175 | points.push( [ - 1, 0, data[ ( y * width + lx ) * 4 ] / 255 * depth ] ); 176 | points.push( [ - 1, - 1, data[ ( ly * width + lx ) * 4 ] / 255 * depth ] ); 177 | points.push( [ 0, - 1, data[ ( ly * width + x ) * 4 ] / 255 * depth ] ); 178 | points.push( [ 1, - 1, data[ ( ly * width + ux ) * 4 ] / 255 * depth ] ); 179 | points.push( [ 1, 0, data[ ( y * width + ux ) * 4 ] / 255 * depth ] ); 180 | points.push( [ 1, 1, data[ ( uy * width + ux ) * 4 ] / 255 * depth ] ); 181 | points.push( [ 0, 1, data[ ( uy * width + x ) * 4 ] / 255 * depth ] ); 182 | points.push( [ - 1, 1, data[ ( uy * width + lx ) * 4 ] / 255 * depth ] ); 183 | 184 | var normals = []; 185 | var num_points = points.length; 186 | 187 | for ( var i = 0; i < num_points; i ++ ) { 188 | 189 | var v1 = points[ i ]; 190 | var v2 = points[ ( i + 1 ) % num_points ]; 191 | v1 = subtract( v1, origin ); 192 | v2 = subtract( v2, origin ); 193 | normals.push( normalize( cross( v1, v2 ) ) ); 194 | 195 | } 196 | 197 | var normal = [ 0, 0, 0 ]; 198 | 199 | for ( var i = 0; i < normals.length; i ++ ) { 200 | 201 | normal[ 0 ] += normals[ i ][ 0 ]; 202 | normal[ 1 ] += normals[ i ][ 1 ]; 203 | normal[ 2 ] += normals[ i ][ 2 ]; 204 | 205 | } 206 | 207 | normal[ 0 ] /= normals.length; 208 | normal[ 1 ] /= normals.length; 209 | normal[ 2 ] /= normals.length; 210 | 211 | var idx = ( y * width + x ) * 4; 212 | 213 | output[ idx ] = ( ( normal[ 0 ] + 1.0 ) / 2.0 * 255 ) | 0; 214 | output[ idx + 1 ] = ( ( normal[ 1 ] + 1.0 ) / 2.0 * 255 ) | 0; 215 | output[ idx + 2 ] = ( normal[ 2 ] * 255 ) | 0; 216 | output[ idx + 3 ] = 255; 217 | 218 | } 219 | 220 | } 221 | 222 | context.putImageData( imageData, 0, 0 ); 223 | 224 | return canvas; 225 | 226 | }, 227 | /** 228 | * @desc 生成DataTexture对象使用的图像数据 229 | * @param {number} width 宽度 230 | * @param {number} height 高度 231 | * @param {THREE.Color} color 颜色 232 | * @returns {THREE.DataTexture} 233 | */ 234 | generateDataTexture: function ( width, height, color ) { 235 | 236 | var size = width * height; 237 | var data = new Uint8Array( 3 * size ); 238 | 239 | var r = Math.floor( color.r * 255 ); 240 | var g = Math.floor( color.g * 255 ); 241 | var b = Math.floor( color.b * 255 ); 242 | 243 | for ( var i = 0; i < size; i ++ ) { 244 | 245 | data[ i * 3 ] = r; 246 | data[ i * 3 + 1 ] = g; 247 | data[ i * 3 + 2 ] = b; 248 | 249 | } 250 | 251 | var texture = new THREE.DataTexture( data, width, height, THREE.RGBFormat ); 252 | texture.needsUpdate = true; 253 | 254 | return texture; 255 | 256 | } 257 | 258 | }; 259 | -------------------------------------------------------------------------------- /math/Triangle.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author bhouston / http://exocortex.com 3 | * @author mrdoob / http://mrdoob.com/ 4 | */ 5 | /** 6 | * @classdesc 三角形类
7 | * 注释内容部分参照 http://blog.csdn.net/omni360 8 | * @desc 由a,b,c三个向量组成的三角形 9 | * @param {THREE.Vector3} a 10 | * @param {THREE.Vector3} b 11 | * @param {THREE.Vector3} c 12 | * @constructor 13 | */ 14 | THREE.Triangle = function ( a, b, c ) { 15 | /** 16 | * 17 | * @type {THREE.Vector3} 18 | */ 19 | this.a = ( a !== undefined ) ? a : new THREE.Vector3(); 20 | /** 21 | * 22 | * @type {THREE.Vector3} 23 | */ 24 | this.b = ( b !== undefined ) ? b : new THREE.Vector3(); 25 | /** 26 | * 27 | * @type {THREE.Vector3} 28 | */ 29 | this.c = ( c !== undefined ) ? c : new THREE.Vector3(); 30 | 31 | }; 32 | /** 33 | * @function 34 | * @desc 计算三角形的法线向量 35 | * @param {THREE.Vector3} a 36 | * @param {THREE.Vector3} b 37 | * @param {THREE.Vector3} c 38 | * @param {THREE.Vector3} optionalTarget 39 | * @return {THREE.Vector3} 40 | */ 41 | THREE.Triangle.normal = function () { 42 | 43 | var v0 = new THREE.Vector3(); 44 | 45 | return function ( a, b, c, optionalTarget ) { 46 | 47 | var result = optionalTarget || new THREE.Vector3(); 48 | 49 | result.subVectors( c, b ); 50 | v0.subVectors( a, b ); 51 | result.cross( v0 ); 52 | 53 | var resultLengthSq = result.lengthSq(); 54 | if ( resultLengthSq > 0 ) { 55 | 56 | return result.multiplyScalar( 1 / Math.sqrt( resultLengthSq ) ); 57 | 58 | } 59 | 60 | return result.set( 0, 0, 0 ); 61 | 62 | }; 63 | 64 | }(); 65 | 66 | // static/instance method to calculate barycoordinates 67 | // based on: http://www.blackpawn.com/texts/pointinpoly/default.html 68 | /** 69 | * @function 70 | * @desc 算返回参数a,b,c所组成的三角形所在的平面上任意点(参数point)所表示三角形顶点的加权平均值
71 | * 这个权值就是重心坐标 72 | * @param {THREE.Vector3} point 三角平面上任意点 73 | * @param {THREE.Vector3} a 74 | * @param {THREE.Vector3} b 75 | * @param {THREE.Vector3} c 76 | * @param {THREE.Vector3} optionalTarget 77 | */ 78 | THREE.Triangle.barycoordFromPoint = function () { 79 | 80 | var v0 = new THREE.Vector3(); 81 | var v1 = new THREE.Vector3(); 82 | var v2 = new THREE.Vector3(); 83 | 84 | return function ( point, a, b, c, optionalTarget ) { 85 | 86 | v0.subVectors( c, a ); 87 | v1.subVectors( b, a ); 88 | v2.subVectors( point, a ); 89 | 90 | var dot00 = v0.dot( v0 ); 91 | var dot01 = v0.dot( v1 ); 92 | var dot02 = v0.dot( v2 ); 93 | var dot11 = v1.dot( v1 ); 94 | var dot12 = v1.dot( v2 ); 95 | 96 | var denom = ( dot00 * dot11 - dot01 * dot01 ); 97 | 98 | var result = optionalTarget || new THREE.Vector3(); 99 | 100 | // colinear or singular triangle 101 | if ( denom == 0 ) { 102 | // arbitrary location outside of triangle? 103 | // not sure if this is the best idea, maybe should be returning undefined 104 | return result.set( - 2, - 1, - 1 ); 105 | } 106 | 107 | var invDenom = 1 / denom; 108 | var u = ( dot11 * dot02 - dot01 * dot12 ) * invDenom; 109 | var v = ( dot00 * dot12 - dot01 * dot02 ) * invDenom; 110 | 111 | // barycoordinates must always sum to 1 112 | return result.set( 1 - u - v, v, u ); 113 | 114 | }; 115 | 116 | }(); 117 | 118 | /** 119 | * @function 120 | * @desc 判断任意点(参数point)是否在a,b,c所组成的三角形内 121 | * @param {THREE.Vector3} point 三角平面上任意点 122 | * @param {THREE.Vector3} a 123 | * @param {THREE.Vector3} b 124 | * @param {THREE.Vector3} c 125 | * @return {boolean} 126 | */ 127 | THREE.Triangle.containsPoint = function () { 128 | 129 | var v1 = new THREE.Vector3(); 130 | 131 | return function ( point, a, b, c ) { 132 | 133 | var result = THREE.Triangle.barycoordFromPoint( point, a, b, c, v1 ); 134 | 135 | return ( result.x >= 0 ) && ( result.y >= 0 ) && ( ( result.x + result.y ) <= 1 ); 136 | 137 | }; 138 | 139 | }(); 140 | 141 | THREE.Triangle.prototype = { 142 | 143 | constructor: THREE.Triangle, 144 | /** 145 | * @desc 设置三角平面 146 | * @param {THREE.Vector3} a 147 | * @param {THREE.Vector3} b 148 | * @param {THREE.Vector3} c 149 | * @returns {THREE.Triangle} 150 | */ 151 | set: function ( a, b, c ) { 152 | 153 | this.a.copy( a ); 154 | this.b.copy( b ); 155 | this.c.copy( c ); 156 | 157 | return this; 158 | 159 | }, 160 | 161 | /** 162 | * @desc 通过数组和索引设置三角平面 163 | * @param {THREE.Vector3[]} points 164 | * @param {float} i0 165 | * @param {float} i1 166 | * @param {float} i2 167 | * @returns {THREE.Triangle} 168 | */ 169 | setFromPointsAndIndices: function ( points, i0, i1, i2 ) { 170 | 171 | this.a.copy( points[ i0 ] ); 172 | this.b.copy( points[ i1 ] ); 173 | this.c.copy( points[ i2 ] ); 174 | 175 | return this; 176 | 177 | }, 178 | 179 | /** 180 | * @desc 拷贝三角平面 181 | * @param {THREE.Triangle} triangle 182 | * @returns {THREE.Triangle} 183 | */ 184 | copy: function ( triangle ) { 185 | 186 | this.a.copy( triangle.a ); 187 | this.b.copy( triangle.b ); 188 | this.c.copy( triangle.c ); 189 | 190 | return this; 191 | 192 | }, 193 | 194 | /** 195 | * @function 196 | * @desc 计算三角形面他积 197 | * @return {float} 198 | */ 199 | area: function () { 200 | 201 | var v0 = new THREE.Vector3(); 202 | var v1 = new THREE.Vector3(); 203 | 204 | return function () { 205 | 206 | v0.subVectors( this.c, this.b ); 207 | v1.subVectors( this.a, this.b ); 208 | 209 | return v0.cross( v1 ).length() * 0.5; 210 | 211 | }; 212 | 213 | }(), 214 | 215 | /** 216 | * @desc 计算三角形中心 217 | * @param {THREE.Vector3} optionalTarget 218 | * @returns {THREE.Vector3} 219 | */ 220 | midpoint: function ( optionalTarget ) { 221 | 222 | var result = optionalTarget || new THREE.Vector3(); 223 | return result.addVectors( this.a, this.b ).add( this.c ).multiplyScalar( 1 / 3 ); 224 | 225 | }, 226 | 227 | /** 228 | * @desc 计算三角形的法向量 229 | * @param {THREE.Vector3} optionalTarget 230 | * @returns {THREE.Vector3} 231 | */ 232 | normal: function ( optionalTarget ) { 233 | 234 | return THREE.Triangle.normal( this.a, this.b, this.c, optionalTarget ); 235 | 236 | }, 237 | /** 238 | * @desc 创建三角形共面的平面Plane对象 239 | * @param {THREE.Plane} optionalTarget 240 | * @returns {THREE.Plane} 241 | */ 242 | plane: function ( optionalTarget ) { 243 | 244 | var result = optionalTarget || new THREE.Plane(); 245 | 246 | return result.setFromCoplanarPoints( this.a, this.b, this.c ); 247 | 248 | }, 249 | 250 | /** 251 | * @desc 计算返回当前三角形所在的平面上任意点(参数point)所表示当前三角形顶点的加权平均值
252 | * 这个权值就是重心坐标 253 | * @param {THREE.Vector3} point 254 | * @param {THREE.Vector3} optionalTarget 255 | * @returns {THREE.Vector3} 256 | */ 257 | barycoordFromPoint: function ( point, optionalTarget ) { 258 | 259 | return THREE.Triangle.barycoordFromPoint( point, this.a, this.b, this.c, optionalTarget ); 260 | 261 | }, 262 | 263 | /** 264 | * @desc 计算点是否在三角形内 265 | * @param {THREE.Vector3} point 266 | * @returns {boolean} 267 | */ 268 | containsPoint: function ( point ) { 269 | 270 | return THREE.Triangle.containsPoint( point, this.a, this.b, this.c ); 271 | 272 | }, 273 | 274 | /** 275 | * @desc 计算三角形是否相等 276 | * @param {THREE.Triangle} triangle 277 | * @returns {boolean} 278 | */ 279 | equals: function ( triangle ) { 280 | 281 | return triangle.a.equals( this.a ) && triangle.b.equals( this.b ) && triangle.c.equals( this.c ); 282 | 283 | }, 284 | 285 | /** 286 | * @desc 克隆三角形 287 | * @returns {THREE.Triangle} 288 | */ 289 | clone: function () { 290 | 291 | return new THREE.Triangle().copy( this ); 292 | 293 | } 294 | 295 | }; 296 | -------------------------------------------------------------------------------- /objects/MorphAnimMesh.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author alteredq / http://alteredqualia.com/ 3 | */ 4 | /** 5 | * @classdesc 变形动画网格对象
6 | * 注释内容部分参照 http://blog.csdn.net/omni360 7 | * @desc 这个对象是专门针对变形动画的,增加了许多角色变形动画的内容 8 | * @param {THREE.Geometry} geometry 几何对象 9 | * @param {THREE.Material} material 材质对象 10 | * @constructor 11 | */ 12 | THREE.MorphAnimMesh = function ( geometry, material ) { 13 | 14 | THREE.Mesh.call( this, geometry, material ); 15 | 16 | this.type = 'MorphAnimMesh'; 17 | 18 | // API 19 | /** 20 | * @desc 周期,单位毫秒,默认初始化为1000毫秒,每帧间隔时长 21 | * @default 22 | * @type {number} 23 | */ 24 | this.duration = 1000; // milliseconds 25 | /** 26 | * @desc 镜像循环,看下面的算法,应该是播放完后,回放动画 27 | * @default 28 | * @type {boolean} 29 | */ 30 | this.mirroredLoop = false; 31 | /** 32 | * @desc 动画时长 33 | * @default 34 | * @type {number} 35 | */ 36 | this.time = 0; 37 | 38 | // internals 39 | /** 40 | * @desc 最后关键帧 41 | * @default 42 | * @type {number} 43 | */ 44 | this.lastKeyframe = 0; 45 | /** 46 | * @desc 当前关键帧 47 | * @default 48 | * @type {number} 49 | */ 50 | this.currentKeyframe = 0; 51 | /** 52 | * @desc 方向,应该指的是时间轴的方向 53 | * @default 54 | * @type {number} 55 | */ 56 | this.direction = 1; 57 | /** 58 | * @desc 时间轴是否是返方向,默认为false 59 | * @default 60 | * @type {boolean} 61 | */ 62 | this.directionBackwards = false; 63 | // 创建关键帧动画时间轴,从morphTargets数组创建. 64 | this.setFrameRange( 0, this.geometry.morphTargets.length - 1 ); 65 | 66 | }; 67 | /** 68 | * @desc MorphAnimMesh从Mesh的原型继承所有属性方法 69 | * @type {THREE.Mesh} 70 | */ 71 | THREE.MorphAnimMesh.prototype = Object.create( THREE.Mesh.prototype ); 72 | /** 73 | * @desc 创建关键帧动画时间轴,从morphTargets数组创建 74 | * @param {number} start 开始帧 75 | * @param {number} end 结束帧 76 | */ 77 | THREE.MorphAnimMesh.prototype.setFrameRange = function ( start, end ) { 78 | /** 79 | * @memberof THREE.MorphAnimMesh 80 | * @desc 开始帧 81 | * @type {number} 82 | */ 83 | this.startKeyframe = start; 84 | /** 85 | * @memberof THREE.MorphAnimMesh 86 | * @desc 结束帧 87 | * @type {number} 88 | */ 89 | this.endKeyframe = end; 90 | /** 91 | * @memberof THREE.MorphAnimMesh 92 | * @desc 动画长度 93 | * @type {number} 94 | */ 95 | this.length = this.endKeyframe - this.startKeyframe + 1; 96 | 97 | }; 98 | /** 99 | * @desc 设置关键帧动画正放 100 | */ 101 | THREE.MorphAnimMesh.prototype.setDirectionForward = function () { 102 | 103 | this.direction = 1; 104 | this.directionBackwards = false; 105 | 106 | }; 107 | /** 108 | * @desc 设置关键帧动画倒放 109 | */ 110 | THREE.MorphAnimMesh.prototype.setDirectionBackward = function () { 111 | 112 | this.direction = - 1; 113 | this.directionBackwards = true; 114 | 115 | }; 116 | /** 117 | * @desc 从morphTagets数组中解析关键帧动画 118 | */ 119 | THREE.MorphAnimMesh.prototype.parseAnimations = function () { 120 | 121 | var geometry = this.geometry; 122 | 123 | if ( ! geometry.animations ) geometry.animations = {}; 124 | 125 | var firstAnimation, animations = geometry.animations; 126 | 127 | var pattern = /([a-z]+)_?(\d+)/; 128 | 129 | for ( var i = 0, il = geometry.morphTargets.length; i < il; i ++ ) { 130 | // 获得单个变形动画关键帧 131 | var morph = geometry.morphTargets[ i ]; 132 | var parts = morph.name.match( pattern ); 133 | 134 | if ( parts && parts.length > 1 ) { 135 | 136 | var label = parts[ 1 ]; 137 | var num = parts[ 2 ]; 138 | 139 | if ( ! animations[ label ] ) animations[ label ] = { start: Infinity, end: - Infinity }; 140 | 141 | var animation = animations[ label ]; 142 | 143 | if ( i < animation.start ) animation.start = i; 144 | if ( i > animation.end ) animation.end = i; 145 | 146 | if ( ! firstAnimation ) firstAnimation = label; 147 | 148 | } 149 | 150 | } 151 | // 设置第一个动画. 152 | geometry.firstAnimation = firstAnimation; 153 | 154 | }; 155 | /** 156 | * @desc 从morphTagets数组中设置关键帧动画标签,可以将morphTargets数组中,分成几段动画,分别存放. 157 | * @param {string} label 动画名称 158 | * @param {number} start morphTargets开始索引 159 | * @param {number} end morphTargets结束索引 160 | */ 161 | THREE.MorphAnimMesh.prototype.setAnimationLabel = function ( label, start, end ) { 162 | 163 | if ( ! this.geometry.animations ) this.geometry.animations = {}; 164 | 165 | this.geometry.animations[ label ] = { start: start, end: end }; 166 | 167 | }; 168 | /** 169 | * @desc 根据动画的标签名(参数lab)按照指定的速度(参数fps)播放动画 170 | * @param {string} label 动画名称 171 | * @param {number} fps 帧率 172 | */ 173 | THREE.MorphAnimMesh.prototype.playAnimation = function ( label, fps ) { 174 | 175 | var animation = this.geometry.animations[ label ]; 176 | 177 | if ( animation ) { 178 | 179 | this.setFrameRange( animation.start, animation.end ); 180 | this.duration = 1000 * ( ( animation.end - animation.start ) / fps ); 181 | this.time = 0; 182 | 183 | } else { 184 | 185 | console.warn( 'animation[' + label + '] undefined' ); 186 | 187 | } 188 | 189 | }; 190 | /** 191 | * @desc 根据当前时钟频率生成补间动画 192 | * @param {number} delta 时钟频率 193 | */ 194 | THREE.MorphAnimMesh.prototype.updateAnimation = function ( delta ) { 195 | 196 | var frameTime = this.duration / this.length; 197 | 198 | this.time += this.direction * delta; 199 | 200 | if ( this.mirroredLoop ) { 201 | 202 | if ( this.time > this.duration || this.time < 0 ) { 203 | 204 | this.direction *= - 1; 205 | 206 | if ( this.time > this.duration ) { 207 | 208 | this.time = this.duration; 209 | this.directionBackwards = true; 210 | 211 | } 212 | 213 | if ( this.time < 0 ) { 214 | 215 | this.time = 0; 216 | this.directionBackwards = false; 217 | 218 | } 219 | 220 | } 221 | 222 | } else { 223 | 224 | this.time = this.time % this.duration; 225 | 226 | if ( this.time < 0 ) this.time += this.duration; 227 | 228 | } 229 | 230 | var keyframe = this.startKeyframe + THREE.Math.clamp( Math.floor( this.time / frameTime ), 0, this.length - 1 ); 231 | 232 | if ( keyframe !== this.currentKeyframe ) { 233 | 234 | this.morphTargetInfluences[ this.lastKeyframe ] = 0; 235 | this.morphTargetInfluences[ this.currentKeyframe ] = 1; 236 | 237 | this.morphTargetInfluences[ keyframe ] = 0; 238 | 239 | this.lastKeyframe = this.currentKeyframe; 240 | this.currentKeyframe = keyframe; 241 | 242 | } 243 | 244 | var mix = ( this.time % frameTime ) / frameTime; 245 | 246 | if ( this.directionBackwards ) { 247 | 248 | mix = 1 - mix; 249 | 250 | } 251 | 252 | this.morphTargetInfluences[ this.currentKeyframe ] = mix; 253 | this.morphTargetInfluences[ this.lastKeyframe ] = 1 - mix; 254 | 255 | }; 256 | /** 257 | * @desc 根据变形幅度t将morphTaInfluences[a]设置为1-t,morphTaInfluences[b]设置为t. 258 | * @param {number} a 节点a 259 | * @param {number} b 节点b 260 | * @param {float} t 变形幅度 261 | */ 262 | THREE.MorphAnimMesh.prototype.interpolateTargets = function ( a, b, t ) { 263 | 264 | var influences = this.morphTargetInfluences; 265 | 266 | for ( var i = 0, l = influences.length; i < l; i ++ ) { 267 | 268 | influences[ i ] = 0; 269 | 270 | } 271 | 272 | if ( a > -1 ) influences[ a ] = 1 - t; 273 | if ( b > -1 ) influences[ b ] = t; 274 | 275 | }; 276 | /** 277 | * @desc Three.MorphAnimMesh 克隆函数 278 | * @param {THREE.MorphAnimMesh} object 279 | * @returns {THREE.MorphAnimMesh} 280 | */ 281 | THREE.MorphAnimMesh.prototype.clone = function ( object ) { 282 | 283 | if ( object === undefined ) object = new THREE.MorphAnimMesh( this.geometry, this.material ); 284 | 285 | object.duration = this.duration; 286 | object.mirroredLoop = this.mirroredLoop; 287 | object.time = this.time; 288 | 289 | object.lastKeyframe = this.lastKeyframe; 290 | object.currentKeyframe = this.currentKeyframe; 291 | 292 | object.direction = this.direction; 293 | object.directionBackwards = this.directionBackwards; 294 | 295 | THREE.Mesh.prototype.clone.call( this, object ); 296 | 297 | return object; 298 | 299 | }; 300 | -------------------------------------------------------------------------------- /math/Box2.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author bhouston / http://exocortex.com 3 | */ 4 | /** 5 | * @classdesc 2维矩形类
6 | * 注释内容部分参照 http://blog.csdn.net/omni360 7 | * @param {THREE.Vector2} min 未定义则为无穷大 8 | * @param {THREE.Vector2} max 未定义则为无穷小 9 | * @constructor 10 | */ 11 | THREE.Box2 = function ( min, max ) { 12 | /** 13 | * @desc 最小值 14 | * @default ( Infinity, Infinity ) 15 | * @type {THREE.Vector2} 16 | */ 17 | this.min = ( min !== undefined ) ? min : new THREE.Vector2( Infinity, Infinity ); 18 | /** 19 | * @desc 最大值 20 | * @default ( - Infinity, - Infinity ) 21 | * @type {THREE.Vector2} 22 | */ 23 | this.max = ( max !== undefined ) ? max : new THREE.Vector2( - Infinity, - Infinity ); 24 | 25 | }; 26 | 27 | THREE.Box2.prototype = { 28 | 29 | constructor: THREE.Box2, 30 | /** 31 | * @desc 设置2维矩形 32 | * @param {THREE.Vector2} min 33 | * @param {THREE.Vector2} max 34 | * @returns {THREE.Box2} 35 | */ 36 | set: function ( min, max ) { 37 | 38 | this.min.copy( min ); 39 | this.max.copy( max ); 40 | 41 | return this; 42 | 43 | }, 44 | /** 45 | * @desc 2维坐标数组的外包围盒 46 | * @param {THREE.Vector2[]}points 47 | * @returns {THREE.Box2} 48 | */ 49 | setFromPoints: function ( points ) { 50 | 51 | this.makeEmpty(); 52 | 53 | for ( var i = 0, il = points.length; i < il; i ++ ) { 54 | 55 | this.expandByPoint( points[ i ] ) 56 | 57 | } 58 | 59 | return this; 60 | 61 | }, 62 | /** 63 | * @function 64 | * @desc 由中心点和边长设置2维矩形 65 | * @param {THREE.Vector2} center 中心点 66 | * @param {float} size 边长 67 | * @returns {THREE.Box2} 68 | */ 69 | setFromCenterAndSize: function () { 70 | 71 | var v1 = new THREE.Vector2(); 72 | 73 | return function ( center, size ) { 74 | 75 | var halfSize = v1.copy( size ).multiplyScalar( 0.5 ); 76 | this.min.copy( center ).sub( halfSize ); 77 | this.max.copy( center ).add( halfSize ); 78 | 79 | return this; 80 | 81 | }; 82 | 83 | }(), 84 | /** 85 | * @desc 拷贝2维矩形 86 | * @param {THREE.Box2} box 87 | * @returns {THREE.Box2} 88 | */ 89 | copy: function ( box ) { 90 | 91 | this.min.copy( box.min ); 92 | this.max.copy( box.max ); 93 | 94 | return this; 95 | 96 | }, 97 | /** 98 | * @desc 设置无效2维矩形 99 | * @returns {THREE.Box2} 100 | */ 101 | makeEmpty: function () { 102 | 103 | this.min.x = this.min.y = Infinity; 104 | this.max.x = this.max.y = - Infinity; 105 | 106 | return this; 107 | 108 | }, 109 | /** 110 | * @desc 是否是无效2维矩形 111 | * @returns {boolean} 112 | */ 113 | empty: function () { 114 | 115 | // this is a more robust check for empty than ( volume <= 0 ) because volume can get positive with two negative axes 116 | 117 | return ( this.max.x < this.min.x ) || ( this.max.y < this.min.y ); 118 | 119 | }, 120 | /** 121 | * @desc 获得2维矩形中心点 122 | * @param {THREE.Vector2} optionalTarget 123 | * @returns {THREE.Vector2} 124 | */ 125 | center: function ( optionalTarget ) { 126 | 127 | var result = optionalTarget || new THREE.Vector2(); 128 | return result.addVectors( this.min, this.max ).multiplyScalar( 0.5 ); 129 | 130 | }, 131 | /** 132 | * @desc 获得2维矩形边界尺寸向量 133 | * @param {THREE.Vector2} optionalTarget 134 | * @returns {THREE.Vector2} 135 | */ 136 | size: function ( optionalTarget ) { 137 | 138 | var result = optionalTarget || new THREE.Vector2(); 139 | return result.subVectors( this.max, this.min ); 140 | 141 | }, 142 | /** 143 | * @desc 通过vector2对象(point参数)扩展二维矩形边界的最小值,最大值 144 | * @param {THREE.Vector2} point 145 | * @returns {THREE.Box2} 146 | */ 147 | expandByPoint: function ( point ) { 148 | 149 | this.min.min( point ); 150 | this.max.max( point ); 151 | 152 | return this; 153 | }, 154 | /** 155 | * @desc 通过Vector2对象(vector参数)扩展二维矩形边界的最小值,最大值 156 | * @param {THREE.Vector2} vector 157 | * @returns {THREE.Box2} 158 | */ 159 | expandByVector: function ( vector ) { 160 | 161 | this.min.sub( vector ); 162 | this.max.add( vector ); 163 | 164 | return this; 165 | }, 166 | /** 167 | * @desc 通过scalar值(scalar参数)扩展二维矩形边界的最小值,最大值 168 | * @param {float} scalar 169 | * @returns {THREE.Box2} 170 | */ 171 | expandByScalar: function ( scalar ) { 172 | 173 | this.min.addScalar( - scalar ); 174 | this.max.addScalar( scalar ); 175 | 176 | return this; 177 | }, 178 | /** 179 | * @desc 判断点是否在2维矩形内 180 | * @param {THREE.Vector2} point 181 | * @returns {boolean} 182 | */ 183 | containsPoint: function ( point ) { 184 | 185 | if ( point.x < this.min.x || point.x > this.max.x || 186 | point.y < this.min.y || point.y > this.max.y ) { 187 | 188 | return false; 189 | 190 | } 191 | 192 | return true; 193 | 194 | }, 195 | /** 196 | * @desc 判断box是否在当前2维矩形内 197 | * @param {THREE.Box2} box 198 | * @returns {boolean} 199 | */ 200 | containsBox: function ( box ) { 201 | 202 | if ( ( this.min.x <= box.min.x ) && ( box.max.x <= this.max.x ) && 203 | ( this.min.y <= box.min.y ) && ( box.max.y <= this.max.y ) ) { 204 | 205 | return true; 206 | 207 | } 208 | 209 | return false; 210 | 211 | }, 212 | /** 213 | * @desc 获得参数point(一个Vector2的二维点坐标)在当前二维矩形边界的高宽比 214 | * @param {THREE.Vector2} point 215 | * @param {THREE.Vector2} optionalTarget 216 | * @returns {THREE.Vector2} 217 | */ 218 | getParameter: function ( point, optionalTarget ) { 219 | 220 | // This can potentially have a divide by zero if the box 221 | // has a size dimension of 0. 222 | 223 | var result = optionalTarget || new THREE.Vector2(); 224 | 225 | return result.set( 226 | ( point.x - this.min.x ) / ( this.max.x - this.min.x ), 227 | ( point.y - this.min.y ) / ( this.max.y - this.min.y ) 228 | ); 229 | 230 | }, 231 | /** 232 | * @desc 判断box是否和当前2维矩形相交 233 | * @param {THREE.Box2} box 234 | * @returns {boolean} 235 | */ 236 | isIntersectionBox: function ( box ) { 237 | 238 | // using 6 splitting planes to rule out intersections. 239 | 240 | if ( box.max.x < this.min.x || box.min.x > this.max.x || 241 | box.max.y < this.min.y || box.min.y > this.max.y ) { 242 | 243 | return false; 244 | 245 | } 246 | 247 | return true; 248 | 249 | }, 250 | /** 251 | * @desc 限制参数point在二维矩形边界内.如果point小于min,返回min,如果大于max返回max,否则返回point 252 | * @param {THREE.Vector2} point 253 | * @param {THREE.Vector2} optionalTarget 254 | * @returns {THREE.Vector2} 255 | */ 256 | clampPoint: function ( point, optionalTarget ) { 257 | 258 | var result = optionalTarget || new THREE.Vector2(); 259 | return result.copy( point ).clamp( this.min, this.max ); 260 | 261 | }, 262 | /** 263 | * @function 264 | * @desc 边界内一点到最小边界,最大边界的长度 265 | * @param {THREE.Vector2} point 266 | * @return {THREE.Vector2} 267 | */ 268 | distanceToPoint: function () { 269 | 270 | var v1 = new THREE.Vector2(); 271 | 272 | return function ( point ) { 273 | 274 | var clampedPoint = v1.copy( point ).clamp( this.min, this.max ); 275 | return clampedPoint.sub( point ).length(); 276 | 277 | }; 278 | 279 | }(), 280 | 281 | /** 282 | * @desc 获取box和当前box的相交矩形 283 | * @param {THREE.Box2} box 284 | * @returns {THREE.Box2} 285 | */ 286 | intersect: function ( box ) { 287 | 288 | this.min.max( box.min ); 289 | this.max.min( box.max ); 290 | 291 | return this; 292 | 293 | }, 294 | 295 | /** 296 | * @desc 获取box和当前box的相并矩形 297 | * @param {THREE.Box2} box 298 | * @returns {THREE.Box2} 299 | */ 300 | union: function ( box ) { 301 | 302 | this.min.min( box.min ); 303 | this.max.max( box.max ); 304 | 305 | return this; 306 | 307 | }, 308 | /** 309 | * @desc 2维矩形的平移 310 | * @param {float} offset 311 | * @returns {THREE.Box2} 312 | */ 313 | translate: function ( offset ) { 314 | 315 | this.min.add( offset ); 316 | this.max.add( offset ); 317 | 318 | return this; 319 | 320 | }, 321 | 322 | /** 323 | * @desc 判断box和当前2维矩形是否相等 324 | * @param {THREE.Box2} box 325 | * @returns {boolean} 326 | */ 327 | equals: function ( box ) { 328 | 329 | return box.min.equals( this.min ) && box.max.equals( this.max ); 330 | 331 | }, 332 | /** 333 | * @desc 克隆当前2维矩形 334 | * @returns {THREE.Box2} 335 | */ 336 | clone: function () { 337 | 338 | return new THREE.Box2().copy( this ); 339 | 340 | } 341 | 342 | }; 343 | -------------------------------------------------------------------------------- /materials/MeshPhongMaterial.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author mrdoob / http://mrdoob.com/ 3 | * @author alteredq / http://alteredqualia.com/ 4 | * 5 | * parameters = { 6 | * color: , 7 | * ambient: , 8 | * emissive: , 9 | * specular: , 10 | * shininess: , 11 | * opacity: , 12 | * 13 | * map: new THREE.Texture( ), 14 | * 15 | * lightMap: new THREE.Texture( ), 16 | * 17 | * bumpMap: new THREE.Texture( ), 18 | * bumpScale: , 19 | * 20 | * normalMap: new THREE.Texture( ), 21 | * normalScale: , 22 | * 23 | * specularMap: new THREE.Texture( ), 24 | * 25 | * alphaMap: new THREE.Texture( ), 26 | * 27 | * envMap: new THREE.TextureCube( [posx, negx, posy, negy, posz, negz] ), 28 | * combine: THREE.Multiply, 29 | * reflectivity: , 30 | * refractionRatio: , 31 | * 32 | * shading: THREE.SmoothShading, 33 | * blending: THREE.NormalBlending, 34 | * depthTest: , 35 | * depthWrite: , 36 | * 37 | * wireframe: , 38 | * wireframeLinewidth: , 39 | * 40 | * vertexColors: THREE.NoColors / THREE.VertexColors / THREE.FaceColors, 41 | * 42 | * skinning: , 43 | * morphTargets: , 44 | * morphNormals: , 45 | * 46 | * fog: 47 | * } 48 | */ 49 | /** 50 | * @classdesc 高光材质类型
51 | * 注释内容部分参照 http://blog.csdn.net/omni360 52 | * @desc mesh(网格)的phong(冯氏)高光材质类型
53 | * 表面有光泽的材质类型,计算每个像素 54 | * @param {String} parameters 材质参数 55 | * @extends {THREE.Material} 56 | * @constructor 57 | */ 58 | THREE.MeshPhongMaterial = function ( parameters ) { 59 | 60 | THREE.Material.call( this ); 61 | /** 62 | * @default 'MeshPhongMaterial' 63 | * @type {string} 64 | */ 65 | this.type = 'MeshPhongMaterial'; 66 | 67 | /** 68 | * @desc 材质颜色 69 | * @default 0xffffff 白色 70 | * @type {THREE.Color} 71 | */ 72 | this.color = new THREE.Color( 0xffffff ); // diffuse 73 | /** 74 | * @desc 环境色 75 | * @default 0xffffff 白色 76 | * @type {THREE.Color} 77 | */ 78 | this.ambient = new THREE.Color( 0xffffff ); 79 | /** 80 | * @desc 自发光(荧光)颜色 81 | * @default 0x000000 黑色 82 | * @type {THREE.Color} 83 | */ 84 | this.emissive = new THREE.Color( 0x000000 ); 85 | /** 86 | * @desc 高光色
87 | * 默认初始化为0x111111,灰色, 材质发光区域的颜色,
88 | * 比如设置为漫射颜色,亮度加大,材质更像金属,
89 | * 设成灰色,使材质更像塑料.默认是灰色的. 90 | * @default 0x111111 灰色 91 | * @type {THREE.Color} 92 | */ 93 | this.specular = new THREE.Color( 0x111111 ); 94 | /** 95 | * @desc 高光的强度,数值越大,高光呈现出一个亮点. 96 | * @default 97 | * @type {number} 98 | */ 99 | this.shininess = 30; 100 | /** 101 | * @desc 是否是金属 102 | * @default 103 | * @type {boolean} 104 | */ 105 | this.metal = false; 106 | 107 | /** 108 | * @desc 是否遮罩 109 | * @default 110 | * @type {boolean} 111 | */ 112 | this.wrapAround = false; 113 | /** 114 | * @desc 遮罩颜色 115 | * @default ( 1, 1, 1 ) 116 | * @type {THREE.Vector3} 117 | */ 118 | this.wrapRGB = new THREE.Vector3( 1, 1, 1 ); 119 | 120 | /** 121 | * @desc 纹理贴图 122 | * @default 123 | * @type {THREE.Texture} 124 | */ 125 | this.map = null; 126 | /** 127 | * @desc 光照贴图 128 | * @default 129 | * @type {THREE.Texture} 130 | */ 131 | this.lightMap = null; 132 | 133 | //所谓纯色的凹凸贴图就是如同浮雕效果一样的图像。其颜色与线框色相同。 134 | // 如果按默认色的话则为黑(白)色(即:黑色屏幕时为白色,白色背景时为黑色。) 135 | // 如下面的浮雕效果,就是白色线框绘出的立方体而凹凸贴图的。 136 | /** 137 | * @desc 凹凸贴图 138 | * @default 139 | * @type {THREE.Texture} 140 | */ 141 | this.bumpMap = null; 142 | /** 143 | * @desc 凹凸贴图的纹理大小. 144 | * @default 145 | * @type {float} 146 | */ 147 | this.bumpScale = 1; 148 | // 法线贴图就是在原物体的凹凸表面的每个点上均作法线, 149 | // 通过RGB颜色通道来标记法线的方向, 150 | // 你可以把它理解成与原凹凸表面平行的另一个不同的表面, 151 | // 但实际上它又只是一个光滑的平面。 152 | // 对于视觉效果而言,它的效率比原有的凹凸表面更高, 153 | // 若在特定位置上应用光源, 154 | // 可以让细节程度较低的表面生成高细节程度的精确光照方向和反射效果。 155 | /** 156 | * @desc 法线贴图 157 | * @default 158 | * @type {THREE.Texture} 159 | */ 160 | this.normalMap = null; 161 | /** 162 | * @desc 法线缩放,指定一个数值,将法线贴图与网格大小进行匹配. 163 | * @default ( 1, 1 ) 164 | * @type {THREE.Vector2} 165 | */ 166 | this.normalScale = new THREE.Vector2( 1, 1 ); 167 | 168 | /** 169 | * @desc 高光贴图 170 | * @default 171 | * @type {THREE.Texture} 172 | */ 173 | this.specularMap = null; 174 | /** 175 | * @desc 透明贴图 176 | * @default 177 | * @type {THREE.Texture} 178 | */ 179 | this.alphaMap = null; 180 | /** 181 | * @desc 环境贴图 182 | * @default 183 | * @type {THREE.Texture} 184 | */ 185 | this.envMap = null; 186 | /** 187 | * @desc 材质混合模式 188 | * @default THREE.MultiplyOperation 189 | * @type {number} 190 | */ 191 | this.combine = THREE.MultiplyOperation; 192 | /** 193 | * @desc 反射率 194 | * @default 195 | * @type {float} 196 | */ 197 | this.reflectivity = 1; 198 | /** 199 | * @desc 折射率 200 | * @default 201 | * @type {float} 202 | */ 203 | this.refractionRatio = 0.98; 204 | 205 | /** 206 | * @desc 雾效,默认开启 207 | * @default 208 | * @type {boolean} 209 | */ 210 | this.fog = true; 211 | 212 | /** 213 | * @desc 着色方式
214 | * THREE.SmoothShading平滑着色:用多种颜色进行绘制
215 | * 每个顶点都是单独进行处理的,各顶点和各图元之间采用均匀插值。 216 | * @default 217 | * @type {number} 218 | */ 219 | this.shading = THREE.SmoothShading; 220 | 221 | /** 222 | * @desc 是否以线框方式渲染几何体 223 | * @default 224 | * @type {boolean} 225 | */ 226 | this.wireframe = false; 227 | /** 228 | * @desc 线框宽度 229 | * @default 230 | * @type {float} 231 | */ 232 | this.wireframeLinewidth = 1; 233 | /** 234 | * @desc 线框端点类型,参照LineBasicMaterial的定义 235 | * @default 'round' 236 | * @type {string} 237 | */ 238 | this.wireframeLinecap = 'round'; 239 | /** 240 | * @desc 线框连接类型,参照LineBasicMaterial的定义 241 | * @default 'round' 242 | * @type {string} 243 | */ 244 | this.wireframeLinejoin = 'round'; 245 | 246 | /** 247 | * @desc 材质顶点颜色 248 | * @default THREE.NoColors 249 | * @type {number} 250 | */ 251 | this.vertexColors = THREE.NoColors; 252 | 253 | /** 254 | * @desc 材质是否使用蒙皮 255 | * @default 256 | * @type {boolean} 257 | */ 258 | this.skinning = false; 259 | /** 260 | * @desc 材质是否设定目标变形动画 261 | * @default 262 | * @type {boolean} 263 | */ 264 | this.morphTargets = false; 265 | /** 266 | * @desc 材质是否反转(变换)法线 267 | * @default 268 | * @type {boolean} 269 | */ 270 | this.morphNormals = false; 271 | 272 | this.setValues( parameters ); 273 | 274 | }; 275 | /** 276 | * @desc MeshPhongMaterial对象从THREE.Material的原型继承所有属性方法 277 | * @type {THREE.Material} 278 | */ 279 | THREE.MeshPhongMaterial.prototype = Object.create( THREE.Material.prototype ); 280 | /** 281 | * @desc MeshPhongMaterial材质的克隆函数 282 | * @returns {THREE.MeshPhongMaterial} 283 | */ 284 | THREE.MeshPhongMaterial.prototype.clone = function () { 285 | 286 | var material = new THREE.MeshPhongMaterial(); 287 | 288 | THREE.Material.prototype.clone.call( this, material ); 289 | 290 | material.color.copy( this.color ); 291 | material.ambient.copy( this.ambient ); 292 | material.emissive.copy( this.emissive ); 293 | material.specular.copy( this.specular ); 294 | material.shininess = this.shininess; 295 | 296 | material.metal = this.metal; 297 | 298 | material.wrapAround = this.wrapAround; 299 | material.wrapRGB.copy( this.wrapRGB ); 300 | 301 | material.map = this.map; 302 | 303 | material.lightMap = this.lightMap; 304 | 305 | material.bumpMap = this.bumpMap; 306 | material.bumpScale = this.bumpScale; 307 | 308 | material.normalMap = this.normalMap; 309 | material.normalScale.copy( this.normalScale ); 310 | 311 | material.specularMap = this.specularMap; 312 | 313 | material.alphaMap = this.alphaMap; 314 | 315 | material.envMap = this.envMap; 316 | material.combine = this.combine; 317 | material.reflectivity = this.reflectivity; 318 | material.refractionRatio = this.refractionRatio; 319 | 320 | material.fog = this.fog; 321 | 322 | material.shading = this.shading; 323 | 324 | material.wireframe = this.wireframe; 325 | material.wireframeLinewidth = this.wireframeLinewidth; 326 | material.wireframeLinecap = this.wireframeLinecap; 327 | material.wireframeLinejoin = this.wireframeLinejoin; 328 | 329 | material.vertexColors = this.vertexColors; 330 | 331 | material.skinning = this.skinning; 332 | material.morphTargets = this.morphTargets; 333 | material.morphNormals = this.morphNormals; 334 | 335 | return material; 336 | 337 | }; 338 | -------------------------------------------------------------------------------- /math/Plane.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author bhouston / http://exocortex.com 3 | */ 4 | /** 5 | * @classdesc 平面类
6 | * 注释内容部分参照 http://blog.csdn.net/omni360 7 | * @desc 法线向量为normal,从原点到平面的距离为constant的无限延展的2维平面对象 8 | * @param {THREE.Vector3} normal 法线向量 9 | * @param {number} constant 原点到平面的距离 10 | * @constructor 11 | */ 12 | THREE.Plane = function ( normal, constant ) { 13 | /** 14 | * @desc 平面法线 15 | * @default (1,0,0) 16 | * @type {THREE.Vector3} 17 | */ 18 | this.normal = ( normal !== undefined ) ? normal : new THREE.Vector3( 1, 0, 0 ); 19 | /** 20 | * @desc 原点到平面的距离 21 | * @default 0 22 | * @type {float} 23 | */ 24 | this.constant = ( constant !== undefined ) ? constant : 0; 25 | 26 | }; 27 | 28 | THREE.Plane.prototype = { 29 | 30 | constructor: THREE.Plane, 31 | /** 32 | * @desc 根据 normal 和 constant 设置平面 33 | * @param {THREE.Vector3} normal 法线向量 34 | * @param {float} constant 原点到平面的距离 35 | * @returns {THREE.Plane} 36 | */ 37 | set: function ( normal, constant ) { 38 | 39 | this.normal.copy( normal ); 40 | this.constant = constant; 41 | 42 | return this; 43 | 44 | }, 45 | /** 46 | * @desc 过x,y,z,w分量重新设置二维平面 47 | * @param {float} x 平面法线向量x坐标 48 | * @param {float} y 平面法线向量y坐标 49 | * @param {float} z 平面法线向量z坐标 50 | * @param {float} w 二维平面离原点的距离 51 | * @returns {THREE.Plane} 52 | */ 53 | setComponents: function ( x, y, z, w ) { 54 | 55 | this.normal.set( x, y, z ); 56 | this.constant = w; 57 | 58 | return this; 59 | 60 | }, 61 | /** 62 | * @desc 通过参数normal(平面法线向量)和参数point(共面的点)重新设置二维平面 63 | * @param {THREE.Vector3} normal 64 | * @param {THREE.Vector3} point 65 | * @returns {THREE.Plane} 66 | */ 67 | setFromNormalAndCoplanarPoint: function ( normal, point ) { 68 | 69 | this.normal.copy( normal ); 70 | this.constant = - point.dot( this.normal ); // must be this.normal, not normal, as this.normal is normalized 71 | 72 | return this; 73 | 74 | }, 75 | 76 | /** 77 | * @function 78 | * @desc 通过共面的点a,b,c重新设置二维平面 79 | * @param {THREE.Vector3} a 80 | * @param {THREE.Vector3} b 81 | * @param {THREE.Vector3} c 82 | * @returns {THREE.Plane} 83 | */ 84 | setFromCoplanarPoints: function () { 85 | 86 | var v1 = new THREE.Vector3(); 87 | var v2 = new THREE.Vector3(); 88 | 89 | return function ( a, b, c ) { 90 | 91 | var normal = v1.subVectors( c, b ).cross( v2.subVectors( a, b ) ).normalize(); 92 | 93 | // Q: should an error be thrown if normal is zero (e.g. degenerate plane)? 94 | 95 | this.setFromNormalAndCoplanarPoint( normal, a ); 96 | 97 | return this; 98 | 99 | }; 100 | 101 | }(), 102 | 103 | /** 104 | * @desc 二维平面的拷贝 105 | * @param {THREE.Plane} plane 106 | * @returns {THREE.Plane} 107 | */ 108 | copy: function ( plane ) { 109 | 110 | this.normal.copy( plane.normal ); 111 | this.constant = plane.constant; 112 | 113 | return this; 114 | 115 | }, 116 | /** 117 | * @desc 二维平面的单位化
118 | * 几何意义:单位化法线向量,并调整constant常量的值 119 | * @returns {THREE.Plane} 120 | */ 121 | normalize: function () { 122 | 123 | // Note: will lead to a divide by zero if the plane is invalid. 124 | 125 | var inverseNormalLength = 1.0 / this.normal.length(); 126 | this.normal.multiplyScalar( inverseNormalLength ); 127 | this.constant *= inverseNormalLength; 128 | 129 | return this; 130 | 131 | }, 132 | /** 133 | * @desc 获得二维平面的负平面
134 | * 几何意义:获得二维平面的背面 135 | * @returns {THREE.Plane} 136 | */ 137 | negate: function () { 138 | 139 | this.constant *= - 1; 140 | this.normal.negate(); 141 | 142 | return this; 143 | 144 | }, 145 | /** 146 | * @desc 三维空间内一点到Plane二维平面对象表面的最小长度.
147 | * 几何意义:点到面上的投影等于从参数point到平面上的垂距 148 | * @param {THREE.Vector3} point 149 | * @returns {float} 150 | */ 151 | distanceToPoint: function ( point ) { 152 | 153 | return this.normal.dot( point ) + this.constant; 154 | 155 | }, 156 | /** 157 | * @desc 三维空间内球体到Plane二维平面对象表面的最小长度
158 | * 几何意义:球体到面上的投影等于从球体表面到平面上的最小垂距 159 | * @param {THREE.Sphere} sphere 160 | * @returns {float} 161 | */ 162 | distanceToSphere: function ( sphere ) { 163 | 164 | return this.distanceToPoint( sphere.center ) - sphere.radius; 165 | 166 | }, 167 | /** 168 | * @desc 三维空间中一点到当前平面的投影
169 | * 几何意义:点到面上的投影等于从参数point到平面上的垂足 170 | * @param {THREE.Vector3} point 171 | * @param {THREE.Vector3} optionalTarget 172 | * @returns {THREE.Vector3} 173 | */ 174 | projectPoint: function ( point, optionalTarget ) { 175 | 176 | return this.orthoPoint( point, optionalTarget ).sub( point ).negate(); 177 | 178 | }, 179 | 180 | /** 181 | * @desc 当前二维平面对象法线向量方向相同,与参数point到平面距离相等大小的向量
182 | * 几何意义:点到面上的投影等于从参数point到平面上的垂足向量 183 | * @param {THREE.Vector3} point 184 | * @param {THREE.Vector3} optionalTarget 185 | * @returns {THREE.Vector3} 186 | */ 187 | orthoPoint: function ( point, optionalTarget ) { 188 | 189 | var perpendicularMagnitude = this.distanceToPoint( point ); 190 | 191 | var result = optionalTarget || new THREE.Vector3(); 192 | return result.copy( this.normal ).multiplyScalar( perpendicularMagnitude ); 193 | 194 | }, 195 | /** 196 | * @desc 当前二维平面是否与参数line相交 197 | * @param {THREE.Line3} line 198 | * @returns {boolean} 199 | */ 200 | isIntersectionLine: function ( line ) { 201 | 202 | // Note: this tests if a line intersects the plane, not whether it (or its end-points) are coplanar with it. 203 | 204 | var startSign = this.distanceToPoint( line.start ); 205 | var endSign = this.distanceToPoint( line.end ); 206 | 207 | return ( startSign < 0 && endSign > 0 ) || ( endSign < 0 && startSign > 0 ); 208 | 209 | }, 210 | /** 211 | * @function 212 | * @desc 当前二维平面与参数line相交的交点 213 | * @param {THREE.Line3} line 214 | * @param {THREE.Vector3} optionalTarget 215 | * @return {THREE.Vector3} 216 | */ 217 | intersectLine: function () { 218 | 219 | var v1 = new THREE.Vector3(); 220 | 221 | return function ( line, optionalTarget ) { 222 | 223 | var result = optionalTarget || new THREE.Vector3(); 224 | 225 | var direction = line.delta( v1 ); 226 | 227 | var denominator = this.normal.dot( direction ); 228 | 229 | if ( denominator == 0 ) { 230 | 231 | // line is coplanar, return origin 232 | if ( this.distanceToPoint( line.start ) == 0 ) { 233 | 234 | return result.copy( line.start ); 235 | 236 | } 237 | 238 | // Unsure if this is the correct method to handle this case. 239 | return undefined; 240 | 241 | } 242 | 243 | var t = - ( line.start.dot( this.normal ) + this.constant ) / denominator; 244 | 245 | if ( t < 0 || t > 1 ) { 246 | 247 | return undefined; 248 | 249 | } 250 | 251 | return result.copy( direction ).multiplyScalar( t ).add( line.start ); 252 | 253 | }; 254 | 255 | }(), 256 | 257 | /** 258 | * @desc 当前二维平面的法线向量到当前二维平面投影点 259 | * @param {THREE.Vector3} optionalTarget 260 | * @returns {THREE.Vector3} 261 | */ 262 | coplanarPoint: function ( optionalTarget ) { 263 | 264 | var result = optionalTarget || new THREE.Vector3(); 265 | return result.copy( this.normal ).multiplyScalar( - this.constant ); 266 | 267 | }, 268 | /** 269 | * @function 270 | * @desc 通过传递matrix(旋转,缩放,移动等变换矩阵)对当前Plane二维平面对象的法线向量normal和,应用变换. 271 | * @param {THREE.Matrix4} matrix 272 | * @param {THREE.Matrix4} optionalNormalMatrix 若设置了,可以对法线变换 273 | * @return {THREE.Plane} 274 | */ 275 | applyMatrix4: function () { 276 | 277 | var v1 = new THREE.Vector3(); 278 | var v2 = new THREE.Vector3(); 279 | var m1 = new THREE.Matrix3(); 280 | 281 | return function ( matrix, optionalNormalMatrix ) { 282 | 283 | // compute new normal based on theory here: 284 | // http://www.songho.ca/opengl/gl_normaltransform.html 285 | var normalMatrix = optionalNormalMatrix || m1.getNormalMatrix( matrix ); 286 | var newNormal = v1.copy( this.normal ).applyMatrix3( normalMatrix ); 287 | 288 | var newCoplanarPoint = this.coplanarPoint( v2 ); 289 | newCoplanarPoint.applyMatrix4( matrix ); 290 | 291 | this.setFromNormalAndCoplanarPoint( newNormal, newCoplanarPoint ); 292 | 293 | return this; 294 | 295 | }; 296 | 297 | }(), 298 | 299 | /** 300 | * @desc 移动当前二维平面的位置 301 | * @param {THREE.Vector3} offset 302 | * @returns {THREE.Plane} 303 | */ 304 | translate: function ( offset ) { 305 | 306 | this.constant = this.constant - offset.dot( this.normal ); 307 | 308 | return this; 309 | 310 | }, 311 | /** 312 | * @desc 判断二维平面是否相等 313 | * @param plane 314 | * @returns {boolean} 315 | */ 316 | equals: function ( plane ) { 317 | 318 | return plane.normal.equals( this.normal ) && ( plane.constant == this.constant ); 319 | 320 | }, 321 | /** 322 | * @desc 克隆二维平面 323 | * @returns {THREE.Plane} 324 | */ 325 | clone: function () { 326 | 327 | return new THREE.Plane().copy( this ); 328 | 329 | } 330 | 331 | }; 332 | --------------------------------------------------------------------------------