比方说,我有两个顶点,并且我想知道两个顶点之间的3D角度。所谓3D角,是指在三个维平面中的一个顶点与另一个顶点之间的角度,存储为
{ x, y, z }
function getAngleBetweenVertices(vert1, vert2){
return {
x: 0, // ?
y: 0, // ?
z: 0 // ?
}
}
// Classes
class Vertex {
constructor(position){
this.position = {
x: 0,
y: 0,
z: 0,
...position
};
}
}
// Init
let vert1 = new Vertex({ x: 1, y: 0, z: 1 });
let vert2 = new Vertex({ x: 0, y: 1, z: 1 });
let angle = getAngleBetweenVertices(vert1, vert2);
console.log("angle ", angle);
例如,在上图中,我在连接三角形上两个顶点的线段上进行了追踪。应该可以找到x,y和z轴上两个顶点位置之间的角度。
如何计算两个顶点之间的三维角度?
答案 0 :(得分:1)
您可以在两个方向v1,v2
(向量)之间设置角度,如下所示:
ang = acos(dot(v1,v2)/(|v1|.|v2|))
将 3D 转换为:
ang = acos( (x1*x2 + y1*y2 + z1*z1) / sqrt( (x1*x1 + y1*y1 + z1*z1)*(x2*x2+y2*y2+z2*z2) ) )
但是,您不能在两点之间没有完全没有意义的角度。还要注意3D角度不是您想的那样(它的角度为球面度,您可以将其视为体积覆盖率...法线角度是面积覆盖率),是的,它也是标量值。因此,您要查找的是方向余弦或欧拉角(您需要更多信息和变换顺序以免过于雄心勃勃)或transform matrices。 / p>
但是由于我怀疑它是XY问题,并且根据您的评论,我是对的。
因此,您的实际问题(基于评论)是从(三角形)面上找到反射光线。使用角度(方向余弦,欧拉角或变换矩阵)不是一个好主意,因为那样做会非常慢。而是使用简单的矢量数学,我会这样看:
因此,您获得了射线方向dir
,并希望从具有正常dir'
的脸部反射nor
,所以:
dir' = 2 * ( nor*dot(-dir,nor) + dir ) - dir
dir' = 2 * ( -nor*dot(dir,nor) + dir ) - dir
dir' = -2*nor*dot(dir,nor) + 2*dir - dir
dir' = -2*nor*dot(dir,nor) + dir
dir' = dir-2*nor*dot(dir,nor)
所以在 3D 中是:
dir=(dx,dy,dz)
nor=(nx,ny,nz)
t = 2*(dx*nx + dy*ny + dz*nz) // 2*dot(dir,nor)
dx' = dx-t*nx
dy' = dy-t*ny
dz' = dz-t*nz
正如您所见,根本不需要角度测量法或角度... dot
的法向点是否在人脸/物体中也无关紧要...
如果需要法线,则可以通过其2边的叉积来计算,因此,如果三角形由v0,v1,v2
点定义,则:
nor = cross( v1-v0 , v2-v1 )
在此示例中,我将这种技术用于raytracer:
它的我的 GLSL 射线跟踪器支持三角形面上的反射,并且其中没有测角法...在片段着色器中寻找// reflect
评论,尤其是寻找:
ray[rays].dir=ray[rays].dir-(2.0*t*ray[rays].nor);
将其反射到
t=dot(ray[i0].dir,ray[i0].nor);
其中dir
是射线方向,nor
是面法线(看起来很熟悉?是的,它是相同的方程式)...
答案 1 :(得分:0)
我不确定这段代码是否正确,但是我认为它是我想要的。
// Utilities
function normalizeAngle(angle){
if (angle > 360) return angle - 360;
if (angle < 0) return 360 + angle;
else return angle;
}
function getAngleBetweenPoints(cx, cy, ex, ey){
var dy = ey - cy;
var dx = ex - cx;
var theta = Math.atan2(dy, dx);
theta *= 180 / Math.PI;
return theta;
}
function getAngleBetweenVertices(vert1, vert2){
return {
x: normalizeAngle(getAngleBetweenPoints(vert1.position.z,
vert1.position.x, vert2.position.z, vert2.position.x)),
y: normalizeAngle(getAngleBetweenPoints(vert1.position.z,
vert1.position.y, vert2.position.z, vert2.position.y)),
z: normalizeAngle(getAngleBetweenPoints(vert1.position.x,
vert1.position.y, vert2.position.x, vert2.position.y))
}
}
// Classes
class Vertex {
constructor(position){
this.position = {
x: 0,
y: 0,
z: 0,
...position
};
}
}
// Init
let vert1 = new Vertex({ x: 1, y: 0, z: 1 });
let vert2 = new Vertex({ x: 0, y: 1, z: 1 });
let angle = getAngleBetweenVertices(vert1, vert2);
console.log("angle ", angle);