![](/img/trans.png)
[英]How to declare variables in ray-tracing object-oriented program when most of them a vectors and camera declarations?
[英]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.