three.js 源代码凝视(十五)Math/Plane.js

本文深入解析Three.js中Plane对象的构造与功能函数,包括如何创建平面、设置法线向量、距离原点的距离,以及提供了丰富的操作平面的方法,如规范化、翻转、复制和变换等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

商域无疆 (http://blog.csdn.net/omni360/)

本文遵循“署名-非商业用途-保持一致”创作公用协议

转载请保留此句:商域无疆 -  本博客专注于 敏捷开发及移动和物联设备研究:数据可视化、GOLANG、Html5、WEBGL、THREE.JS否则,出自本博客的文章拒绝转载或再转载,谢谢合作。


俺也是刚開始学,好多地儿肯定不正确还请见谅.

下面代码是THREE.JS 源代码文件里Math/Plane.js文件的凝视.

很多其它更新在 : https://github.com/omni360/three.js.sourcecode/blob/master/Three.js


// File:src/math/Plane.js

/**
 * @author bhouston / http://exocortex.com
 */

/*
///Plane对象的构造函数.用来在三维空间内创建一个法线向量为normal,从原点到平面的距离为constant的无限延展的二维平面对象.Plane对象的功能函数採用
///定义构造的函数原型对象来实现.
///
///	使用方法: var normal = new Vector3(0,0,0),constant = 5.5; var Plane = new Plane(normal,constant);
///创建一个法线向量是0,0,0原点到平面的距离是5.5的二维平面.
*/
///<summary>Plane</summary>
///<param name ="normal" type="Vector3">平面法线向量</param>
///<param name ="constant" type="Number">Number二维平面离原点的距离</param>
THREE.Plane = function ( normal, constant ) {

	this.normal = ( normal !== undefined ) ? normal : new THREE.Vector3( 1, 0, 0 );	//赋值或者初始化normal
	this.constant = ( constant !== undefined ) ? constant : 0;	//赋值或者初始化constant

};

/****************************************
****以下是Plane对象提供的功能函数.
****************************************/
THREE.Plane.prototype = {

	constructor: THREE.Plane,	//构造器,返回对创建此对象的Plane函数的引用

	/*
	///set方法用来又一次设置二维平面的法线向量normal,原点到平面的距离constant,并返回新的二维平面.
	*/
	///<summary>set</summary>
	///<param name ="normal" type="Vector3">平面法线向量</param>
	///<param name ="constant" type="Number">Number二维平面离原点的距离</param>
	///<returns type="Plane">返回新的二维平面</returns>
	set: function ( normal, constant ) {

		this.normal.copy( normal );
		this.constant = constant;

		return this;		//返回新的二维平面

	},

	/*
	///setComponents方法用来通过x,y,z,w分量又一次设置二维平面的法线向量normal,原点到平面的距离constant,并返回新的二维平面.
	*/
	///<summary>setComponents</summary>
	///<param name ="normal" type="Vector3">平面法线向量</param>
	///<param name ="x" type="Number">平面法线向量x坐标</param>
	///<param name ="y" type="Number">平面法线向量y坐标</param>
	///<param name ="z" type="Number">平面法线向量z坐标</param>
	///<param name ="w" type="Number">Number二维平面离原点的距离w</param>
	///<returns type="Plane">返回新的二维平面</returns>
	setComponents: function ( x, y, z, w ) {

		this.normal.set( x, y, z );
		this.constant = w;

		return this;		//返回新的二维平面

	},

	/*
	///setFromNormalAndCoplanarPoint方法用来通过參数normal(平面法线向量)和參数point(共面的点)又一次设置二维平面的法线向量normal,原点到平面的距离constant,并返回新的二维平面.
	*/
	///<summary>setFromNormalAndCoplanarPoint</summary>
	///<param name ="normal" type="Vector3">平面法线向量</param>
	///<param name ="point" type="Vector3">共面的点</param>
	///<returns type="Plane">返回新的二维平面</returns>
	setFromNormalAndCoplanarPoint: function ( normal, point ) {

		this.normal.copy( normal );
													//以下point.dot()方法仅仅接收this.normal,不接收normal,this.normal是被规范化的,是单位向量
		this.constant = - point.dot( this.normal );	// must be this.normal, not normal, as this.normal is normalized

		return this;	//并返回新的二维平面

	},

	/*
	///setFromCoplanarPoints方法用来通过共面的点a,b,c又一次设置二维平面的法线向量normal,原点到平面的距离constant,并返回新的二维平面.
	/// NOTE:setFromCoplanarPoints方法接受的3个点a,b,c,须要依照逆时针方向的顺序传入,来确定发现的方向.
	*/
	///<summary>setFromCoplanarPoints</summary>
	///<param name ="a" type="Vector3">共面的点a</param>
	///<param name ="b" type="Vector3">共面的点b</param>
	///<param name ="c" type="Vector3">共面的点c</param>
	///<returns type="Plane">返回新的二维平面</returns>
	setFromCoplanarPoints: function () {

		var v1 = new THREE.Vector3();
		var v2 = new THREE.Vector3();

		return function ( a, b, c ) {

			var normal = v1.subVectors( c, b ).cross( v2.subVectors( a, b ) ).normalize();	//先得到向量c,b的差,通过cross方法获得向量a,b差的交叉乘积(交叉乘积垂直于向量a,b所在的平面),然后在调用normalize()方法获得单位向量.

			// Q: should an error be thrown if normal is zero (e.g. degenerate plane)?

//NOTE: 假设法向量normal是0,会产生一个无效的平面对象. this.setFromNormalAndCoplanarPoint( normal, a ); //setFromNormalAndCoplanarPoint方法用来通过參数normal(平面法线向量)和參数point(共面的点)又一次设置二维平面的法线向量normal,原点到平面的距离constant,并返回新的二维平面. return this; //返回新的二维平面 }; }(), /* ///copy方法用来复制二维平面的法线向量normal,原点到平面的距离constant值.返回新的二维平面 ///TODO: copy方法和clone方法有什么不同? */ ///<summary>copy</summary> ///<param name ="Plane" type="Plane">二维平面</param> ///<returns type="Plane">返回新的二维平面</returns> copy: function ( plane ) { this.normal.copy( plane.normal ); this.constant = plane.constant; return this; //返回新的二维平面 }, /* ///normalize方法用来规范化法线向量,并调整constant常量的值(获得单位平面). */ ///<summary>normalize</summary> ///<returns type="Plane">返回规范化后的二维平面(获得单位平面)</returns> normalize: function () { // Note: will lead to a divide by zero if the plane is invalid. // NOTE: 注意假设平面无效将产生除数是0的错误. var inverseNormalLength = 1.0 / this.normal.length(); this.normal.multiplyScalar( inverseNormalLength ); this.constant *= inverseNormalLength; return this; //返回规范化的二维平面(获得单位平面) }, /* ///negate方法用来翻转法线,获得当前平面的背面, */ ///<summary>negate</summary> ///<returns type="Plane">返回当前平面的背面</returns> negate: function () { this.constant *= - 1; this.normal.negate(); //翻转法线,Vector3.negate方法将当前三维向量的(x,y,z)坐标值若为负数时,返回正数. 而当前三维向量的(x,y,z)坐标值若为正数时,返回负数. return this; //返回当前平面的背面 }, /* ///distanceToPoint方法用来获得三维空间内一点到Plane二维平面对象表面的最小长度. */ ///<summary>distanceToPoint</summary> ///<param name ="point" type="Vector3">一个三维空间内的Vector3的三维点坐标</param> ///<returns type="Number">返回三维空间内一点到Plane二维平面对象表面的最小长度.</returns> distanceToPoint: function ( point ) { return this.normal.dot( point ) + this.constant; //返回三维空间内一点到Plane二维平面对象表面的最小长度 }, /* ///distanceToPoint方法用来获得Plane二维平面对象到三维空间内一个球体表面的最小长度.() */ ///<summary>distanceToPoint</summary> ///<param name ="sphere" type="Sphere">一个三维空间内的Sphere的球体对象</param> ///<returns type="Number">返回三维空间内Plane二维平面对象到三维空间内一个球体表面的最小长度.</returns> distanceToSphere: function ( sphere ) { return this.distanceToPoint( sphere.center ) - sphere.radius; //返回三维空间内Plane二维平面对象到三维空间内一个球体表面的最小长度 }, /* ///projectPoint方法返回三维空间中一点到当前平面的投影.点到面上的投影等于从參数point到平面上的垂足,所以从垂足画条线到点垂直于平面. */ ///<summary>projectPoint</summary> ///<param name ="point" type="Vector3">Vector3三维向量</param> ///<param name ="optionalTarget" type="Vector3">可选參数,接收返回结果</param> ///<returns type="Number">返回点到平面的投影</returns> projectPoint: function ( point, optionalTarget ) { return this.orthoPoint( point, optionalTarget ).sub( point ).negate(); //调用orthoPoint()方法,减去point,返回取反的结果 }, /* ///orthoPoint方法返回一个与当前二维平面对象法线向量方向同样,与參数point到平面距离相等大小的向量(垂足).假设设置了optionalTarget參数,将结果保存在optionalTarget里. */ ///<summary>orthoPoint</summary> ///<param name ="point" type="Vector3">Vector3三维向量</param> ///<param name ="optionalTarget" type="Vector3">可选參数,接收返回结果</param> ///<returns type="Vector3">返回一个与当前二维平面对象法线向量方向同样,与參数point到平面距离相等大小的向量(垂足).</returns> orthoPoint: function ( point, optionalTarget ) { var perpendicularMagnitude = this.distanceToPoint( point ); //获得平面到參数point的距离,赋值给prependicularMagnitude var result = optionalTarget || new THREE.Vector3(); //生命变量resault,用来存放结果 return result.copy( this.normal ).multiplyScalar( perpendicularMagnitude ); //调用multiplyScalar(perpendicularMagnitude)方法,将当前二维平面的法向量的分量x,y,z分别乘以获得平面到參数point的距离.最后返回计算结果. }, /* ///isIntersectionLine方法获取当前二维平面是否与參数line相交,返回true 或者 false */ ///<summary>isIntersectionLine</summary> ///<param name ="line" type="Line3">三维空间中的线Line3</param> ///<returns type="Boolean">返回true 或者 false</returns> isIntersectionLine: function ( line ) { // Note: this tests if a line intersects the plane, not whether it (or its end-points) are coplanar with it. // NOTE:isIntersectionLine()是測试线和面是否相交,不是误以为线和面是否共面 var startSign = this.distanceToPoint( line.start ); var endSign = this.distanceToPoint( line.end ); return ( startSign < 0 && endSign > 0 ) || ( endSign < 0 && startSign > 0 ); //返回true 或者 false }, /* ///intersectLine方法获取当前二维平面与參数line相交的交点,假设和參数Line不相交返回undefined,假设线和当前二维平面共面返回线的起点. */ ///<summary>isIntersectionLine</summary> ///<param name ="line" type="Line3">三维空间中的线Line3</param> ///<param name ="optionalTarget" type="Vector3">可选參数,接收返回结果</param> ///<returns type="Boolean">返回当前二维平面与參数line相交的交点,假设和參数Line不相交或其他未知返回undefined,假设线和当前二维平面共面返回线的起点.</returns> intersectLine: function () { var v1 = new THREE.Vector3(); return function ( line, optionalTarget ) { var result = optionalTarget || new THREE.Vector3(); var direction = line.delta( v1 ); var denominator = this.normal.dot( direction ); if ( denominator == 0 ) { // line is coplanar, return origin // 假设线和当前二维平面共面返回线的起点 if ( this.distanceToPoint( line.start ) == 0 ) { return result.copy( line.start ); } // Unsure if this is the correct method to handle this case. // 假设其他未知返回undefined return undefined; } var t = - ( line.start.dot( this.normal ) + this.constant ) / denominator; if ( t < 0 || t > 1 ) { return undefined; //假设和參数Line不相交返回undefined } return result.copy( direction ).multiplyScalar( t ).add( line.start ); //返回当前二维平面与參数line相交的交点 }; }(), /* ///coplanarPoint方法获取当前二维平面的法线向量到当前二维平面投影(垂足,与当前平面的共面的点). ///TODO:这里没有弄明确,有时间在弄清楚,高中几何都快忘光了,钻牛角尖了.只是知道在以下应用变换时调用了. */ ///<summary>coplanarPoint</summary> ///<param name ="optionalTarget" type="Vector3">可选參数,接收返回结果</param> ///<returns type="Boolean">返回共面的点.</returns> coplanarPoint: function ( optionalTarget ) { var result = optionalTarget || new THREE.Vector3(); return result.copy( this.normal ).multiplyScalar( - this.constant ); //返回共面的点 }, /* ///applyMatrix4方法通过传递matrix(旋转,缩放,移动等变换矩阵)对当前Plane二维平面对象的法线向量normal和,应用变换. */ ///<summary>applyMatrix4</summary> ///<param name ="matrix" type="Matrix4">(旋转,缩放,移动等变换矩阵</param> ///<param name ="optionalNormalMatrix" type="Matrix3">可选參数,假设设置了就会对法线应用(旋转,缩放,移动等变换矩阵</param> ///<returns type="Boolean">返回变换后的二维平面.</returns> applyMatrix4: function () { var v1 = new THREE.Vector3(); var v2 = new THREE.Vector3(); var m1 = new THREE.Matrix3(); return function ( matrix, optionalNormalMatrix ) { // compute new normal based on theory here: // http://www.songho.ca/opengl/gl_normaltransform.html var normalMatrix = optionalNormalMatrix || m1.getNormalMatrix( matrix ); var newNormal = v1.copy( this.normal ).applyMatrix3( normalMatrix ); var newCoplanarPoint = this.coplanarPoint( v2 ); //获得共面的点 newCoplanarPoint.applyMatrix4( matrix ); this.setFromNormalAndCoplanarPoint( newNormal, newCoplanarPoint ); //setFromNormalAndCoplanarPoint方法用来通过參数normal(平面法线向量)和參数point(共面的点)又一次设置二维平面的法线向量normal,原点到平面的距离constant,并返回新的二维平面. return this; //返回变换后的二维平面 }; }(), /* ///translate方法用来通过參数offset,移动当前二维平面的位置. */ ///<summary>translate</summary> ///<param name ="offset" type="Vector3">偏移量</param> ///<returns type="Boolean">返回新的二维平面</returns> translate: function ( offset ) { this.constant = this.constant - offset.dot( this.normal ); return this; //返回新的二维平面 }, /* ///equals方法用来获得參数Plane(一个Plane的二维平面)是否与当前二维平面全然相等,即法线向量normal和半径相等. */ ///<summary>equals</summary> ///<param name ="Plane" type="Plane">一个Plane的二维平面</param> ///<returns type="Boolean">返回true 或者 false</returns> equals: function ( plane ) { return plane.normal.equals( this.normal ) && ( plane.constant == this.constant ); //返回true 或者 false }, /*clone方法 ///clone方法克隆一个二维平面对象. */ ///<summary>clone</summary> ///<returns type="Plane">返回二维平面对象</returns> clone: function () { return new THREE.Plane().copy( this ); //返回二维平面对象 } };




商域无疆 (http://blog.csdn.net/omni360/)

本文遵循“署名-非商业用途-保持一致”创作公用协议

转载请保留此句:商域无疆 -  本博客专注于 敏捷开发及移动和物联设备研究:数据可视化、GOLANG、Html5、WEBGL、THREE.JS否则,出自本博客的文章拒绝转载或再转载,谢谢合作。


下面代码是THREE.JS 源代码文件里Math/Plane.js文件的凝视.

很多其它更新在 : https://github.com/omni360/three.js.sourcecode/blob/master/Three.js

转载于:https://www.cnblogs.com/yxysuanfa/p/6872813.html

### 使用 Three.js 创建地图效果 Three.js 是一个功能强大的 JavaScript 庢库,用于在浏览器中渲染 3D 图形。通过结合其他工具或数据源(如地理坐标),可以实现复杂的 3D 地图效果。 #### 基础概念 为了创建基于 Three.js 的地图效果,通常需要以下几个核心组件: - **场景 (Scene)**:定义整个三维空间。 - **相机 (Camera)**:决定观察视角。 - **几何体 (Geometry)** 和 材质 (Material):构建地形或其他对象。 - **光源 (Lighting)**:增强视觉效果。 - **动画 (Animation)**:动态展示地图上的变化。 以下是具体方法和技术细节: --- #### 方法一:基础地形绘制 可以通过加载高度图(Height Map)来模拟地球表面的起伏。这种方法适用于简单的地形可视化。 ```javascript // 初始化场景、相机和渲染器 const scene = new THREE.Scene(); const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000); const renderer = new THREE.WebGLRenderer(); renderer.setSize(window.innerWidth, window.innerHeight); document.body.appendChild(renderer.domElement); // 加载高度图并生成地形 const loader = new THREE.TextureLoader(); loader.load('heightmap.png', function(texture) { const geometry = new THREE.PlaneBufferGeometry(100, 100, 256, 256); // 平面网格 const displacementMap = texture; // 设置位移贴图 const material = new THREE.MeshStandardMaterial({ color: 0x87ceeb, displacementMap: displacementMap, displacementScale: 5 // 控制地形高低程度 }); const plane = new THREE.Mesh(geometry, material); plane.rotation.x = Math.PI / 2; scene.add(plane); }); camera.position.z = 100; function animate() { requestAnimationFrame(animate); renderer.render(scene, camera); } animate(); ``` 此代码片段展示了如何利用 `displacementMap` 属性生成具有高度差异的地表纹理[^1]。 --- #### 方法二:集成外部地图服务 如果希望更精确地表示地理位置,则可结合第三方地图 API(如高德地图)。例如,使用高德地图作为底图,并叠加 Three.js 渲染的 3D 效果。 ##### 步骤概述 1. 获取高德地图的二维视图; 2. 将其嵌入到 HTML 页面中的 `<canvas>` 容器; 3. 利用 Three.js 添加额外的 3D 对象(如飞线、标志物等)。 下面是一个简化版的例子,演示如何将 Two.js 和 Highcharts 结合在一起[^2]: ```html <div id="amap-container"></div> <script src="https://webapi.amap.com/maps?v=1.4&key=YOUR_API_KEY"></script> <script type="module"> import * as THREE from 'https://cdn.skypack.dev/three'; let map = new AMap.Map('amap-container', { zoom: 10 }); AMap.plugin(['AMap.FlightLine'], () => { let flightLine = new AMap.FlightLine({ path: [[...]], ...}); map.add(flightLine); // 同时初始化 Three.js 场景... const scene = new THREE.Scene(); ... }); </script> ``` 上述代码实现了基本的地图框架以及飞行轨迹的功能扩展。 --- #### 方法三:复杂交互与特效设计 对于更加高级的需求——比如实时更新的数据流显示或者互动性强的应用程序来说,还需要考虑性能优化策略及用户体验提升措施。这可能涉及以下方面: - 数据压缩传输减少延迟时间; - GPU加速计算提高帧率表现; - 用户界面友好度调整使得操作简便直观等等。 --- ### 总结 无论是单纯依靠 Three.js 构建静态模型还是与其他平台协作完成综合型应用开发工作,在实际项目实施过程中都需要充分考虑到资源消耗情况以及最终呈现质量之间的平衡关系。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值