繁体   English   中英

粒子未对准相机

[英]Particles not oriented to the camera

我有一个非常简单的粒子系统,它在屏幕上显示粒子并围绕 X、Y 和 Z 轴移动它们。 问题是粒子并不总是朝向相机。

glRotatef(g_fX, 1.0f, 1.0f, 1.0f);                                      
glEnable(GL_BLEND);                                                          
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_TEXTURE_2D);
glDisable(GL_DEPTH_TEST);
glBindTexture(GL_TEXTURE_2D, texCircle);

glColor3f (1.0f, 0.0f, 0.0f);

for (x = -1; x <= 1; x += 0.25)
{
    for (y = -1; y <= 1; y += 0.25)
    {
        for (z = -1; z <= 1; z += 0.25)
        {
            glBegin(GL_TRIANGLE_STRIP);                                    
            glTexCoord2d(1,1); glVertex3f(x+0.5f,y+0.5f,z);
            glTexCoord2d(0,1); glVertex3f(x-0.5f,y+0.5f,z);
            glTexCoord2d(1,0); glVertex3f(x+0.5f,y-0.5f,z);
            glTexCoord2d(0,0); glVertex3f(x-0.5f,y-0.5f,z);
            glEnd();
        }
    }
}      

glEnable(GL_DEPTH_TEST);  
glDisable(GL_BLEND);  

我应该在代码中更改什么?

您必须在与视口正交的平面中绘制粒子。 该平面由当前逆模型视图矩阵的 X 轴和 Y 轴给出。
矩形的角点应该像下面的伪代码一样计算:

X = X-Axis of the inverse modelview matrix
Y = Y-Axis of the inverse modelview matrix

TL = (x, y, z) - 0.5 * X + 0.5 * Y
TR = (x, y, z) + 0.5 * X + 0.5 * Y
BL = (x, y, z) - 0.5 * X - 0.5 * Y
BR = (x, y, z) + 0.5 * X - 0.5 * Y

请注意,转换矩阵通常如下所示:

( X-axis.x, X-axis.y, X-axis.z, 0 )
( Y-axis.x, Y-axis.y, Y-axis.z, 0 )
( Z-axis.x, Z-axis.y, Z-axis.z, 0 )
( trans.x,  trans.y,  trans.z,  1 )

您应该使用像glm 这样的库来计算矩阵,但如果您到目前为止还没有使用过,您还可以使用glGetFloatv(GL_MODELVIEW_MATRIX, ptr)读取当前的模型视图矩阵(请参阅如何在 OpenGL 中获取模型视图和投影矩阵? )。
要在与您必须绘制的视口正交的平面中绘制,矩形与逆视图矩阵的轴对齐(请参阅Inverse matrix )。 我使用glm::inverse来计算逆视图矩阵,但任何其他库也适用。 另请参阅 Stackoverflow question inverting a 4x4 matrix的答案。

void InverseMat44( const GLfloat m[], GLfloat im[] )
{
    // here you can put in a function, of any other library , which calculates a inverse 4*4 matrix.
    glm::mat4 glm_m = glm::make_mat4(m);
    glm::mat4 glm_im = glm::inverse(glm_m);
    memcpy( im, glm::value_ptr( glm_im ), 16 * sizeof( GLfloat ) );
}

GLfloat vm[16], ivm[16];
glGetFloatv(GL_MODELVIEW_MATRIX, vm );
InverseMat44( vm, ivm );

如果缩放视图矩阵,则必须对轴向量进行归一化,或者必须考虑四边形边长中的比例因子:

GLfloat scaleX = sqrt( ivm[0]*ivm[0] + ivm[1]*ivm[1] + ivm[2]*ivm[2] );
GLfloat scaleY = sqrt( ivm[4]*ivm[4] + ivm[5]*ivm[5] + ivm[6]*ivm[6] );

GLfloat lenX = 0.5f, lenY = 0.5f;
lenX = lenX / scaleX;
lenY = lenY / scaleY;

矩形的绘制应该看起来像这样:

GLfloat xx = ivm[0] * lenX, xy = ivm[1] * lenX, xz = ivm[2] * lenX;
GLfloat yx = ivm[4] * lenY, yy = ivm[5] * lenY, yz = ivm[6] * lenY;

glBegin(GL_TRIANGLE_STRIP);                                    

glTexCoord2d(1,1); glVertex3f( x + xx + yx, y + xy + yy, z + xz + yz );
glTexCoord2d(0,1); glVertex3f( x - xx + yx, y - xy + yy, z - xz + yz );
glTexCoord2d(1,0); glVertex3f( x + xx - yx, y + xy - yy, z + xz - yz );
glTexCoord2d(0,0); glVertex3f( x - xx - yx, y - xy - yy, z - xz - yz );

glEnd();


另请参阅以下问题的答案:

使用模型视图矩阵的解决方案

但更优雅的解决方案是使用模型视图矩阵来实现广告牌效果。 为此,您首先必须将平移应用于模型矩阵而不是网格,然后您必须将反向视图旋转应用于模型矩阵:

GLfloat scaleX = sqrt( ivm[0]*ivm[0] + ivm[1]*ivm[1] + ivm[2]*ivm[2] );
GLfloat scaleY = sqrt( ivm[4]*ivm[4] + ivm[5]*ivm[5] + ivm[6]*ivm[6] );
GLfloat scaleZ = sqrt( ivm[8]*ivm[8] + ivm[9]*ivm[9] + ivm[10]*ivm[10] );

