• Hey Guest! Ever feel like entering a Game Jam, but the time limit is always too much pressure? We get it... You lead a hectic life and dedicating 3 whole days to make a game just doesn't work for you! So, why not enter the GMC SLOW JAM? Take your time! Kick back and make your game over 4 months! Interested? Then just click here!

3Dcube vertical rotation not always correct

C

Constant

Guest
My program has 1 3Dcube on screen.
When you press one of the arrow-keys <Left>, <Right>, <Up> or <Down>
the cube will rotate horizontally or vertically.

But when horizontal rotation is -90, -270, 90 or 270
vertical rotation does not work correctly.

Can somebody explain to me why this happens and what to do
to solve this problem.

Thanks a lot.

Regards, Game Maker
Constant Professional Edition v1.4.1675


I added the code below.
I hope you use the code so you will see what to do to reproduce the problem.
The problem is clearly explained on screen and the code is easy to read.

Objects:
obj_cam - camera
obj_cube - contains all code
obj_text - Is used in script scr_show_info but does not contain any code.

Script:
scr_show_info - shows all info about the problem.

Backgrounds:
face - the image the cube has

// >>> obj_cam_CREATE
d3d_start();
d3d_set_perspective(true);
d3d_set_hidden(true);
d3d_set_lighting(false);
d3d_set_culling(false);
d3d_set_shading(false);
draw_set_color(c_white);

// >>> obj_cam_Draw
d3d_set_projection(obj_cube.x,obj_cube.y,30,obj_cube.x,obj_cube.y,60,0,0,1);

// >>> obj_cube_CREATE
b_Left_Pressed=false; //to check if Left is pressed
b_Right_Pressed=false; //to check if Right is pressed
b_Up_pressed=false; //to check if Up is pressed
b_Down_pressed=false; //to check if Down is pressed

h_rot = 0; //rotation variable horizontal (Left, Right)
v_rot = 0; //rotation variable vertical (Up, Down)

total_h_rot_value = 0; //actual total value h_rot after each rotation
total_v_rot_value = 0; //actual total value v_rot after each rotation

var_face = 0; //variable to keep image
str_comments = ""; //Contains comments


var_face = background_get_texture(face);

str_comments = "Start of this example program.
When you press one of the arrow-keys <Left>, <Right>, <Up> or <Down>
the cube will rotate horizontally or vertically.
You will see when horizontal rotation is -90, -270, 90 or 270
vertical rotation does not work correctly.
Can somebody explain to me why? Is there a solution?
All the code regarding this problem can be found in obj_cube."

// >>> obj_cube_DRAW
scr_show_info(); //This script shows info of h_rot, v_rot and comments

if b_Left_Pressed=true {
if h_rot > total_h_rot_value then { h_rot-=5;}
d3d_transform_add_rotation_x(v_rot);
d3d_transform_add_rotation_y(h_rot);
}

if b_Right_Pressed=true {
if h_rot < total_h_rot_value then { h_rot+=5;}
d3d_transform_add_rotation_x(v_rot);
d3d_transform_add_rotation_y(h_rot);
}

if b_Up_pressed=true{ // <Up> works correctly
if v_rot < total_v_rot_value then { v_rot+=5;} // when h_rot NOT =
if h_rot=-180 or h_rot=180 then // 90, 270, -90 or -270
{
d3d_transform_add_rotation_x(-v_rot); // back became front so
d3d_transform_add_rotation_y(-h_rot); // values become negative to
} // still have same result in rotation
else
{
d3d_transform_add_rotation_x(v_rot);
d3d_transform_add_rotation_y(h_rot);
}
}

if b_Down_pressed=true{ // <Down> works correctly
if v_rot > total_v_rot_value then { v_rot-=5;} // when h_rot NOT =
if h_rot=-180 or h_rot=180 then // 90, 270, -90 or -270
{
d3d_transform_add_rotation_x(-v_rot); // back became front so
d3d_transform_add_rotation_y(-h_rot); // values become negative to
} // still have same result in rotation
else
{
d3d_transform_add_rotation_x(v_rot);
d3d_transform_add_rotation_y(h_rot);
}
}

d3d_transform_add_translation(room_width/2,room_height/2,0);

d3d_draw_block(-32,-32,32, 32,32,-32,var_face,1,1);

d3d_transform_set_identity();


// >>> obj_cube_release<Left>
b_Left_Pressed=true;
b_Up_pressed=false;
b_Right_Pressed=false;
b_Down_pressed=false;

//If total h_rotation value now is -360 then reset to 0
if total_h_rot_value = -360 then total_h_rot_value = 0;

//Give new value
total_h_rot_value -= 90;

//If h_rotation value now is -360 then reset to 0
if h_rot <= -360 then h_rot = 0;

//str_comments is used in script scr_shwo_info which is called in obj_cube_Draw
str_comments = "The cube rotated horizontally to the Left."


// >>> obj_cube_release<Up>
b_Left_Pressed=false;
b_Up_pressed=true;
b_Right_Pressed=false;
b_Down_pressed=false;

//If total v_rotation value now is 360 then reset to 0
if total_v_rot_value = 360 then total_v_rot_value = 0;

//Give new value
total_v_rot_value += 90;

//If v_rot now is 360 then reset to 0
if v_rot >= 360 then v_rot = 0;

