three.js 数学方法之Plane
今天郭先生就来继续说一说three.js数学方法中的plane(平面)。在三维空间中无限延伸的二维平面,平面方程用单位长度的法向量和常数表示。构造器为Plane( normal : Vector3, constant : Float )。第一个参数为平面的法向量,既然是法向量也就预示着这个平面是有方向之分的,第二个参数是平面到法向量的距离,因为法向量相同到原点距离相同的平面也是有两个,所以这个constant也是有正负号的之分的。接下来我先说下它的属性和方法,最后给一个plane相关的小案例。
1. plane的属性
1. normal
获取plane的法向量
2. constant
获取plane到原点的距离
2. plane的方法
1. set( normal: Vector3, constant: number ): Plane
设置平面 normal 的法线和常量 constant 属性值。
new THREE.Plane().set(new THREE.Vector3(0,1,0), -10);
这里可要注意plane的法向量为new THREE.Vector3(0,1,0)代表平面的正方向是沿Y轴向上的,距离-10代表平面到原点的距离,符号代表和法向量的方向相反,所以这个这个平面在Y轴正方向。如下图,这是一个size为20的planeHelper所展示的plane。
2. setComponents( x: number, y: number, z: number, w: number ): Plane
设置定义平面的各个变量。
x - 单位长度法向量的x值。
y - 单位长度法向量的y值。
z - 单位长度法向量的z值。
w - 原点沿法向量到平面常量 constant 距离。
new THREE.Plane().setComponents(0,1,0,-10);//效果同上
3. setFromNormalAndCoplanarPoint( normal: Vector3, point: Vector3 ): Plane
通过平面上的一点以及法线确定平面。
new THREE.Plane().setFromNormalAndCoplanarPoint(new THREE.Vector3(0,1,0), new THREE.Vector3(10,10,10));//效果同上
4. setFromCoplanarPoints( a: Vector3, b: Vector3, c: Vector3 ): Plane
根据给定的三个点确定平面。通过右手螺旋规则确定(向量叉乘)法向量 normal。
new THREE.Plane().setFromCoplanarPoints(new THREE.Vector3(-10,10,9), new THREE.Vector3(2,10,3), new THREE.Vector3(10,10,10));//效果同上
new THREE.Plane().setFromCoplanarPoints(new THREE.Vector3(1,2,3), new THREE.Vector3(2,2,3), new THREE.Vector3(3,2,3));//如果三个点共线的话将返回默认的平面
5. clone(): this
返回一个与当前平面有相同法线 normal,常量 constant 距离的平面。就不多说了
6. copy( plane: Plane ): this
拷贝给定平面,将其中的法线 normal,距离常量 constant属性拷贝给该对象。克隆和拷贝的方法我们已经说的很多了
7. normalize(): Plane
归一化法向量 normal ,并相应的调整常量 constant数值。这个比较有意思我们说一下
//首先我们通过构造函数,并且两个法向量方向相同模长不同,因为返回的constant相同,实际上得到的是相同的平面,因为法向量默认是归一化了的
var plane1 = new THREE.Plane(new THREE.Vector3(2,2,0), -20);//constant: -20,normal: Vector3 {x: 2, y: 2, z: 0}
var plane2 = new THREE.Plane(new THREE.Vector3(1,1,0), -20);//constant: -20,normal: Vector3 {x: 1, y: 1, z: 0} //然后我们将其归一化,这是两个plane的constant,也会随着归一化的比例调整,所以实际效果的距离相差一倍。
var plane_n1 = plane1.normalize();//返回constant: -7.071067811865475,normal: Vector3 {x: 0.7071067811865475, y: 0.7071067811865475, z: 0}
var plane_n2 = plane2.normalize();//返回constant: -14.14213562373095,normal: Vector3 {x: 0.7071067811865475, y: 0.7071067811865475, z: 0}
8. negate(): Plane
将法向量与常量求反(乘以-1)。
var plane1 = new THREE.Plane(new THREE.Vector3(2,2,0), -10);
plane1.negate();
注意这个方法直接修改原plane
9. distanceToPoint( point: Vector3 ): number
返回点point到平面的有符号距离。在法向量方向的正方向则返回正值。
var plane1 = new THREE.Plane(new THREE.Vector3(0,1,0), -10);
plane1.distanceToPoint(new THREE.Vector3(0,1,0))//返回-9
10. distanceToSphere( sphere: Sphere ): number
返回球面 sphere 的边缘到平面的最短距离。
var plane = new THREE.Plane(new THREE.Vector3(0,1,0), -10);
var sphere = new THREE.Sphere(new THREE.Vector3(0,0,0), 5);
plane.distanceToSphere(sphere)//返回-15
//three.js distanceToSphere源码
distanceToSphere: function ( sphere ) {
return this.distanceToPoint( sphere.center ) - sphere.radius;
},
按照道理来说球面到平面的最近距离应该是5,而返回的是-15,看到源码发现,这个最短距离的求法是先算平面到球心的距离减去球的半径,即-10-5=-15。
11. projectPoint( point: Vector3, target: Vector3 ): Vector3
将一个点point投射到该平面上。
var plane = new THREE.Plane(new THREE.Vector3(0,1,0), -10);
plane.projectPoint(new THREE.Vector3(1,1,1));//返回(1,10,1)
12. intersectLine( line: Line3, target: Vector3 ): Vector3 | undefined
返回给定线段和平面的交点。如果不相交则返回undefined。如果线与平面共面,则返回该线段的起始点。
var line1 = new THREE.Line3(new THREE.Vector3(0,0,0), new THREE.Vector3(9,9,9));
var line2 = new THREE.Line3(new THREE.Vector3(0,0,0), new THREE.Vector3(11,11,11));
console.log(plane.intersectLine(line1))//返回undefined
console.log(plane.intersectLine(line2))//返回Vector3 {x: 10, y: 10, z: 10}
13. intersectsLine( line: Line3 ): boolean
测试线段是否与平面相交。
var line1 = new THREE.Line3(new THREE.Vector3(0,0,0), new THREE.Vector3(9,9,9));
var line2 = new THREE.Line3(new THREE.Vector3(0,0,0), new THREE.Vector3(11,11,11));
console.log(plane.intersectLine(line1))//返回false
console.log(plane.intersectLine(line2))//返回true
14. intersectsBox( box: Box3 ): boolean
确定该平面是否与给定3d包围盒Box3相交。
var box1 = new THREE.Box3(new THREE.Vector3(-2,-2,-2), new THREE.Vector3(2,2,2));
var box2 = new THREE.Box3(new THREE.Vector3(-2,-2,-2), new THREE.Vector3(2,10,2));
console.log(plane.intersectsBox(box1));//不相交返回false
console.log(plane.intersectsBox(box2));//相交返回true
15. intersectsSphere( sphere: Sphere ): boolean
确定该平面是否与给定球体 Sphere 相交。
var sphere1 = new THREE.Sphere(new THREE.Vector3(0,0,0), 5);
var sphere2 = new THREE.Sphere(new THREE.Vector3(0,0,0), 10);
console.log(plane.intersectsBox(sphere1));//不相交返回false
console.log(plane.intersectsBox(sphere2));//相交返回true
16. coplanarPoint( target: Vector3 ): Vector3
返回一个共面点,通过原点的法向量在平面上投影算得。这个方法和projectPoint很相似。只是固定为原点的投影,
var plane = new THREE.Plane(new THREE.Vector3(1,1,1), -10);
plane.coplanarPoint(new THREE.Vector3())//返回Vector3 {x: 10, y: 10, z: 10}
//如果将法向量归一化,这样一来得到的这个点正好是在平面上
var plane = new THREE.Plane(new THREE.Vector3(1,1,1).normalize(), -10);
plane.coplanarPoint(new THREE.Vector3())//返回Vector3 {x: 5.7735, y: 5.7735, z: 5.7735}
//three.js coplanarPoint源码
// normal is assumed to be normalized
return target.copy( this.normal ).multiplyScalar( - this.constant );
17. applyMatrix4( matrix: Matrix4, optionalNormalMatrix?: Matrix3 ): Plane
matrix - 要应用的四位矩阵(Matrix4)。
optionalNormalMatrix - (可选参数) 预先计算好的上述Matrix4参数的法线矩阵 Matrix3。
在平面上应用矩阵。矩阵必须是仿射齐次变换。
var plane = new THREE.Plane(new THREE.Vector3(0,1,0), -10);//返回constant: -10,normal: Vector3 {x: 0.7071067811865475, y: 0.7071067811865476, z: 0}
var matrix = new THREE.Matrix4().makeRotationZ(-Math.PI/4);
plane.applyMatrix4(matrix);//返回constant: -10,normal: Vector3 {x: 1, y: 2.220446049250313e-16, z: 0}
18. translate( offset: Vector3 ): Plane
将平面平移给定向量大小,注意:这只会影响平面的常量不会影响平面的法向量。
var plane = new THREE.Plane(new THREE.Vector3(0,1,0), -10);
plane.translate(new THREE.Vector3(0,-5,0));//将平面向下平移5个单位
19. equals( plane: Plane ): boolean
检查两个平面是否相等。(法线 normal 以及常量 constant 都相同)。很简单我们不多说。
3.使用plane
应用平面的地方有很多,我来拿WebGLRenderer的clippingPlanes属性做案例,clippingPlanes是包含Plane的数组作为剪裁平面,主要代码如下,在线案例点击博客原文。
box = new THREE.Mesh(new THREE.BoxGeometry(20,20,20), new THREE.MeshNormalMaterial({side: THREE.DoubleSide}));
plane = new THREE.Plane(new THREE.Vector3(1,1,1), 0);
planeHelper = new THREE.PlaneHelper(plane, 30);
renderer.clippingPlanes = [plane]
scene.add(planeHelper);
scene.add(box);
gui = new GUI();
params = new function() {
this.normal_x = 1;
this.normal_y = 1;
this.normal_z = 1;
this.constant = 0;
this.clipping = true;
};
gui.add(params, 'normal_x', -1, 1).onChange(() => setParams());
gui.add(params, 'normal_y', -1, 1).onChange(() => setParams());
gui.add(params, 'normal_z', -1, 1).onChange(() => setParams());
gui.add(params, 'constant', -10, 10).onChange(() => setParams());
gui.add(params, 'clipping').onChange(e => renderer.clippingPlanes = e ? [plane] : []); this.render();
document.getElementById("loading").style.display = "none"; function setParams() {
plane.set(new THREE.Vector3(params.normal_x, params.normal_y, params.normal_z), params.constant);
planeHelper = new THREE.PlaneHelper(plane, 30)
}
转载请注明地址:郭先生的博客
three.js 数学方法之Plane的更多相关文章
- three.js 数学方法之Box3
从今天开始郭先生就会说一下three.js 的一些数学方法了,像Box3.Plane.Vector3.Matrix3.Matrix4当然还有欧拉角和四元数.今天说一说three.js的Box3方法(B ...
- three.js 数学方法之Matrix3
今天郭先生来说一说three.js的三维矩阵,这块知识需要结合线性代数的一些知识,毕业时间有点长,线性代数的知识大部分都还给了老师.于是一起简单的复习了一下.所有的计算都是使用列优先顺序进行的.然而, ...
- three.js 数学方法之Vector3
今天郭先生来说一说three.js的Vector3,该类表示的是一个三维向量(3D vector). 一个三维向量表示的是一个有顺序的.三个为一组的数字组合(标记为x.y和z),可被用来表示很多事物, ...
- three.js 数学方法之Matrix4
今天郭先生说一说three.js中的Matrix4,相较于Matrix3来说,Matrix4和three.js联系的更紧密,因为在4x4矩阵最常用的用法是作为一个变换矩阵.这使得表示三维空间中的一个点 ...
- js数学方法应用
找出数组中最大的数 var values = [1, 2, 3, 4, 5, 6, 7, 8]; alert(Math.min.apply(Math,values))//8 这个技巧的关键是把 Mat ...
- js数组及常用数学方法
数组方法 清空数组 1: arr.length=0; 2: arr=[]; arr.push() //往数组最后一个添加元素,会待会一个返回值,就是新的数组长度arr.uns ...
- js数组方法大全(下)
# js数组方法大全(下) 记录一下整理的js数组方法,免得每次要找方法都找不到.图片有点多,注意流量,嘻嘻! 本期分享 forEach() map() filer() every() some() ...
- js数组方法
数组方法清空数组1: arr.length=02: arr=[]arr.push()//往数组最后一个添加元素,会待会一个返回值,就是新的数组长度arr.unshift()//往数组的第一个添加元素, ...
- js调用php和php调用js的方法举例
js调用php和php调用js的方法举例1 JS方式调用PHP文件并取得php中的值 举一个简单的例子来说明: 如在页面a.html中用下面这句调用: <script type="te ...
随机推荐
- oracle包package的使用
创建包 包头: CREATE OR REPLACE PACKAGE test_pkg IS PROCEDURE update_sal(e_name VARCHAR2,newsal NUMBER); ...
- JavaWeb网上图书商城完整项目--day02-8.提交注册表单功能之dao、service实现
1.发送邮件 发送邮件的时候的参数我们都写在了配置文件中,配置文件放在src目录下,可以使用类加载器进行加载该数据 //向注册的用户发送邮件 //1读取配置文件 Properties properti ...
- SpringMVC 学习笔记(五)
47. 尚硅谷_佟刚_SpringMVC_文件上传.avi 参看博客https://www.cnblogs.com/hanfeihanfei/p/7931758.html相当的经典 我是陌生人关于Sp ...
- redis基础二----操作set数据类型
set集合是无序的,不能存在重复元素 bbb吃重复元素,是不能添加成功的 2 接下来分析zset,是有序的,你在添加的时候要指定元素的序列号 上面的 3 4 5 6 就是指定的元素的序列号 withs ...
- Java 将PDF/XPS转为Word/html /SVG/PS/PCL/PNG、PDF和XPS互转(基于Spire.Cloud.SDK for Java)
Spire.Cloud.SDK for Java提供了接口PdfConvertApi通过convert()方法将PDF文档以及XPS文档转为指定文档格式,如转PDF为Word(支持Docx.Doc). ...
- HashMap的基本使用
常用方法 首先,我们应该知道HashMap类实现了Map接口,所以实现了Map常用的一些方法. (1) 插入键值对数据 public V put(K key, V value) (2)根据键值获取键值 ...
- No configuration file found and no output filename configured via Cli option.报错
webpack手动配置webpack.config.js文件,打包时出现的报错,可以试试这种解决方案 报错如下: No configuration file found and no output f ...
- 使用 Prometheus-Operator 监控 Calico
原文链接:https://fuckcloudnative.io/posts/monitoring-calico-with-prometheus-operator/ Calico 中最核心的组件就是 F ...
- 117.填充每个节点的下一个右侧节点指针II
# Definition for a Node.class Node: def __init__(self, val: int = 0, left: 'Node' = None, right: 'No ...
- 1年转行资深前端工程师,开源项目过 1k stars,完整学习过程
先介绍下大致情况时间线. 18 年 8 月正式转方向为前端,之前做了一段时间的 iOS,后来因为对前端更感兴趣所以就打算转方向了.19 年 10 月入职当前公司,定级资深前端,分配到业务架构小组,自此 ...