GLfloat len = 0.5f;
for (x = -1; x <= 1; x += 0.25)
{
    for (y = -1; y <= 1; y += 0.25)
    {
        for (z = -1; z <= 1; z += 0.25)
        {
            GLfloat rm[16] = {
                ivm[0]/scaleX, ivm[1]/scaleX, ivm[2]/scaleX,  0.0f,
                ivm[4]/scaleY, ivm[5]/scaleY, ivm[6]/scaleY,  0.0f,
                ivm[8]/scaleZ, ivm[9]/scaleZ, ivm[10]/scaleZ, 0.0f,
                0.0f,          0.0f,          0.0f,           1.0f
            };

            glPushMatrix();
            glTranslated( x, y, z );
            glMultMatrixf( rm );

            glBegin(GL_TRIANGLE_STRIP);                                    
            glTexCoord2d(1,1); glVertex3f(  len,  len, 0.0f );
            glTexCoord2d(0,1); glVertex3f( -len,  len, 0.0f );
            glTexCoord2d(1,0); glVertex3f(  len, -len, 0.0f );
            glTexCoord2d(0,0); glVertex3f( -len, -len, 0.0f );
            glEnd();

            glPopMatrix();
        }
    }
}

请注意,对于任何解决方案,您都必须知道当前模型视图矩阵,并且必须计算逆模型视图矩阵。

用于计算逆矩阵的替代函数如下所示(参见反转 4x4 矩阵):

bool InverseMat44( const GLfloat m[16], GLfloat invOut[16] )
{
    float inv[16], det;
    int i;

    inv[0]  =  m[5] * m[10] * m[15] - m[5] * m[11] * m[14] - m[9] * m[6] * m[15] + m[9] * m[7] * m[14] + m[13] * m[6] * m[11] - m[13] * m[7] * m[10];
    inv[4]  = -m[4] * m[10] * m[15] + m[4] * m[11] * m[14] + m[8] * m[6] * m[15] - m[8] * m[7] * m[14] - m[12] * m[6] * m[11] + m[12] * m[7] * m[10];
    inv[8]  =  m[4] * m[9]  * m[15] - m[4] * m[11] * m[13] - m[8] * m[5] * m[15] + m[8] * m[7] * m[13] + m[12] * m[5] * m[11] - m[12] * m[7] * m[9];
    inv[12] = -m[4] * m[9]  * m[14] + m[4] * m[10] * m[13] + m[8] * m[5] * m[14] - m[8] * m[6] * m[13] - m[12] * m[5] * m[10] + m[12] * m[6] * m[9];
    inv[1]  = -m[1] * m[10] * m[15] + m[1] * m[11] * m[14] + m[9] * m[2] * m[15] - m[9] * m[3] * m[14] - m[13] * m[2] * m[11] + m[13] * m[3] * m[10];
    inv[5]  =  m[0] * m[10] * m[15] - m[0] * m[11] * m[14] - m[8] * m[2] * m[15] + m[8] * m[3] * m[14] + m[12] * m[2] * m[11] - m[12] * m[3] * m[10];
    inv[9]  = -m[0] * m[9]  * m[15] + m[0] * m[11] * m[13] + m[8] * m[1] * m[15] - m[8] * m[3] * m[13] - m[12] * m[1] * m[11] + m[12] * m[3] * m[9];
    inv[13] =  m[0] * m[9]  * m[14] - m[0] * m[10] * m[13] - m[8] * m[1] * m[14] + m[8] * m[2] * m[13] + m[12] * m[1] * m[10] - m[12] * m[2] * m[9];
    inv[2]  =  m[1] * m[6]  * m[15] - m[1] * m[7]  * m[14] - m[5] * m[2] * m[15] + m[5] * m[3] * m[14] + m[13] * m[2] * m[7]  - m[13] * m[3] * m[6];
    inv[6]  = -m[0] * m[6]  * m[15] + m[0] * m[7]  * m[14] + m[4] * m[2] * m[15] - m[4] * m[3] * m[14] - m[12] * m[2] * m[7]  + m[12] * m[3] * m[6];
    inv[10] =  m[0] * m[5]  * m[15] - m[0] * m[7]  * m[13] - m[4] * m[1] * m[15] + m[4] * m[3] * m[13] + m[12] * m[1] * m[7]  - m[12] * m[3] * m[5];
    inv[14] = -m[0] * m[5]  * m[14] + m[0] * m[6]  * m[13] + m[4] * m[1] * m[14] - m[4] * m[2] * m[13] - m[12] * m[1] * m[6]  + m[12] * m[2] * m[5];
    inv[3]  = -m[1] * m[6]  * m[11] + m[1] * m[7]  * m[10] + m[5] * m[2] * m[11] - m[5] * m[3] * m[10] - m[9]  * m[2] * m[7]  + m[9]  * m[3] * m[6];
    inv[7]  =  m[0] * m[6]  * m[11] - m[0] * m[7]  * m[10] - m[4] * m[2] * m[11] + m[4] * m[3] * m[10] + m[8]  * m[2] * m[7]  - m[8]  * m[3] * m[6];
    inv[11] = -m[0] * m[5]  * m[11] + m[0] * m[7]  * m[9]  + m[4] * m[1] * m[11] - m[4] * m[3] * m[9]  - m[8]  * m[1] * m[7]  + m[8]  * m[3] * m[5];
    inv[15] =  m[0] * m[5]  * m[10] - m[0] * m[6]  * m[9]  - m[4] * m[1] * m[10] + m[4] * m[2] * m[9]  + m[8]  * m[1] * m[6]  - m[8]  * m[2] * m[5];

    det = m[0] * inv[0] + m[1] * inv[4] + m[2] * inv[8] + m[3] * inv[12];
    if (det == 0) return false;
    det = 1.0 / det;

    for (i = 0; i < 16; i++)
        invOut[i] = inv[i] * det;

    return true;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM