I am following a tutorial series about skeletal animation on Youtube (https://www.youtube.com/watch?v=f3Cr8Yx3GGA) and have ran into a problem – everything works fine, except when I rotate one of the bones (or "joints"), they get rotated around the scene origin, meaning they do not stay in place but are translated. The following image illustrates the problem:
How can I make it so that the translation doesn't happen? I have been going over the tutorial series multiple times now, but cannot identify which step would prevent this from happening.
The code is very large, split into around a dozen files, and I don't know which section might be causing the issue, so I do not think there's much point in posting it all here (it should be similar to the code in the tutorial, even though I am using C++ while he's working in Java. The tutorial code can be found here: https://github.com/TheThinMatrix/OpenGL-Animation). If you could give me even general advice on how this issue is normally solved in skeletal animation, it should hopefully be enough for me to at least identify the part that's wrong and try moving from there.
Rotation matrices on their own can only describe rotations around the origin (Wikipedia). However, rotations can be used in conjunction with translations to change where the origin is to get the desired effect. For example, you could:
Translate the object so that it is centered around the origin
Rotate the object to the desired orientation
Translate the object back to the original position
Or, to phrase it in a different, but functionally equivalent way:
Move the origin to the object's position
Rotate the object to the desired orientation
Reset the origin back to its original position
Related question: Rotating an object around a fixed point in opengl
You just need to pay attention to what you are rotating around.
A way to fix this: Rotate it first and then translate it. Rotate the object while it is at the origin and then translate the object to where you want it.
Repeatedly do this when things change throughout your program. Start the object at the origin, do the desired rotation, and then translate out to it's final resting position.
Related
I currently have an ray-tracer that can read .obj models and then render the objects described on them. Until now, I was basically working with .obj models where the vertices where around the origin, generally closer than 10 of distance, at maximum being around 100.
Now, I downloaded a different model, where the vertices are far away from the origin, Always at least at hundreds of units from the origin, some vertices being about 5000 away in some axis.
The problem is that now I cannot focus the entire car!
One of my tests was with the distance from camera to origin of -3639.
And the result was this:
Then I step the camera away at -4639 and what was produced was this:
Changing my approach, decided to approach it, placing the camera at -2639
The result:
So at -2639 a I am being able to visualize the entire car but it does not fit in my field of view. At -3669 the light is already fading away by some reason.
I imagine that might be possible to see the full car proper lightened using a intermediate distance between -2669 and -3669 and also experimenting with the filed of view value, but there is something odd about the Light not covering the entire car at -3669 and I would like to find out the reason.
So I would appreciate suggestions about the cause of this issue and how to proceed in this kind of situation, how to focus the entire car.
Your question mentions you are changing the camera position. However, the images show the lighting area changing between the various cases. Just a spotlight in one case, and more of the car being lit in the other.
Most likely, in the third case, nothing of the car is lit, hence everything comes up black. Start by fixing the light staying the same when the camera moves, and see if it fixes your issue.
If you move the camera: It could help looking into the settings for the front and back clipping planes.
If you don't move the camera: The FOV show be larger if the object is larger. I would avoid doing this as this likely will lead to more problems when you read more than one object that are different.
Personally I would scale the input from the file. Ideally to some SI-unit that makes sense.
I want to move the camera forward, which is equivalent to moving the world back towards camera. I'm using Glut and glTranslate would do the job, but my question is how should I use it?
Suppose initially I start with glLoadIdentity(), then I set up the look at point using gluLookAt, and then I did some translation/rotation to the model. In this case how should I use glTranslate to translate the object in the world so that they can move with respect to the camera instead of their own origin/coordinate?
I thought I could save the current matrix using glGet, load Identity matrix, then do the translation I wanted, and then multiply the previous matrix back using glMultmatrix. But this didn't work for me.
And also if I want to enable yaw/pitch using glrotate, how should I do? (Also in the sense to rotate the world to make it seems rotating camera)
Sorry for my poor wording or conceptual mistake if there is any. I'm quite new to opengl and graphic programming in general and I'm still trying to fully understand the opengl pipeline, especially the matrix part. Any detailed explanation to that will also be greatly appreciated!
From reading your question, it sounds to me like what you're trying to do is simulate camera movement by translating every other object in the world about a fixed point (the camera)
While you're correct in saying that moving the camera actually moves everything else in the world about it, you seem to be going about it the wrong way. After all, look how much difficulty you're having just moving one box. Now imagine you have hundreds! Not much fun :)
Fortunately, there is a function that can help you, and you're already using it! gluLookAt (http://www.opengl.org/sdk/docs/man2/xhtml/gluLookAt.xml) is your guy. What it does under the hood is it creates a matrix (Not sure what a matrix is? Give this a read: http://solarianprogrammer.com/2013/05/22/opengl-101-matrices-projection-view-model/) that every other point in the world is multiplied by. This multiplication translates each point until its in its correct position relative to the camera. So you are correct in saying that moving the camera actually moves the whole world relative to the camera, this way we can do it all in one pass instead of having to calculate the new positions of each point manually.
So, you want to move the camera forward on the z axis? Just call gluLookAt, but pass in a value of eyez that is less than when you previously called gluLookAt. Here's an example:
gluLookAt(0,3,0,0,0,0,0,1,0);//This is out starting position, (0,3,0)
gluLookAt(0,2,0,0,0,0,0,1,0);//And this is out ending position. Notice that the eyez value has decreased by one
As for how to rotate, take a look at the second group of three parameters, the "center" parameters. Those determine what point is in the center of the camera, that is, what the camera is looking at. In the previous example, the center point was (0,0,0). You can rotate the camera by moving these points around. How you do it is a pretty complicated topic with a good bit of math thrown in, but the following links should help a bit:
http://ogldev.atspace.co.uk/www/tutorial15/tutorial15.html
http://www.fastgraph.com/makegames/3drotation/
http://en.wikipedia.org/wiki/Quaternions_and_spatial_rotation
Don't get discouraged if it seems too hard, keep at it! Feel free to ask me if you need clarification on this answer.
I'm currently trying to solve a problem regarding the display of an arm avatar.
I'm using a 3D tracker that's sending me coordinates and angles through my serial port. It works quite fine as long as I only want to show a "hand" or a block of wood in its place in 3D space.
The problem is: When I want to draw an entire arm (lets say the wrist is "stiff"), so the only degree of freedom is the elbow), I'm using the given coordinates (to which I've gltranslatef'd and glmultmatrix'd), but I want to draw another quad primitive with 2 vertices that are relative to the tracker coordinates (part of the "elbow") and 2 vertices that are always fixed next to the camera (part of the "shoulder"). However, I can't get out of my translated coordinate system.
Is my question clear?
My code is something like
cubeStretch = 0.15;
computeRotationMatrix();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glPushMatrix();
glTranslatef(handX, handY, handZ);
glMultMatrixf(*rotationMatrix);
glBegin(GL_QUADS);
/*some vertices for the "block of wood"*/
/*then a vertex which is relative to handX-handZ*/
glVertex3f(-cubeStretch, -cubeStretch+0.1, 5+cubeStretch);
/*and here I want to go back to the origin*/
gltranslatef(-handX, -handY, -handZ);
/*so the next vertex should preferably be next to the camera; the shoulder, so to say*/
glVertex3f(+0.5,-0.5,+0.5);
I already know the last three line don't work, it's just one of the ways I've tried.
I realize it might be hard to understand what I'm trying to do. Anyone got any idea on how to get back to the "un-gltranslatef'd" coordinate origin?
(I'd rather avoid having to implement a whole bone/joint system for this.)
Edit:https://imagizer.imageshack.us/v2/699x439q90/202/uefw.png
In the picture you can see what I have so far. As you can see, the emphasis so far has not been on beauty, but rather on using the tracker coordinates to correctly display something on the screen.
The white cubes are target points which turn red when the arm avatar "touches" them ("arm avatar" used here as a word for the hideous brown contraption to the right, but I think you know what I mean). I now want to have a connection from the back end of the "lower arm" (the broad end of the avatar is supposed to be the hand) to just the right of the screen. Maybe it's clearer now?
a) The fixed function stack is deprecated and you shouldn't use it. Use a proper matrix math library (like GLM), make copies of the branching nodes in your transformation hierarchy so that you can use those as starting point for different branches.
b) You can reset the matrix state to identity at any time using glLoadIdentity. Using glPushMatrix and glPopMatrix you can create a stack. You know how stacks work, do you? Pushing makes a copy and adds it to the top, all following operations happen on that. Poping removes the element at the top and gives you back the state it was in before the previous push.
Update
Regarding transformation trees you may be interested in the following:
https://stackoverflow.com/a/8953078/524368
https://stackoverflow.com/a/15566740/524368
(I'd rather avoid having to implement a whole bone/joint system for this.)
It's actually the most easy way to do this. In terms of fixed function OpenGL a bone-joint is just a combination of glTranslate(…); glRotate(…).
So I have been here before asking about this issue but no one has been able to answer my question thus far. So I made a video that demonstrates the issue.
I have so far checked and rechecked my math files, so has two of my college professors, I have checked my shaders, and I am just using a simple pass through shader.
I have create a video of the issue happening, I will describe a little of my process.
I have set initial values of my rotations to, this pushes it to the point where the issue appears.
rotX = 0.0f;
rotY = -22.0f;
rotZ = -62.0f;
These values ensure that I do not have to rotate the object at run time, these values are where the problem occurs. As you can see in the video the cow will start to rotation without any place in the code actually telling it to. I output the rotations matrices and rotations values to my log file and they are all normal.
http://www.youtube.com/watch?v=LB7_zftalT8
So I have never seen this before ever, anywhere. If anyone has seen something like this let me know. I have not posted any code because there are far to many possible issues, however I can provide code snippets on demand, or provide access to my source svn.
I have spent three weeks debugging this issue, I have at least 10 other sets of eyes look at this issue and review my code.
The only issue floating around that I haven't been able to remove as an issue is memory corruption, I hope you have better luck.
Edit:
Code Samples:
http://pastebin.com/hRSvEYAZ
I use quaternions for my rotations, I create them with axis angles. I then multiple my rotations together and create my 4x4.
Edit:
I have tried the answer provided by MadCoreTom, it did not help, I have also continued to take a look at memory and I cannot see any issue.
Edit:
So I have removed the normalization calls from my quaternions, now I only normalize the axis when I create my quaternion from an axis angle. I have also rewritten my toMatrix3 for my quaternion to see if that helps, it hasn't.
I also moved my updating the rotations to inside my key press, I intend to provide more code soon as well.
It is possible that rounding errors during .normalize() are causing the values to change slightly, and this keeps building up until the cow goes crazy.
You could try something like the following, and use rx in place of rotationX within the update method:
rx = rotationX.normalized();
Instead of modifying the value each time you loop through.
Alright so I solved my issue. There was a floating point error covering up the actual issue.
So once I fixed that, not using the method provided by MadcoreTom though. What I ended up doing was only normalizing the the axis, and never normalizing my quaternion during rotations.
The real issue was I was storing my angle and accumulating it, this was causing the issue.
Now I just pass in the change in rotation, create my quaternion from the axis/angle change, then I multiply this to my quaternionF.
I'm working on an Augmented Reality marker detection program, using OpenCV and I'm getting two different rotation and translation values for the same marker.
The 3D model switches between these states automatically without my control, when the camera is slightly moved. Screenshots of the above two situations are added below. I want the Image#1 to be the correct one. How to and where to correct this?
I have followed How to use an OpenCV rotation and translation vector with OpenGL ES in Android? to create the Projection Matrix for OpenGL.
ex:
// code to convert rotation, translation vector
glLoadMatrixf(ConvertedProjMatrix);
glColor3f(0,1,1) ;
glutSolidTeapot(50.0f);
Image #1
Image #2
Additional
I'd be glad if someone suggests me a way to make the Teapot sit on the marker plane. I know I have to edit the Rotation matrix. But what's the best way of doing that?
To rotate the teapot you can use glRotatef(). If you want to rotate your current matrix for example by 125° around the y-axis you can call:
glRotate(125,0,1,0);
I can't make out the current orientation of your teapot, but I guess you would need to rotate it by 90° around the x-axis.
I have no idea about your first problem, OpenCV seems unable to decide which of the shown positions is the "correct" one. It depends on what kind of features OpenCV is looking for (edges, high contrast, unique points...) and how you implemented it.
Have you tried swapping the pose algorithm (ITERATIVE, EPNP, P3P)? Or possibly use the values from the previous calculation - remember that it's just giving you its 'best guess'.