2016-05-05 37 views
1

我想在opengl中渲染3d激光束。我有两个点(p1,p2)和一个由p1和p2之间的距离缩放的三面圆柱体。问题是我无法让气缸正确旋转。我尝试过使用atan2来计算三轴角度并将它们应用到矩阵中,到目前为止没有成功。圆柱体根本没有遵循这些点。这就是我如何完成旋转计算:Opengl 3d激光束

p3 = p2 - p1 
rotX = atan2(p3.y, p3.z) 
rotY = atan2(p3.x, p3.z) 
rotZ = atan2(p3.x, p3.y) 

matrix.rotate(rotX, rotY, rotZ) 
+1

使用四元数并将其转换为旋转矩阵 –

+0

@willywonka_dailyblah:这没有帮助。问题是角度的选择。使用四元数是获得相同答案的另一种技术。 –

回答

1

这是线性代数稍微长一点的情况之一。你根本不需要三角函数。三角函数全是关于角度的,你正在做的是将直角坐标转换成角度,然后再转换成直角坐标。这两次转换是不必要的。

我们来定义v = p2-p1。假设你的圆柱沿Z轴从(0,0,0)到(0,0,1)。我们正努力创造一个矩阵A为我们提供了如下改造:

A * (0, 0, 1) = v 

那么,一旦你写出来这样的,它看起来非常简单,不是吗!因为通过基向量右乘矩阵给我们一个列向量。所以v必须是矩阵的其中一列。

A = [ ? ? v.x ] 
    [ ? ? v.y ] 
    [ ? ? v.z ] 

现在我们只选择那些被归一化和正交至v另外两个列向量,所以我们保持激光器的横截面形状。这很简单。下面是一些代码,因为它将用GLSL编写(你可以在C++中使用glm或在JavaScript中使用gl-matrix来获得类似的语法)。

mat3 create_laser_matrix(vec3 v) { 
    // Find a vector, ref, not parallel to v 
    vec3 vmag = abs(v); 
    vec3 ref; 
    if (vmag.x <= vmag.y && vmag.x <= vmag.z) { 
     ref = vec3(1.0, 0.0, 0.0); 
    } else if (vmag.y <= vmag.z) { 
     ref = vec3(0.0, 1.0, 0.0); 
    } else { 
     ref = vec3(0.0, 0.0, 1.0); 
    } 
    // Use ref to create two unit vectors, u1, u2, so {v, u1, u2} are orthogonal 
    vec3 utemp = cross(v, ref); 
    vec3 u1 = normalize(cross(v, utemp)); 
    vec3 u2 = normalize(cross(v, u1)); 
    return mat3(u1, u2, v); 
} 

为了扩大对数学:三角允许我们的角度和直角坐标和反之亦然之间进行转换,但事实证明,我们并不需要这样做的。一个“旋转矩阵”只是一种正交矩阵(一个具有行列式1而不是-1),正交矩阵就是列向量正交的矩阵,这就意味着任意两列的点积向量是零。没有三角法需要。我们并不完全在正交矩阵之后,因为我们需要“伸出”激光来连接两个点,但大部分相同的数学运算也适用。