Interpolation using boost:timer and slerp, quaternions - c++

Im aware this code just looks like a massive block of mess so iv'e done my best to comment what i can... If anyone regularly does skeletal animation im hoping youl see whats going on here.
The problem im having is that float interp = (next-current)/(next-start); is not returning whats expected, e.g. values greater than 1 and minus values... Im guessing this is the whole reason the animations arent being shown and theres no other underlying mistakes.. If there is anything obvious sticking out please let me know.
m_animations stores all the keyframe information for a joint.
void Animation::getRotation(Joint& J) {
int i=0,j=0; //i for bone to animation j for which keyframe in animation
float start, next, current = m_time.elapsed(); //storing time elapsed to keep it the same thoughout method to avoid errors
for (i=0; i<m_animations.size(); i++) {
if(m_animations[i].m_bname == J.name) //finds which bone is being animated
break;
} //retrieve the correct 'anim' for Joint
if (current > m_animations[i].rx_time[m_animations[i].rx_time.size()-1]) { //checks to see if end of animation
m_time.restart();
current = m_time.elapsed(); //resets the animation at its end
}
for (j=0; j<m_animations[i].rx_time.size()-1; j++) {
if(m_animations[i].rx_time[j] >= next && next < m_animations[i].rx_time[j+1]) { //finds the keyframe
start = m_animations[i].rx_time[j]; //start time of current frame
next = m_animations[i].rx_time[j+1]; //end time of current frame
break;
}
}
cout << start <<" "<< current <<" "<< m_time.elapsed() <<" "<< next << endl;
//Get start and end quaternions for slerp
Rotation3 Rj(m_animations[i].rx_angle[j], m_animations[i].ry_angle[j], m_animations[i].rz_angle[j], J.translation);
J.quat = Rj.GetQuat(); //rotating to
Rotation3 R = Rotation3(m_animations[i].rx_angle[j+1], m_animations[i].ry_angle[j+1], m_animations[i].rz_angle[j+1], J.translation);
Quat4 q = R.GetQuat(); //rotating from
float interp = (next-current)/(next-start); //find interpolation point
Quat4 slerp = Slerp(J.quat, q, interp); //sphereical linear interpolation
R = Rotation3(slerp,J.translation);
J.rotation.PasteRotation(R.GetRotationMatrix());
}
Also if it helps heres the update skeleton function that calls getRotation
void Animation::update_skeleton(Joint& J) {
getRotation(J);
J.world.PasteTranslation(J.translation); //world becomes translation matrix
J.world *= J.rotation;
if(J.pName != "") {
J.world = Mat4(J.parent->world) *= J.world; //as not to overwrite the parents world matrix
}
J.translation = J.world.ExtractTranslation();
for(int i=0; i<J.children.size(); i++) {
update_skeleton(*J.children[i]);
}
}
Also when i run my program, it seems to be as if there is only one joint... So im guessing something might be going wrong with the J.translation value during getRotation, but im hoping that fixing my interpolation problem might solve this...
Any help will be VERY appreciated.

You seem to be resetting current before using the original values of start and next, if I've read the code properly that will be causing current to be greater than next, leading to yor negative interpolations.

Turns out there were quite a few mistakes... But the main error was to do with pointers, I fixed it by giving the bones ids for parents, children and itself. Then I changed the functions to take bone id instead of reference to a joint. Problem = fixed :D

Related

OpenGL Collisions between 2 spheres sometimes not detected

