Constant in separate namespace using class/struct with a big constuctor - c++

I have a struct:
struct ColorspaceData
{
private:
glm::vec3 sMatrix;
public:
/// X red
float xr;
/// Y red
float yr;
/// Z red
float zr;
/// X green
float xg;
/// Y green
float yg;
/// Z green
float zg;
/// X blue
float xb;
/// y blue
float yb;
/// Z blue
float zb;
/// Whitepoint
WhitepointData *whitepoint;
/// A [3x3] matrix used in linear-gamma transformation function
glm::mat3 linearTransform;
/// Result of linear-gamma transformation function as `LinearTransformData`
TransformData *linearTransformData;
ColorspaceData(float c_xr, float c_yr, float c_xg, float c_yg, float c_xb, float c_yb,
StdIlluminant c_whitepoint, TransformData c_linearTransformData)
{
xr = c_xr / c_yr;
xg = c_xg / c_yg;
xb = c_xb / c_yb;
yr = 1.0f;
yg = 1.0f;
yb = 1.0f;
zr = (1.0f - c_xr - c_yr) / c_yr;
zg = (1.0f - c_xg - c_yg) / c_yg;
zb = (1.0f - c_xb - c_yb) / c_yb;
switch (c_whitepoint)
{
case (StdIlluminant::A):
whitepoint = new WhitepointData(0.44757f, 0.40745f);
break;
case (StdIlluminant::B):
whitepoint = new WhitepointData(0.34842f, 0.35161f);
break;
case (StdIlluminant::C):
whitepoint = new WhitepointData(0.31006f, 0.31616f);
break;
case (StdIlluminant::D50):
whitepoint = new WhitepointData(0.34567f, 0.35850f);
break;
case (StdIlluminant::D55):
whitepoint = new WhitepointData(0.33242f, 0.34743f);
break;
case (StdIlluminant::D65):
whitepoint = new WhitepointData(0.31271f, 0.32902f);
break;
case (StdIlluminant::D75):
whitepoint = new WhitepointData(0.29902f, 0.31485f);
break;
case (StdIlluminant::D93):
whitepoint = new WhitepointData(0.28315f, 0.29711f);
break;
case (StdIlluminant::E):
whitepoint = new WhitepointData(0.33333f, 0.33333f);
break;
case (StdIlluminant::F1):
whitepoint = new WhitepointData(0.31310f, 0.33727f);
break;
case (StdIlluminant::F2):
whitepoint = new WhitepointData(0.37208f, 0.37529f);
break;
case (StdIlluminant::F3):
whitepoint = new WhitepointData(0.40910f, 0.39430f);
break;
case (StdIlluminant::F4):
whitepoint = new WhitepointData(0.44018f, 0.40329f);
break;
case (StdIlluminant::F5):
whitepoint = new WhitepointData(0.31379f, 0.34531f);
break;
case (StdIlluminant::F6):
whitepoint = new WhitepointData(0.37790f, 0.38835f);
break;
case (StdIlluminant::F7):
whitepoint = new WhitepointData(0.31292f, 0.32933f);
break;
case (StdIlluminant::F8):
whitepoint = new WhitepointData(0.34588f, 0.35875f);
break;
case (StdIlluminant::F9):
whitepoint = new WhitepointData(0.37417f, 0.37281f);
break;
case (StdIlluminant::F10):
whitepoint = new WhitepointData(0.34609f, 0.35986f);
break;
case (StdIlluminant::F11):
whitepoint = new WhitepointData(0.38052f, 0.37713f);
break;
case (StdIlluminant::F12):
whitepoint = new WhitepointData(0.43695f, 0.40441f);
break;
case (StdIlluminant::LEDB1):
whitepoint = new WhitepointData(0.4560f, 0.4078f);
break;
case (StdIlluminant::LEDB2):
whitepoint = new WhitepointData(0.4357f, 0.4012f);
break;
case (StdIlluminant::LEDB3):
whitepoint = new WhitepointData(0.3756f, 0.3723f);
break;
case (StdIlluminant::LEDB4):
whitepoint = new WhitepointData(0.3422f, 0.3502f);
break;
case (StdIlluminant::LEDB5):
whitepoint = new WhitepointData(0.3118f, 0.3236f);
break;
case (StdIlluminant::LEDBH1):
whitepoint = new WhitepointData(0.4474f, 0.4066f);
break;
case (StdIlluminant::LEDRGB1):
whitepoint = new WhitepointData(0.4557f, 0.4211f);
break;
case (StdIlluminant::LEDV1):
whitepoint = new WhitepointData(0.4560f, 0.4548f);
break;
case (StdIlluminant::LEDV2):
whitepoint = new WhitepointData(0.3781f, 0.3775f);
break;
case (StdIlluminant::Theatre):
whitepoint = new WhitepointData(0.3141f, 0.351f);
break;
default:
throw new ColorException("Undefined whitepoint value");
}
sMatrix = glm::vec3(whitepoint->x, whitepoint->y, whitepoint->z) * glm::inverse(glm::mat3x3(xr, xg, xb, yr, yg,
yb, zr, zg, zb));
linearTransform = glm::mat3(sMatrix[0] * xr, sMatrix[1] * xg, sMatrix[2] * xb,
sMatrix[0] * yr, sMatrix[1] * yg, sMatrix[2] * yb,
sMatrix[0] * zr, sMatrix[1] * zg, sMatrix[2] * zb);
linearTransformData = &c_linearTransformData;
}
};
I need to declare CT variable. It works with #define:
#define ColorspaceDefaultSRGB ColorspaceData(0.64f, 0.33f, 0.3f, 0.6f, 0.15f, 0.06f, StdIlluminant::D65, TransformData(1.055f, 0.0031308f, 12.0f / 5.0f, 12.92f, 0.04045f))
But describing constexpr constructor is too many code duplicate like this (I've got an explanation in my previous question):
constexpr ColorspaceData(float p_xr, float p_yr): xr(p_xr), yr(p_yr) ... (other constructor code) {};
Need to describe all lines twice? Declaring a function for constructor? What is the best way to do that?

I suggest a constexpr init method if you can't make the whole constructor constexpr containing all the code that should be duplicated. Note that if a function is constexpr you can call it even if in that case a non constexpr would work too.
constexpr void init(...){
//a lot of stuff
}
ColorspaceData(...){
init(...)
//not constexpr stuff
}
constexpr ColorspaceData(...){
init(...)
//constexpr stuff
}

Related

How to fix std::shift_right not functioning properly with 2 element std::vector

I am currently working on a Snake game, everything functions as it should except the vector containing the snake body positions. The head of the snake should be the only initial element and after an apple has been eaten a new body part is added along with a trailing tail.
To move the snake body positions so it looks like they are part of the snake I use std::shift_right which works very well except for the first body part added. When the first part is added it is always inside the head/front of the vector. This makes it look like the snake has no growth/parts that follow.
As soon as the second apple is eaten the snake gets a 'tail'. The snake_body vector has now 3 elements while visually only having 2 on the game screen.
One apple has been eaten (snake_body is 2 long) but no tail
Two apples have been eaten (snake_body is 3 long) but has 1 part following instead of 2
How do I fix this?
(Thankyou in advance)
Related sample code:
std::vector <SDL_Point> snake_body = { SDL_Point(_PLAYER_START_POS) };
void Player::Movement()
{
switch (active_valid_input)
{
case SDLK_UP:
snake_body.front() = snake_body.front() + _MOVEMENT_UP;
break;
case SDLK_DOWN:
snake_body.front() = snake_body.front() + _MOVEMENT_DOWN;
break;
case SDLK_RIGHT:
snake_body.front() = snake_body.front() + _MOVEMENT_RIGHT;
break;
case SDLK_LEFT:
snake_body.front() = snake_body.front() + _MOVEMENT_LEFT;
break;
default:
break;
}
std::shift_right(snake_body.begin(), snake_body.end(), 1);
}
void Player::AddSnakePart() noexcept{
snake_body.push_back(snake_body.back());
}
You need to break up your movement, such that the shift happens between calculating the next head position, and assigning that position to head. At the moment your movement function leaves the head part in a moved-from state.
void Player::Movement()
{
SDL_Point next_head;
switch (active_valid_input)
{
case SDLK_UP:
next_head = snake_body.front() + _MOVEMENT_UP;
break;
case SDLK_DOWN:
next_head = snake_body.front() + _MOVEMENT_DOWN;
break;
case SDLK_RIGHT:
next_head = snake_body.front() + _MOVEMENT_RIGHT;
break;
case SDLK_LEFT:
next_head = snake_body.front() + _MOVEMENT_LEFT;
break;
default:
break;
}
std::shift_right(snake_body.begin(), snake_body.end(), 1);
snake_body.front() = next_head;
}
Aside: I would extract that switch into a function:
SDL_Point Player::Direction()
{
switch (active_valid_input)
{
case SDLK_UP: return _MOVEMENT_UP;
case SDLK_DOWN: return _MOVEMENT_DOWN;
case SDLK_RIGHT: return _MOVEMENT_RIGHT;
case SDLK_LEFT: return _MOVEMENT_LEFT;
}
}
void Player::Movement()
{
SDL_Point next_head = snake_body.front() + Direction();
std::shift_right(snake_body.begin(), snake_body.end(), 1);
snake_body.front() = next_head;
}
The issue was a simple matter of when I actually shifted the snake_body vector, I moved the std::shift_right before I applied the change to the front() position, it now functions properly.

Why won't this audio envelope progress through the cases of a switch?

I am working on modifying a simple audio envelope posted here. The posted version runs simple exponential attack, decay, sustain, and release cases of a switch and progresses through the envelope based on expected sample length duration of each phase.
I require more complex and individualized equations for each case. I could calculate the predicted length of each case based on my equations and maintain this time-based methodology. However, I was thinking it would be easier to control the progress through the cases based on amplitude cutoffs. ie. If level >= 1.0, move from attack case to decay case .
But I am having trouble making this work or figuring out why it won't.
Here is the pertinent original code:
enum EnvelopeStage {
ENVELOPE_STAGE_OFF = 0,
ENVELOPE_STAGE_ATTACK,
ENVELOPE_STAGE_DECAY,
ENVELOPE_STAGE_SUSTAIN,
ENVELOPE_STAGE_RELEASE,
kNumEnvelopeStages
};
double EnvelopeGenerator::nextSample() {
if (currentStage != ENVELOPE_STAGE_OFF &&
currentStage != ENVELOPE_STAGE_SUSTAIN) {
if (currentSampleIndex == nextStageSampleIndex) {
EnvelopeStage newStage = static_cast<EnvelopeStage>(
(currentStage + 1) % kNumEnvelopeStages
);
enterStage(newStage);
}
currentLevel *= multiplier;
currentSampleIndex++;
}
return currentLevel;
}
void EnvelopeGenerator::calculateMultiplier(double startLevel,
double endLevel,
unsigned long long lengthInSamples) {
multiplier = 1.0 + (log(endLevel) - log(startLevel)) / (lengthInSamples);
}
void EnvelopeGenerator::enterStage(EnvelopeStage newStage) {
currentStage = newStage;
currentSampleIndex = 0;
if (currentStage == ENVELOPE_STAGE_OFF ||
currentStage == ENVELOPE_STAGE_SUSTAIN) {
nextStageSampleIndex = 0;
} else {
nextStageSampleIndex = stageValue[currentStage] * sampleRate;
}
switch (newStage) {
case ENVELOPE_STAGE_OFF:
currentLevel = 0.0;
multiplier = 1.0;
break;
case ENVELOPE_STAGE_ATTACK:
currentLevel = minimumLevel;
calculateMultiplier(currentLevel,
1.0,
nextStageSampleIndex);
break;
case ENVELOPE_STAGE_DECAY:
currentLevel = 1.0;
calculateMultiplier(currentLevel,
fmax(stageValue[ENVELOPE_STAGE_SUSTAIN], minimumLevel),
nextStageSampleIndex);
break;
case ENVELOPE_STAGE_SUSTAIN:
currentLevel = stageValue[ENVELOPE_STAGE_SUSTAIN];
multiplier = 1.0;
break;
case ENVELOPE_STAGE_RELEASE:
// We could go from ATTACK/DECAY to RELEASE,
// so we're not changing currentLevel here.
calculateMultiplier(currentLevel,
minimumLevel,
nextStageSampleIndex);
break;
default:
break;
}
}
So progress through the cases is being controlled by double EnvelopeGenerator::nextSample().
Here is what I am trying instead to do to control it differently:
double EnvelopeGenerator::nextSample() {
if (currentStage = ENVELOPE_STAGE_ATTACK) {
currentLevel = pow(currentSampleIndex / 30000.0f, 2.0f);
currentSampleIndex++;
if (currentLevel >= 1.0) {
enterStage(ENVELOPE_STAGE_DECAY);
}
}
else if (currentStage = ENVELOPE_STAGE_DECAY) {
currentLevel = 1/ pow((currentSampleIndex / 30000.0f)+1, 2.0f);
currentSampleIndex++;
if (currentLevel = 0.1) {
enterStage(ENVELOPE_STAGE_RELEASE);
}
}
else if (currentStage = ENVELOPE_STAGE_RELEASE) {
currentLevel = currentLevel = 1 / pow((currentSampleIndex / 30000.0f) + 1, 2.0f);
currentSampleIndex++;
if (currentLevel = 0.0001) {
enterStage(ENVELOPE_STAGE_OFF);
}
}
else {}
Those are not the final equations I need for each case. They're just simple test equations. But currently with this instead for the nextSample function, I am just getting a looping attack phase indefinitely.
I cannot understand why it is looping infinitely on attack. I thought I made it clear that if the level hits 1.0, it should switch to decay case.
What am I doing wrong and how do I fix it? I do not have sufficient experience with C++ to know how to do this properly.
You're using a single = in your if statements, which is an assignment. To compare you want to use ==.
if (currentStage == ENVELOPE_STAGE_ATTACK)

How do I scale Box2D objects with PPM?

I recently ran into a problem with Box2D where my player was moving at a slow speed. I use LinearImpulse's to move the body but (100, 100) was the fastest it could go.
After researching it a bit, I know that the Box2D body is too large because Box2D uses meters and I'm typing it in pixels. I know I have to scale the bodies using a PPM constant, but it's not quite making sense to me.
I've created a PPM constant and set it to 32.0f.
const float PPM = 32.0f;
Here's how I create the dynamic player body:
void Physics::playerDynamic(float x, float y, float width, float height)
{
b2BodyDef bodyDef;
bodyDef.type = b2_dynamicBody;
bodyDef.position.Set(x / PPM, y / PPM);
body = world.CreateBody(&bodyDef);
b2PolygonShape dynamicBox;
dynamicBox.SetAsBox((64.0f) / PPM, (64.0f) / PPM);
b2FixtureDef fixtureDef;
fixtureDef.shape = &dynamicBox;
fixtureDef.filter.categoryBits = CATEGORY_PLAYER;
fixtureDef.filter.maskBits = CATEGORY_PLAYER;
fixtureDef.filter.groupIndex = -1;
body->CreateFixture(&fixtureDef);
world.Step(timeStep, velocityIterations, positionIterations);
posX = x;
posY = y;
bodyType = "player";
}
I understand that I need to scale down the body, which I did by dividing it by the PPM. But now the body is really small and won't collide how I'd like it to.
Here is the function where I apply the impulse to the player body:
void Physics::moveBodies()
{
myCollisionDetection myListener;
world.SetContactListener(&myListener);
if (bodyType != "player")
{
}
else if (bodyType == "player")
{
body->SetAwake(true);
float forceX = 0;
float forceY = 0;
switch (moveState)
{
case MS_UP:
forceY = -50;
break;
case MS_DOWN:
forceY = 50;
break;
case MS_LEFT:
forceX = -50;
break;
case MS_RIGHT:
forceX = 50;
break;
case MS_UPRIGHT:
forceY = -50;
forceX = 50;
break;
case MS_UPLEFT:
forceY = -50;
forceX = -50;
break;
case MS_DOWNRIGHT:
forceY = 50;
forceX = 50;
break;
case MS_DOWNLEFT:
forceY = 50;
forceX = -50;
break;
case MS_STOP:
body->SetLinearVelocity(b2Vec2(0, 0));
}
body->ApplyLinearImpulse(b2Vec2(forceX, forceY ), body->GetWorldCenter(), true);
pos = body->GetPosition();
posX = body->GetPosition().x;
posY = body->GetPosition().y;
}
world.Step(timeStep, velocityIterations, positionIterations);
}
I've been researching this for quite a while and it seems simple but I'm having a hard time applying it to my code.
So what do I do from here? Do I scale the body back up?
I'm also using SDL2 for the graphics. Do I need to change anything with the rendering?

ASSIMP & paintGL() ,slow rendering (and crash)

I am using Assimp to load a .3ds file, and a QGLWidget derived class to draw it using PaintGL(). It works with small .3ds files (some KBytes) but if i try to render bigger files (like 1MBytes) the application crashes. Is my way too bad and twisted? Am I doing something wrong?
With qDebug i understand that paintGL() works correctly.The problem is in ourRender method,because if i obscure the
for (int t = 0; t < p->getFaces().count(); ++t)
and in detail
glVertex3f(f.getVerticesArray()[s].getX(),f.getVerticesArray();
cycle it all works fast (but obviously nothing is painted) except grid and axis.With it,and loading some complicated 3ds,it crashes
my hardware is
Phenom II X3 2.10ghz,4GB and 6650M (last drivers)
On a Celeron 2.1 Ghz it crash
BUT on a i7 the program starts but render #2FPS (if I dont use "ourRender" method,it renders at 120fps on my pc)
void GLWidget::paintGL()
{
qDebug << "Start PaintGL() #" << times;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
gluLookAt(objCamera->mPos.x, objCamera->mPos.y, objCamera->mPos.z,
0, objCamera->mView.y, 0,
objCamera->mUp.x, objCamera->mUp.y, objCamera->mUp.z);
if (drawLines) glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
else glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
draw_grid();
drawAxis();
ourRender(this->scenaa);
qDebug << "Close PaintGL() #" << times;
}
And this is the "ourRender" method:
void GLWidget::ourRender(const Scene* sc){
QHash<QString, SceneObject*>& hash=sc->getObj();
double molt =1/20;
int counter =0;
for (QHash<QString,SceneObject*>::ConstIterator i = hash.begin();i!=hash.end();++i) {
aiMatrix4x4 minchia(1,0,0,molt*20,0,1,0,molt*20,0,0,1,molt*20,0,0,0,1);
aiTransposeMatrix4(&minchia);
glPushMatrix();
const Mesh* p = dynamic_cast<Mesh*>(i.value());
glMultMatrixf((float*) &minchia);
if(p){
for (int t = 0; t < p->getFaces().count(); ++t) {
Face f = p->getFaces()[t];
GLenum face_mode;
switch(f.getVerticesArray().count()) {
case 1: face_mode = GL_POINTS; break;
case 2: face_mode = GL_LINES; break;
case 3: face_mode = GL_TRIANGLES; break;
default: face_mode = GL_POLYGON; break;
}
glBegin(face_mode);
QList<Vector3D> lista = f.getVerticesArray();
for(int s = 0; s < lista.count(); s++) {
if (p->getNormals().count()>0)
--------->glVertex3f(f.getVerticesArray()[s].getX(),f.getVerticesArray()[s].getY(),f.getVerticesArray()[s].getZ());
}
glEnd();
}
}
glPopMatrix();
molt+=13;
counter++;
}
glPopMatrix();
}
...in the derived QGLWidget class costructor...
SceneImporter* aa = new AssimpAdapter();
Scene * nuovo=aa->importFile("C:/Users/nicola/Desktop/Source/aces.3ds");
scenaa=nuovo;
We solved the problem modifying "ourender" method (using references instead of copyes)
void GLWidget::ourRender(Scene *&sc){
QHash<QString, SceneObject*>& hash=sc->getObj();
int counter =0;
for (QHash<QString,SceneObject*>::ConstIterator i = hash.begin();i!=hash.end();++i) {
aiMatrix4x4 m;
aiTransposeMatrix4(&m);
glPushMatrix();
const Mesh* p = dynamic_cast<Mesh*>(i.value());
glMultMatrixf((float*) &m);
if(p){
//apply_material(aaFuori.GetScene()->mMaterials[counter]);
QList<Face>& faccie=p->getFaces();
for (int t = 0; t < faccie.count(); ++t) {
Face f = faccie[t];
GLenum face_mode;
switch(f.getVerticesArray().count()) {
case 1: face_mode = GL_POINTS; break;
case 2: face_mode = GL_LINES; break;
case 3: face_mode = GL_TRIANGLES; break;
default: face_mode = GL_POLYGON; break;
}
glBegin(face_mode);
QList<Vector3D>& lista = f.getVerticesArray();
int conta=lista.count();
glVertex3f(lista[0].x,lista[0].y,lista[0].z);
glVertex3f(lista[1].x,lista[1].y,lista[1].z);
glVertex3f(lista[2].x,lista[2].y,lista[2].z);
glEnd();
}
}
glPopMatrix();
counter++;
}
Now we can render 8MBytes .3Ds #4fps during camera rotations (instead of application crash).Could someone of you give us an opinion about this result?is it good or bad?
Optimizazion.The fact is that for every vertex we were accessing to a QList 3 times.Now we've modified it,and instead of Qlist we use a Vector3D* array that saves the position of the vertices and so we can use the GL method glVertex3fv((GLfloat*)array[numface].posvertex); So,given the pointer to the face,its much faster than before (4 to 10 fps on the same scene).
void GLWidget::ourRender(Scene *sc){
QHash<QString, SceneObject*>& hash=sc->getObj();
aiMatrix4x4 m;
for (QHash<QString,SceneObject*>::ConstIterator i = hash.begin();i!=hash.end();++i) {
aiTransposeMatrix4(&m);
glPushMatrix();
Mesh* p = dynamic_cast<Mesh*>(i.value());
glMultMatrixf((float*) &m);
if(p){
QList<Face>& faccie=p->getFaces();
int numerofacce=faccie.count();
for (int t = 0; t < numerofacce; ++t) {
Face& f = faccie[t];
GLenum face_mode;
Vector3D* lista=f.arrayVertici;
switch(f.getVerticesArray().count()) {
case 1:
face_mode = GL_POINTS;
glBegin(face_mode);
glVertex3fv((GLfloat*)lista[0].pos);
break;
case 2:
face_mode = GL_LINES;
glBegin(face_mode);
glVertex3fv((GLfloat*)lista[0].pos);
glVertex3fv((GLfloat*)lista[1].pos);
break;
case 3:
face_mode = GL_TRIANGLES;
glBegin(face_mode);
glVertex3fv(&lista[0].pos[0]);
glVertex3fv(&lista[1].pos[0]);
glVertex3fv(&lista[2].pos[0]);
break;
default: face_mode = GL_POLYGON; break;
}
glEnd();
}
}
glPopMatrix();
counter++;
}
glPopMatrix();
}
Where Vector3D is initialized like this:
Vector3D::Vector3D(double x, double y, double z) {
setX(x);
setY(y);
setZ(z);
pos[0]=x; //vertex1
pos[1]=y; //vertex2
pos[2]=z; //vertex3
}
PS:Grimmy suggests me to use DisplayLists (discovered right now).Tomorrow I will try them.

How to move relatively to the angle?

I keep looking up on the internet how to move from point A to point B on an angle with a specified distance. When I tried to code it, however, the camera just gets messed up and I'm moving in random directions. I am using SDL/OpenGL with c++ and this is my player function. Right now, I'm trying to get the player to move forwards along the angle.
void player_action()
{
if (SDL_PollEvent(&event))
{
switch (event.type)
{
case SDL_MOUSEMOTION:
{
player.rotxl = (screen->w)/2;
player.rotxd = event.motion.x - player.rotxl;
player.rotx = player.rotx + (player.rotxd/4);
if (player.rotx < 0)
{
player.rotx = player.rotx + 360;
};
if (player.rotx > 360)
{
player.rotx = player.rotx - 360;
}
};
break;
case SDL_KEYDOWN:
switch (event.key.keysym.sym)
{
case SDLK_w:
{player.zvel = 8.0f;}; break;
case SDLK_a:
{player.xvel = 8.0f;}; break;
case SDLK_s:
{player.zvel = -8.0f;}; break;
case SDLK_d:
{player.xvel = -8.0f;}; break;
case SDLK_ESCAPE:
{running = false;}; break;
default: break;
}; break;
case SDL_KEYUP:
switch(event.key.keysym.sym)
{
case SDLK_w:
{player.zvel = 0.0f;}; break;
case SDLK_a:
{player.xvel = 0.0f;}; break;
case SDLK_s:
{player.zvel = 0.0f;}; break;
case SDLK_d:
{player.xvel = 0.0f;}; break;
default: break;
};
break;
};
};
player.x = player.x + float(player.zvel*cos((double)player.rotx));
player.z = player.z + float(player.zvel*sin((double)player.rotx));
glRotatef(player.rotx, 0.0f, 1.0f, 0.0f);
glTranslatef(player.x, player.y, player.z);
SDL_WarpMouse((screen->w/2), (screen->h/2));
};
If I'm correct the math functions sin and cos both take angles in radians, not degrees as player.rotx seems to be. Try the following:
player.x = player.x + float(player.zvel*cos((double)player.rotx*0.0174532925));
player.z = player.z + float(player.zvel*sin((double)player.rotx*0.0174532925));
We're multiplying player.rotx by pi/180, which is how we convert degrees to radians.
Not sure if this is your only problem, but it certainly appears to be one of them.
Two possible sources of the issue I see:
The standard C++ cos/sin function take a function in radians instead of degrees (one radian = 180/pi degrees).
While I'm not familiar with SDL a quick look at the docs makes me think you should be using event.motion.xrel instead of .x. You'll have to change your rotx calculation which should not need the screen width.