У меня есть 3D-модель в OpenGL (C ++), загруженная с использованием Assimp. Мне нужно переместить эту модель по экрану (перевести) так, как если бы она всегда была обращена к камере по осям X и Y (без оси Z). Это похоже на перемещение этой модели, как будто она только 2D (но, конечно, если я поверну ее, она также покажет ось Z).
моя функция рендеринга:
camX = CamY = 0;
camZ = 5;
lookatX = lookatY = lookatZ = 0;
void C3DModel::render(void)
{
static float step = 0.0f;
setCamera(camX, camY, camZ, lookatX, lookatY, lookatZ);
translate(-3, 1, 0); // here is the issue .
scale(scaleFactor, scaleFactor, scaleFactor);
rotate(step, 0.0f, 1.0f, 0.0f);
}
void C3DModel::translate(float x, float y, float z)
{
float aux[16];
setTranslationMatrix(aux, x, y, z);
multMatrix(modelMatrix, aux);
setModelMatrix();
}
void C3DModel::setTranslationMatrix(float *mat, float x, float y, float z)
{
setIdentityMatrix(mat, 4);
mat[12] = x;
mat[13] = y;
mat[14] = z;
}
void C3DModel::setScaleMatrix(float *mat, float sx, float sy, float sz)
{
setIdentityMatrix(mat, 4);
mat[0] = sx;
mat[5] = sy;
mat[10] = sz;
}
void C3DModel::setRotationMatrix(float *mat, float angle, float x, float y, float z)
{
float radAngle = DegToRad(angle);
float co = cos(radAngle);
float si = sin(radAngle);
float x2 = x * x;
float y2 = y * y;
float z2 = z * z;
mat[0] = x2 + (y2 + z2) * co;
mat[4] = x * y * (1 - co) - z * si;
mat[8] = x * z * (1 - co) + y * si;
mat[12] = 0.0f;
mat[1] = x * y * (1 - co) + z * si;
mat[5] = y2 + (x2 + z2) * co;
mat[9] = y * z * (1 - co) - x * si;
mat[13] = 0.0f;
mat[2] = x * z * (1 - co) - y * si;
mat[6] = y * z * (1 - co) + x * si;
mat[10] = z2 + (x2 + y2) * co;
mat[14] = 0.0f;
mat[3] = 0.0f;
mat[7] = 0.0f;
mat[11] = 0.0f;
mat[15] = 1.0f;
}
void C3DModel::rotate(float angle, float x, float y, float z)
{
float aux[16];
setRotationMatrix(aux, angle, x, y, z);
multMatrix(modelMatrix, aux);
setModelMatrix();
}
void C3DModel::scale(float x, float y, float z)
{
float aux[16];
setScaleMatrix(aux, x, y, z);
multMatrix(modelMatrix, aux);
setModelMatrix();
}
void C3DModel::setIdentityMatrix(float *mat, int size)
{
// fill matrix with 0s
for (int i = 0; i < size * size; ++i)
mat[i] = 0.0f;
// fill diagonal with 1s
for (int i = 0; i < size; ++i)
mat[i + i * size] = 1.0f;
}
void C3DModel::multMatrix(float *a, float *b)
{
float res[16];
for (int i = 0; i < 4; ++i)
{
for (int j = 0; j < 4; ++j)
{
res[j * 4 + i] = 0.0f;
for (int k = 0; k < 4; ++k)
{
res[j * 4 + i] += a[k * 4 + i] * b[j * 4 + k];
}
}
}
memcpy(a, res, 16 * sizeof(float));
}
void C3DModel::setModelMatrix()
{
glBindBuffer(GL_UNIFORM_BUFFER, matricesUniBuffer);
glBufferSubData(GL_UNIFORM_BUFFER, ModelMatrixOffset, MatrixSize, modelMatrix);
glBindBuffer(GL_UNIFORM_BUFFER, 0);
}
void C3DModel::crossProduct(float *a, float *b, float *res)
{
res[0] = a[1] * b[2] - b[1] * a[2];
res[1] = a[2] * b[0] - b[2] * a[0];
res[2] = a[0] * b[1] - b[0] * a[1];
}
// Normalize a vec3
void C3DModel::normalize(float *a)
{
float mag = sqrt(a[0] * a[0] + a[1] * a[1] + a[2] * a[2]);
a[0] /= mag;
a[1] /= mag;
a[2] /= mag;
}
void C3DModel::setCamera(float posX, float posY, float posZ, float lookAtX, float lookAtY, float lookAtZ)
{
float dir[3], right[3], up[3];
up[0] = 0.0f; up[1] = 1.0f; up[2] = 0.0f;
dir[0] = (lookAtX - posX);
dir[1] = (lookAtY - posY);
dir[2] = (lookAtZ - posZ);
normalize(dir);
crossProduct(dir, up, right);
normalize(right);
crossProduct(right, dir, up);
normalize(up);
float viewMatrix[16], aux[16];
viewMatrix[0] = right[0];
viewMatrix[4] = right[1];
viewMatrix[8] = right[2];
viewMatrix[12] = 0.0f;
viewMatrix[1] = up[0];
viewMatrix[5] = up[1];
viewMatrix[9] = up[2];
viewMatrix[13] = 0.0f;
viewMatrix[2] = -dir[0];
viewMatrix[6] = -dir[1];
viewMatrix[10] = -dir[2];
viewMatrix[14] = 0.0f;
viewMatrix[3] = 0.0f;
viewMatrix[7] = 0.0f;
viewMatrix[11] = 0.0f;
viewMatrix[15] = 1.0f;
setTranslationMatrix(aux, -posX, -posY, -posZ);
multMatrix(viewMatrix, aux);
glBindBuffer(GL_UNIFORM_BUFFER, matricesUniBuffer);
glBufferSubData(GL_UNIFORM_BUFFER, ViewMatrixOffset, MatrixSize, viewMatrix);
glBindBuffer(GL_UNIFORM_BUFFER, 0);
}