For this project i use OpenGl.
I'm trying to detect the collision between two spheres, I think it's pretty simple.
It works but sometimes (very often actually...) the collision between these two spheres is not detected, and I really don't know why...
I tried to change the algorithm of detection and it allways ends by a non detection sometimes...
void MyGlWindow::checkMoverIsHit()
{
for (size_t i = 0; i < m_container->m_movers.size(); i++)
{
if (m_container->m_ball != m_container->m_movers[i]) {
float size = m_container->m_ball->m_size + m_container->m_movers[i]->m_size;
if (size >= (m_container->m_ball->m_position - m_container->m_movers[i]->m_position).magnitude())
{
score += 10;
m_container->m_movers.erase(std::remove(m_container->m_movers.begin(), m_container->m_movers.end(), m_container->m_movers[i]), m_container->m_movers.end());
for (size_t i = 0; i < (score / 10) + 1; i++)
createMover();
reload();
}
}
}
}
I call this function in my update function
void MyGlWindow::update()
{
TimingData::get().update();
if (!run) return;
float lastFrameDuration = (float)TimingData::get().lastFrameDuration;
float duration = lastFrameDuration * 0.003;
totalTimePrecise += lastFrameDuration;
totalTimeSec = totalTimePrecise / 1000;
if (totalTimeSec > 60) {
writeBestScoreInFile();
restart();
}
if (totalTimeSec == 40)
windBlowing = true;
if (duration <= 0.0f) return;
m_container->update(duration);
if (windBlowing == true)
m_container->windBlow();
checkBallDetachFromAnchor();
checkMoverIsHit(); // !!! ITS CALLED HERE !!!
m_world->runPhysics(duration);
}
m_container is my container of movers: it contains basically all the "movers" of my scene.
m_container->m_ball is a pointer of one of these movers. It's the ball I launched to "shoot" the other movers.
After I think everything is pretty clear, ask me if something is not.
Hope someone can help me... I've done everything in my project it's the only thing bugging !
Here is a GIF, the first ball worked, the second didn't:
I finally manage to find out what was happening.
The problem is that my world is avoiding collisions. What I mean by that is: when two objects collide, they automatically bounce against each other.
This behaviour was the problem because the goal of my hunting ball is to collide against the other objects so.... randomly... it was not detecting some collisions, because it was boucing.
To fix it, I removed from my hunting ball the fact that it was iteracting with the other movers of the scene. So now it's only checking in my function checkMoverIsHit(); if it's colliding with the other movers.
It now works perfectly.

Issues turning loaded meshes into cloth simulation

I'm having a bit of issue trying to get meshes I import into my program to have cloth simulation physics using a particle/spring system. I'm kind of a beginner into graphics programming, so sorry if this is super obvious and I'm just missing something. I'm using C++ with OpenGL, as well as Assimp to import the models. I'm fairly sure my code to calculate the constraints/springs and step each particle is correct, as I tested it out with generated meshes (with quads instead of triangles), and it looked fine, but idk.
I've been using this link to study up on how to actually do this: https://nccastaff.bournemouth.ac.uk/jmacey/MastersProjects/MSc2010/07LuisPereira/Thesis/LuisPereira_Thesis.pdf
What it looks like in-engine: https://www.youtube.com/watch?v=RyAan27wryU
I'm pretty sure it's an issue with the connections/springs, as the imported model thats just a flat plane seems to work fine, for the most part. The other model though.. seems to just fall apart. I keep looking at papers on this, and from what I understand everything should be working right, as I connect the edge/bend springs seemingly correctly, and the physics side seems to work from the flat planes. I really can't figure it out for the life of me! Any tips/help would be GREATLY appreciated! :)
Code for processing Mesh into Cloth:
// Container to temporarily hold faces while we process springs
std::vector<Face> faces;
// Go through indices and take the ones making a triangle.
// Indices come from assimp, so i think this is the right thing to do to get each face?
for (int i = 0; i < this->indices.size(); i+=3)
{
std::vector<unsigned int> faceIds = { this->indices.at(i), this->indices.at(i + 1), this->indices.at(i + 2) };
Face face;
face.vertexIDs = faceIds;
faces.push_back(face);
}
// Iterate through faces and add constraints when needed.
for (int l = 0; l < faces.size(); l++)
{
// Adding edge springs.
Face temp = faces[l];
makeConstraint(particles.at(temp.vertexIDs[0]), particles.at(temp.vertexIDs[1]));
makeConstraint(particles.at(temp.vertexIDs[0]), particles.at(temp.vertexIDs[2]));
makeConstraint(particles.at(temp.vertexIDs[1]), particles.at(temp.vertexIDs[2]));
// We need to get the bending springs as well, and i've just written a function to do that.
for (int x = 0; x < faces.size(); x++)
{
Face temp2 = faces[x];
if (l != x)
{
verticesShared(temp, temp2);
}
}
}
And heres the code where I process the bending springs as well:
// Container for any indices the two faces have in common.
std::vector<glm::vec2> traversed;
// Loop through both face's indices, to see if they match eachother.
for (int i = 0; i < a.vertexIDs.size(); i++)
{
for (int k = 0; k < b.vertexIDs.size(); k++)
{
// If we do get a match, we push a vector into the container containing the two indices of the faces so we know which ones are equal.
if (a.vertexIDs.at(i) == b.vertexIDs.at(k))
{
traversed.push_back(glm::vec2(i, k));
}
}
// If we're here, if means we have an edge in common, aka that we have two vertices shared between the two faces.
if (traversed.size() == 2)
{
// Get the adjacent vertices.
int face_a_adj_ind = 3 - ((traversed[0].x) + (traversed[1].x));
int face_b_adj_ind = 3 - ((traversed[0].y) + (traversed[1].y));
// Turn the stored ones from earlier and just get the ACTUAL indices from the face. Indices of indices, eh.
unsigned int adj_1 = a.vertexIDs[face_a_adj_ind];
unsigned int adj_2 = b.vertexIDs[face_b_adj_ind];
// And finally, make a bending spring between the two adjacent particles.
makeConstraint(particles.at(adj_1), particles.at(adj_2));
}
}

