源引擎风格的绳子渲染

Fel*_*nes 6 c 3d matrix opengl-es-2.0

我正在创建一个3D图形引擎,其中一个要求就是在Valve的源引擎中运行的绳索.

所以在源引擎中,一段绳子是沿其方向轴旋转的四边形,面向摄像机,所以如果绳索的一部分在+ Z方向,它将沿着Z轴旋转,所以它的面朝向相机的中心位置.

目前,我已经定义了绳索的部分,所以我可以有一条漂亮的弯曲绳索,但现在我正在尝试构建矩阵,它将沿着它的方向向量旋转它.

我已经有了一个基于这种广告牌技术渲染广告牌精灵的矩阵: 构建一个广告牌矩阵 现在我一直试图重新组合它,以便右,向上,向前矢量匹配绳段的方向向量.

我的绳子由多个部分组成,每个部分是一个由两个三角形组成的矩形,正如我上面所说,我可以得到位置和部分完美,它是面向相机的旋转,这给我带来了很多问题.

这是在OpenGL ES2中并用C语言编写的.

我在Model_beam.cpp中研究了Doom 3的光束渲染代码,其中使用的方法是基于法线而不是使用矩阵来计算偏移量,所以我在我的C代码中创建了一种类似的技术,它有点工作,至少它,就像我现在需要的那样.

所以对于那些也试图解决这个问题的人来说,使用绳索中点与相机位置的交叉积,将其标准化,然后将其乘以你想要绳索的宽度,然后在施工时顶点,在结果向量的+或 - 方向上偏移每个顶点.

进一步的帮助将是伟大的,虽然这不是完美的!

谢谢

hen*_*rso 1

查看此相关的 stackoverflow 帖子 on billboards in OpenGL 它引用了lighthouse3d教程,这是一本非常好的读物。以下是该技术的要点:

void billboardCylindricalBegin(
                float camX, float camY, float camZ,
                float objPosX, float objPosY, float objPosZ) {

        float lookAt[3],objToCamProj[3],upAux[3];
        float modelview[16],angleCosine;

        glPushMatrix();

    // objToCamProj is the vector in world coordinates from the 
    // local origin to the camera projected in the XZ plane
        objToCamProj[0] = camX - objPosX ;
        objToCamProj[1] = 0;
        objToCamProj[2] = camZ - objPosZ ;

    // This is the original lookAt vector for the object 
    // in world coordinates
        lookAt[0] = 0;
        lookAt[1] = 0;
        lookAt[2] = 1;


    // normalize both vectors to get the cosine directly afterwards
        mathsNormalize(objToCamProj);

    // easy fix to determine wether the angle is negative or positive
    // for positive angles upAux will be a vector pointing in the 
    // positive y direction, otherwise upAux will point downwards
    // effectively reversing the rotation.

        mathsCrossProduct(upAux,lookAt,objToCamProj);

    // compute the angle
        angleCosine = mathsInnerProduct(lookAt,objToCamProj);

    // perform the rotation. The if statement is used for stability reasons
    // if the lookAt and objToCamProj vectors are too close together then 
    // |angleCosine| could be bigger than 1 due to lack of precision
       if ((angleCosine < 0.99990) && (angleCosine > -0.9999))
          glRotatef(acos(angleCosine)*180/3.14,upAux[0], upAux[1], upAux[2]);   
    }
Run Code Online (Sandbox Code Playgroud)