[help] problem with camera lib
Hi, Mac developers!
I write camera in OpenGL for my game engine, I implement rotation matrix, but I can not see why after rotation camera begin to move in global Z axis (not local z axis)? So we look at local z, but move to global z
I write camera in OpenGL for my game engine, I implement rotation matrix, but I can not see why after rotation camera begin to move in global Z axis (not local z axis)? So we look at local z, but move to global z

Code:
#define M_PI2 M_PI / 2.0
enum event_t {
mLEFT,
mRIGHT,
mFORWARD,
mBACK,
mUP,
mDOWN,
LEFT,
RIGHT,
UP,
DOWN
};
typedef struct {
float x, y, z;
} vec3_t;
typedef struct {
vec3_t eye; // global camera location
vec3_t euler; // global euler angles
vec3_t c_eye; // current delta camera coordinates
vec3_t c_euler; // current delta euler angles
} FLCamera;
#include <OpenGL/OpenGL.h>
#include <stdlib.h>
#include <math.h>
#include "libCamera.h"
FLCamera *newCamera(void)
{
return malloc(sizeof(FLCamera));
}
void initCamera(FLCamera *theCamera,
vec3_t thePos,
vec3_t theEuler)
{
theCamera->eye = thePos;
theCamera->euler = theEuler;
}
void useCamera(FLCamera *theCamera)
{
GLfloat m[16] = {0.0}; // opengl matrix
GLfloat n[16] = {0.0}; // global matrix
GLfloat f[16] = {0.0}; // current matrix
vec3_t null = {0.0, 0.0, 0.0};
GLfloat _x, _y, _z;
/*
/////////////////////////////////////////////////
calculate global matrix
/////////////////////////////////////////////////
*/
GLfloat sinx = sinf(theCamera->euler.x);
GLfloat siny = sinf(theCamera->euler.y);
GLfloat sinz = sinf(theCamera->euler.z);
GLfloat cosx = cosf(theCamera->euler.x);
GLfloat cosy = cosf(theCamera->euler.y);
GLfloat cosz = cosf(theCamera->euler.z);
n[0] = cosy * cosz; n[4] = - cosy * sinz; n[8] = siny;
n[1] = sinx * siny * cosz + cosx * sinz; n[5] = cosx * cosz - sinx * siny * sinz; n[9] = - sinx * cosy;
n[2] = sinx * sinz - cosx * siny * cosz; n[6] = sinx * cosz + cosx * siny * sinz; n[10] = cosx * cosy;
/*
/////////////////////////////////////////////////
calculate current matrix
/////////////////////////////////////////////////
*/
sinx = sinf(theCamera->c_euler.x);
siny = sinf(theCamera->c_euler.y);
sinz = sinf(theCamera->c_euler.z);
cosx = cosf(theCamera->c_euler.x);
cosy = cosf(theCamera->c_euler.y);
cosz = cosf(theCamera->c_euler.z);
f[0] = cosy * cosz; f[4] = - cosy * sinz; f[8] = siny;
f[1] = sinx * siny * cosz + cosx * sinz; f[5] = cosx * cosz - sinx * siny * sinz; f[9] = - sinx * cosy;
f[2] = sinx * sinz - cosx * siny * cosz; f[6] = sinx * cosz + cosx * siny * sinz; f[10] = cosx * cosy;
/*
/////////////////////////////////////////////////
calculate opengl matrix
/////////////////////////////////////////////////
*/
m[0] = n[0] * f[0] + n[4] * f[1] + n[8] * f[2];
m[1] = n[1] * f[0] + n[5] * f[1] + n[9] * f[2];
m[2] = n[2] * f[0] + n[6] * f[1] + n[10] * f[2];
m[4] = n[0] * f[4] + n[4] * f[5] + n[8] * f[6];
m[5] = n[1] * f[4] + n[5] * f[5] + n[9] * f[6];
m[6] = n[2] * f[4] + n[6] * f[5] + n[10] * f[6];
m[8] = n[0] * f[8] + n[4] * f[9] + n[8] * f[10];
m[9] = n[1] * f[8] + n[5] * f[9] + n[9] * f[10];
m[10] = n[2] * f[8] + n[6] * f[9] + n[10] * f[10];
_x = theCamera->eye.x += (theCamera->c_eye.x * (m[0] + m[4] + m[8]));
_y = theCamera->eye.y += (theCamera->c_eye.y * (m[1] + m[5] + m[9]));
_z = theCamera->eye.z += (theCamera->c_eye.z * (m[2] + m[6] + m[10]));
m[12] = - (_x * m[0] + _y * m[4] + _z * m[8]);
m[13] = - (_x * m[1] + _y * m[5] + _z * m[9]);
m[14] = - (_x * m[2] + _y * m[6] + _z * m[10]);
m[15] = 1.0;
glLoadMatrixf(m);
theCamera->c_eye = null;
theCamera->c_euler = null;
theCamera->euler = extractEuler(m, NULL);
}
vec3_t extractEuler(float m[16], vec3_t *euler)
{
vec3_t theta;
theta.y = asinf(m[8]);
if (theta.y < M_PI2) {
if (theta.y > - M_PI2) {
theta.x = atan2f(- m[9], m[10]);
theta.z = atan2f(- m[4], m[0]);
}
else {
theta.x = - atan2f(m[4], m[5]);
theta.z = 0.0;
}
}
else {
theta.x = atan2f(m[4], m[5]);
theta.z = 0.0;
}
return theta;
}
void moveCameraLeft(FLCamera *theCamera, float vel)
{
theCamera->c_eye.x -= vel;
}
void moveCameraRight(FLCamera *theCamera, float vel)
{
theCamera->c_eye.x += vel;
}
void moveCameraUp(FLCamera *theCamera, float vel)
{
theCamera->c_eye.y -= vel;
}
void moveCameraDown(FLCamera *theCamera, float vel)
{
theCamera->c_eye.y += vel;
}
void moveCameraForward(FLCamera *theCamera, float vel)
{
theCamera->c_eye.z -= vel;
}
void moveCameraBack(FLCamera *theCamera, float vel)
{
theCamera->c_eye.z += vel;
}
void rotCameraLeft(FLCamera *theCamera, float angle)
{
theCamera->c_euler.y -= angle;
}
void rotCameraRight(FLCamera *theCamera, float angle)
{
theCamera->c_euler.y += angle;
}
void rotCameraUp(FLCamera *theCamera, float angle)
{
theCamera->c_euler.x -= angle;
}
void rotCameraDown(FLCamera *theCamera, float angle)
{
theCamera->c_euler.x += angle;
}
void deleteCamera(FLCamera *theCamera)
{
free(theCamera);
}
I see some issues (or at least potential issues) with your code, but regarding your specific question, this:
Doesn't look correct to me. It looks like the objective here is to transform c_eye from local space to world space, but unless I'm missing something, you're not performing a full matrix-vector multiplication here. It seems to me that each of these lines of code should perform a full dot product, e.g.:
And similarly for the other two lines.
I'd also recommend factoring out common mathematical operations such as the dot product, matrix multiplication, and so on, and making them separate functions (doing so will make your code easier to write, read, and debug). It also looks like you may be performing some Euler-angle conversions that aren't necessary; eliminating any such conversions would help simplify your code.
Code:
_x = theCamera->eye.x += (theCamera->c_eye.x * (m[0] + m[4] + m[8]));
_y = theCamera->eye.y += (theCamera->c_eye.y * (m[1] + m[5] + m[9]));
_z = theCamera->eye.z += (theCamera->c_eye.z * (m[2] + m[6] + m[10]));Doesn't look correct to me. It looks like the objective here is to transform c_eye from local space to world space, but unless I'm missing something, you're not performing a full matrix-vector multiplication here. It seems to me that each of these lines of code should perform a full dot product, e.g.:
Code:
_x = theCamera->eye.x += (
theCamera->c_eye.x * m[0] +
theCamera->c_eye.y * m[4] +
theCamera->c_eye.z * m[8]
);And similarly for the other two lines.
I'd also recommend factoring out common mathematical operations such as the dot product, matrix multiplication, and so on, and making them separate functions (doing so will make your code easier to write, read, and debug). It also looks like you may be performing some Euler-angle conversions that aren't necessary; eliminating any such conversions would help simplify your code.
_jyk_,
thank you for your answer
that would be look like:
but it is just short; maybe my way is incorrect, I think, but there are no examples how to implement camera based on Euler;
by the way I prefer to compute complex matrix because it faster than "true" math function in general case;
ThemsAllTook,
thank you for link
thank you for your answer
that would be look like:
Code:
// move left / right
_x = theCamera->eye.x += theCamera->c_eye.x * m[0]; // right vector
_y = theCamera->eye.y += theCamera->c_eye.y * m[1];
_z = theCamera->eye.z += theCamera->c_eye.z * m[2];
// move up / down
_x = theCamera->eye.x += theCamera->c_eye.x * m[4]; // up vector
_y = theCamera->eye.y += theCamera->c_eye.y * m[5];
_z = theCamera->eye.z += theCamera->c_eye.z * m[6];
// move forward / back
_x = theCamera->eye.x += theCamera->c_eye.x * m[8]; // forward vector
_y = theCamera->eye.y += theCamera->c_eye.y * m[9];
_z = theCamera->eye.z += theCamera->c_eye.z * m[10];but it is just short; maybe my way is incorrect, I think, but there are no examples how to implement camera based on Euler;
by the way I prefer to compute complex matrix because it faster than "true" math function in general case;
ThemsAllTook,
thank you for link