Minimax Algorithm: Why make rating negative?

/* finds the best move for the current player given the state of the game.
* depth parameter and MAX_DEPTH are used to limit the depth of the search for games
* that are too difficult to analyze in full detail (like chess)
* returns best move by storing an int in variable that rating points to.
* we want to make the move that will result in the lowest best move for the position after us(our opponent)
*/
moveT findBestMove(stateT state, int depth, int &rating) {
Vector<moveT> moveList;
generateMoveList(state, moveList);
int nMoves = moveList.size();
if (nMoves == 0) cout << "no move??" << endl;
moveT bestMove;
int minRating = WINNING_POSITION + 1; //guarantees that this will be updated in for loop
for (int i = 0; i < nMoves && minRating != LOSING_POSITION; i++) {
moveT move = moveList[i];
makeMove(state, move);
int curRating = evaluatePosition(state, depth + 1);
if (curRating < minRating) {
bestMove = move;
minRating = curRating;
}
retractMove(state, move);
}
rating = -minRating;
return bestMove;
}
/* evaluates the position by finding the rating of the best move in that position, limited by MAX_DEPTH */
int evaluatePosition(stateT state, int depth) {
int rating;
if (gameIsOver(state) || depth >= MAX_DEPTH) {
return evaluateStaticPosition(state);
}
findBestMove(state, depth, rating);
return rating;
}
This is my code for implementing a minimax algorithm to play a perfect game of tic tac toe against a computer. The code works and there are many other helper functions not show here. I understand the nature of the algorithm, however I am having a hard time fully wrapping my head around the line at the end of the findBestMove() function:
rating = -minRating;
This is what my book says: The negative sign is included because the perspective has shifted: the positions were evaluated from the point- of-view of your opponent, whereas the ratings express the value of a move from your own point of view. A move that leaves your opponent with a negative position is good for you and therefore has a positive value.
But when we call the function initially, it is from the computers perspective. I guess when we evaluate each position, this function is being called from our opponent's perspective and that is why? Could someone give me more insight into what is going on recursively and exactly why the rating needs to be negative at the end.
As always thank you very much for your time.
Imagine two positions, A and B, where A is better for player a and B is better for player b. When player a evaluates these positions, eval(A) > eval(B), but when play b does, we want eval(A) < eval(B), but don't. If b instead compares -eval(A) with -eval(B), we get the desired result, for the very reasons your book says.

Slowdown when loading the same SpriteFrame used in an animation in Cocos2dx