//str_comments is used in script scr_shwo_info which is called in obj_cube_Draw
if h_rot=-90 || h_rot=-270 || h_rot=90 || h_rot=270 then
{
str_comments = "PROBLEM PROBLEM PROBLEM.
Now you see the cube is not rotating vertically upwards when you press <Up>.
This happens only when the value of h_rot is -90, -270, 90 or 270

Press <Left>, <Right>, <Up> and <Down> as much as you like
and see what happens.

When h_rot has the values I mentiod here above rotation vertically
does not work correctly!

Can somebody explain to me why? Is there a solution?
All the code regarding this problem can be found in obj_cube."
}
else
{
str_comments = "The cube rotated vertically upwards.

When the value of h_rot = -90, -270, 90 or 270
vertical rotation does not work correctly."
}


// >>> obj_cube_release<Right>
b_Left_Pressed=false;
b_Up_pressed=false;
b_Right_Pressed=true;
b_Down_pressed=false;

//If total h_rotation value now is 360 then reset to 0
if total_h_rot_value = 360 then total_h_rot_value = 0;

//Give new value
total_h_rot_value += 90;

//If h_rot now is 360 then reset to 0
if h_rot >= 360 then h_rot = 0;

//str_comments is used in script scr_shwo_info which is called in obj_cube_Draw
str_comments = "The cube rotated horizontally to the Right."


// >>> obj_cube_release<Down>
b_Left_Pressed=false;
b_Up_pressed=false;
b_Right_Pressed=false;
b_Down_pressed=true;

//If total v_rotation value now is -360 then reset to 0
if total_v_rot_value = -360 then total_v_rot_value = 0;

//Give new value
total_v_rot_value -= 90;

//If v_rot now is -360 then reset to 0
if v_rot <= -360 then v_rot = 0;

//str_comments is used in script scr_shwo_info which is called in obj_cube_Draw
if h_rot=-90 || h_rot=-270 || h_rot=90 || h_rot=270 then
{
str_comments = "PROBLEM PROBLEM PROBLEM.
Now you see the cube is not rotating vertically downwards when you press <Down>.
This happens only when the value of h_rot is -90, -270, 90 or 270

Press <Left>, <Right>, <Up> and <Down> as much as you like
and see what happens.

When h_rot has the values I mentiod here above rotation vertically
does not work correctly!

Can somebody explain to me why? Is there a solution?
All the code regarding this problem can be found in obj_cube."
}
else
{
str_comments = "The cube rotated vertically downwards.
When the value of h_rot = -90, -270, 90 or 270
vertical rotation does not work correctly."
}


// >>> Script: scr_show_info
d3d_set_hidden(false);

draw_set_color(c_white)
d3d_set_projection_ortho(0,0,room_width,room_height,0);

draw_text(obj_text.x,obj_text.y,
"h_rot = " + string(h_rot) + " (horizontal rotation)" +
"#v_rot = " + string(v_rot)+ " (vertical rotation)" )

draw_text(obj_text.x+85,obj_text.y+100,str_comments)

d3d_set_hidden(true);
 

Attachments

FrostyCat

Redemption Seeker
This is a classic case of gimbal lock. You cannot have meaningful "horizontal" and "vertical" rotations all the time when the axes are fixed against each other. Either you switch to quaternion rotations, or you apply the existing transformation and changes in rotation as two separate transformations.
 
C

Constant

Guest
Thanks flyingsaucerinvasion for this example code. This helps a lot.

What I am trying to do is rotating q cube for 90 degrees up, down, left or right when a button is pressed.
So when I press a "Left-button" the cube rotes -90 degrees to the left. After that when I want to rotate the cube 90 degrees upwards I press an "Up-button" and the cube rotates 90 degrees upwards.
In my code it does not work because of gimbal lock as FrostyCat said.

So FrostyCat pointed me in the right direction and flyingsaucerinvasion provided me with example code.
I understand Euler angle but this is new to me and now I have information to work with and to learn from.
Thanks guys for helping me. I'll let you know when my problem is solved.
 
C

Constant

Guest
Hello flyingsaucerinvasion,

In the code I received I from you I am able to resize the cube.
I do this in obj_main_Create: (my example:) cube_rot = matrix_build(0,0,0,0,0,0,25,25,25); //resize cube by changing xscale, yscale, zscale

But I also want to put the cube at any position on the screen I like.
When I try to put the cube in the middle of the screen I use in obj_main_Create:
cube_x=room_width/2;
cube_y=room_height/2;
But this does not work.
What do I need to do when I want to put the cube in the middle of the screen (or on the right upper corner, or down left, or any position)
I hope yoy will help me because I tried and tried but I don't know the answer.
Thanks in advance.

Kind regards, Constant
 
@Constant Hi again!

It depends on where your camera is located. In the example I sent you, the camera is located at (0,0,1000), looking toward the origin of the room (0,0,0). So if you wanted something to appear at the center of the screen, in that example, you'd need to move it to (0,0,something). In that example, i use "d3d_transform_add_translation" to move the cube after rotating it. And if I want it to be located at the origin of the room (which would put it at the center of the screen because of where the camera is located in that example, then I would make the arguments of that "translation" (0,0,0).

So, I don't know where your camera is located in your project, but I'm guessing it is not located at a point above (room_width/2, room_height/2).

Does all of that make sense?
 
C

Constant

Guest
Thanks flyingsaucerinvasion,
It does make sense.
I'll do some tests and let yoy know.
Thanks!
 
C

Constant

Guest
Hi flyingsaucerinvasion,
I tested and I managed to make it work.
I created 8 cubes on screen: 4 in front and behind them another 4 cubes.
So these 8 cubes form one block all together (2 X 2 x 2).
At the moment each cube rotates individually.
Is it possible to make these 8 cubes rotate together as one block.
 
Top