I am currently experiencing some heavy slowdowns with my game. I have narrowed it down to something related with texture animations.
In my game there are characters that walk in 1 of 4 possible directions, they will walk up to a point, then change direction and continue walking (sort of like a tower defense game).
First i am loading the sprite frame cache like this
SpriteFrameCache::getInstance()->addSpriteFramesWithFile("characters.plist");
This code is only run once during the life time of my application.
When the characters get loaded to the screen their animation is being set using the following code:
int direction = 0;
int number = 0;
if (this->to_x < 0) // Left
{
direction = 1;
number = 1;
}
else if(this->to_x > 0) // Right
{
direction = 2;
number = 1;
}
if (this->to_y < 0) // Down
{
direction = 0;
number = 0;
}
else if(this->to_y > 0) // Up
{
direction = 3;
number = 2;
}
int s = 0; //skin
// Set the animation
Animation *animation = Animation::create();
for (int i = 0; i < INT16_MAX; i++)
{
string frame_sprite_name = StringUtils::format("%s_%d_%d_%d.png",parameters[name].image_name.c_str(),s,number,i);
auto frame = SpriteFrameCache::getInstance()->getSpriteFrameByName(frame_sprite_name);
if (frame) {
animation->addSpriteFrame(frame);
} else {
break;
}
}
// Invert the sprite when they go right
if (direction == 2) {
setFlippedX(true);
}else{
setFlippedX(false);
}
// Set the pace of the animation based on the type
if (name=="runner") {
animation->setDelayPerUnit(0.15f);
} else{
animation->setDelayPerUnit(0.3f);
}
Animate *animate = Animate::create(animation);
this->stopAllActions();
this->runAction(RepeatForever::create(animate));
What this code does is:
Check the direction
Get the sprite frame from the cache based on the direction
Run the action with repeat forever.
However this code is ran every time they change direction to set the new animation of the active characters. Also, at one time I can have around 40-50 of these characters going around.
I've noticed that after a few minutes in the game the slowdown starts to happen as soon as a new "character" is created, (since they are created in rapid succession in waves). And the slowdown also happens when the characters change in direction. So this makes me believe I am using the textures wrong.
If anyone knows how to fix this please let me know.
PD: I was thinking about the possibility of pre-loading all the animations and then just having each of the sprites that represent the characters run the corresponding animation.
You should definitely cache the animation in the AnimationCache with addAnimation and getAnimation methods.

2D Platformer Collision Handling

I am trying to create a 2D platformer (Mario-type) game and I am some having some issues with handling collisions properly. I am writing this game in C++, using SDL for input, image loading, font loading, etcetera. I am also using OpenGL via the FreeGLUT library in conjunction with SDL to display graphics.
My method of collision detection is AABB (Axis-Aligned Bounding Box), which is really all I need to start with. What I need is an easy way to both detect which side the collision occurred on and handle the collisions properly. So, basically, if the player collides with the top of the platform, reposition him to the top; if there is a collision to the sides, reposition the player back to the side of the object; if there is a collision to the bottom, reposition the player under the platform.
I have tried many different ways of doing this, such as trying to find the penetration depth and repositioning the player backwards by the penetration depth. Sadly, nothing I've tried seems to work correctly. Player movement ends up being very glitchy and repositions the player when I don't want it to. Part of the reason is probably because I feel like this is something so simple but I'm over-thinking it.
If anyone thinks they can help, please take a look at the code below and help me try to improve on this if you can. I would like to refrain from using a library to handle this (as I want to learn on my own) or the something like the SAT (Separating Axis Theorem) if at all possible. Thank you in advance for your help!
void world1Level1CollisionDetection()
{
for(int i; i < blocks; i++)
{
if (de2dCheckCollision(ball,block[i],0.0f,0.0f)==true)
{
de2dObj ballPrev;
ballPrev.coords[0] = ball.coords[0];
ballPrev.coords[1] = ball.coords[1];
ballPrev.coords[2] = ball.coords[2];
ballPrev.coords[3] = ball.coords[3];
ballPrev.coords[0] -= ball.xspeed;
ballPrev.coords[1] -= ball.yspeed;
ballPrev.coords[2] -= ball.xspeed;
ballPrev.coords[3] -= ball.yspeed;
int up = 0;
int left = 0;
int right = 0;
int down = 0;
if (ballPrev.coords[0] < block[i].coords[0] && ballPrev.coords[2] < block[i].coords[0] && (((ball.coords[1] < block[i].coords[1]) || (ball.coords[3] < ball.coords[1])) || ((ball.coords[1] < block[i].coords[3]) || ball.coords[3] < block[i].coords[3])))
{
left = 1;
}
if (ballPrev.coords[0] > block[i].coords[2] && ballPrev.coords[2] > block[i].coords[2] && (((ball.coords[1] < block[i].coords[1]) || (ball.coords[3] < ball.coords[1])) || ((ball.coords[1] < block[i].coords[3]) || (ball.coords[3] < block[i].coords[3]))))
{
right = 1;
}
if(ballPrev.coords[1] < block[i].coords[1] && block[i].coords[1] < ballPrev.coords[3] && ballPrev.coords[3] < block[i].coords[3])
{
up = 1;
}
if(block[i].coords[1] < ballPrev.coords[1] && ballPrev.coords[1] < block[i].coords[3] && block[i].coords[3] < ballPrev.coords[3])
{
down = 1;
}
cout << left << ", " << right << ", " << up << ", " << down << ", " << endl;
if (left == 1)
{
ball.coords[0] = block[i].coords[0] - 18.0f;
ball.coords[2] = block[i].coords[0] - 2.0f;
}
else if (right == 1)
{
ball.coords[0] = block[i].coords[2] + 2.0f;
ball.coords[2] = block[i].coords[2] + 18.0f;
}
else if (down == 1)
{
ball.coords[1] = block[i].coords[3] + 4.0f;
ball.coords[3] = block[i].coords[3] + 20.0f;
}
else if (up == 1)
{
ball.yspeed = 0.0f;
ball.gravity = 0.0f;
ball.coords[1] = block[i].coords[1] - 17.0f;
ball.coords[3] = block[i].coords[1] - 1.0f;
}
}
if (de2dCheckCollision(ball,block[i],0.0f,0.0f)==false)
{
ball.gravity = -0.5f;
}
}
}
To explain what some of this code means:
The blocks variable is basically an integer that is storing the amount of blocks, or platforms. I am checking all of the blocks using a for loop, and the number that the loop is currently on is represented by integer i.
The coordinate system might seem a little weird, so that's worth explaining.
coords[0] represents the x position (left) of the object (where it starts on the x axis).
coords[1] represents the y position (top) of the object (where it starts on the y axis).
coords[2] represents the width of the object plus coords[0] (right).
coords[3] represents the height of the object plus coords[1] (bottom).
de2dCheckCollision performs an AABB collision detection.
Up is negative y and down is positive y, as it is in most games.
Hopefully I have provided enough information for someone to help me successfully. If there is something I left out that might be crucial, let me know and I'll provide the necessary information. Finally, for anyone who can help, providing code would be very helpful and much appreciated.
Thank you again for your help!
Edit 2: I have updated my code with a new algorithm that checks where the ball was previously before collision. Corner cases work on that single platform correctly now, and when I have a wall of objects, I can slide against it correctly now. The only remaining problem is that there is a small jittering effect that happens when I am on the ground, where the ball is constantly going up and down as if it is being pulled by gravity and then the ball falls back into the object again.
Edit: Here is a URL to an image trying to show the kinds of problems I am having:
http://img8.imageshack.us/img8/4603/collisionproblem.png
In case the explanation in the picture doesn't make too much sense, the ball cannot move left past the corner of an object unless I jump over it. However, the ball can move right, but it gets repositioned to the right of the object while moving, which is not needed. This creates a skipping movement essentially, where it appears as the the ball is skipping over half of the object or so when I move right. If this doesn't make sense, please ask me and I'll try to clarify more.
One problem with your code is that you only detect situations like this:
If the circle happens to be fully inside the block, you don't reposition at all. And that's a problem.
You're trying to think about your simulation as if it were continuous, but keep in mind it's discrete. In general, if you only look at the current state of the ball, you really cannot know which side it collided with. Look at these two possibilities:
The first solution that comes to mind is to look at the last position of the ball as well; more precisely, look at the delta vector. See if the delta vector intersects a wall. If it does, reposition in an axis-aligned direction towards the wall intersected by the delta vector.
Edit: When I said "delta vector", I forgot that you're moving a square and not a single point. So, if you just look at the delta vector of the top-left corner, that's not going to be enough because it may not detect that part of the ball entered a block. Instead, you can look at the delta vectors of all 4 corners.