void Sphere::DrawRays(Ray ray, sf::RenderWindow *window) { // sf::Vertex way[4]; StraightLine line = ray.Equation(); Vector2 p = Intersect(line, c2.center, c2.r, '-'); way[0] = sf::Vertex(sf::Vector2f(ray.getBegin().x, ray.getBegin().y), COLOR); way[1] = sf::Vertex(sf::Vector2f(p.x, p.y), COLOR); StraightLine normal = Normal(p, 2); StraightLine refrline; // drawNormal(p, normal, window); double sin = sinAngle(normal, line); double refr_sin = sin / n; if (refr_sin > 1 || refr_sin < -1) { // external reflection cout << "I AM HERE" << endl; refrline = external_reflection(normal, sin, p, line.a); double x = - refrline.b / refrline.a; //double y = refrline.a * 500 + refrline.b; way[2] = sf::Vertex(sf::Vector2f(x, 0)); } else{ refrline = refr_line(normal, refr_sin, p, line.a); cout << "REFRSIN" << refr_sin<< endl; p = Intersect(refrline, c1.center, c1.r, '+'); way[2] = sf::Vertex(sf::Vector2f(p.x,p.y), COLOR); normal = Normal(p, 1); } sin = sinAngle(normal, refrline); refr_sin = n*sin; //cout << refr_sin << endl; if (refr_sin > 1 || refr_sin < -1) { // external reflection cout << "REFRSIN" << refr_sin << endl; refrline = external_reflection(normal, sin, p, refrline.a); double x = (250 - refrline.b) / refrline.a; //double y = refrline.a * 500 + refrline.b; way[3] = sf::Vertex(sf::Vector2f(x,250), COLOR); window->draw(way, 4, sf::LinesStrip); } else { refrline = refr_line(normal, refr_sin, p, refrline.a); //double x = (250 - refrline.b) / refrline.a; //way[3] = sf::Vertex(sf::Vector2f(x, 250)); double y = refrline.a * 500 + refrline.b; way[3] = sf::Vertex(sf::Vector2f(500, y), COLOR); window->draw(way, 4, sf::LinesStrip); } }
inline Matrix2d Quaternion2d::rotationMatrix() const { return Matrix2d(cosAngle(), sinAngle(), -sinAngle(), cosAngle()); }
inline Quaternion2d Quaternion2d::inverse() const { return Quaternion2d(cosAngle(), -sinAngle()); }
inline double Quaternion2d::dot(const Quaternion2d& other) const { return cosAngle() * other.cosAngle() + sinAngle() * other.sinAngle(); }
inline double Quaternion2d::angle() const { return atan2(sinAngle(), cosAngle()); }
void Ball::ProcessCollisions(unordered_map<string, Game_Object*> objects) { // Calculate Vector4 thisCenter(this->translationMatrix[0][3], this->translationMatrix[1][3], 0.0f, 0.0f); // Check collision with all objects for(unordered_map<string, Game_Object*>::iterator itr = objects.begin(); itr != objects.end(); itr++) { // Vector4 otherCenter(itr->second->translationMatrix[0][3], itr->second->translationMatrix[1][3], 0.0f, 0.0f); Vector4 combinedRadius = this->sprite->GetRadius() + itr->second->sprite->GetRadius(); // Check for collidable objects, based on dictionary name if(itr->first == "WallLeft" && thisCenter.x - sprite->GetRadius().x < otherCenter.x + itr->second->sprite->GetRadius().x) { velocity->x += this->velocity->x * -2.0f; } if(itr->first == "WallRight" && thisCenter.x + sprite->GetRadius().x > otherCenter.x - itr->second->sprite->GetRadius().x) { velocity->x += this->velocity->x * -2.0f; } if(itr->first == "WallTop" && thisCenter.y + sprite->GetRadius().x > otherCenter.y - itr->second->sprite->GetRadius().y) { velocity->y += this->velocity->y * -2.0f; } if(itr->first == "WallBottom" && thisCenter.y - sprite->GetRadius().x < otherCenter.y + itr->second->sprite->GetRadius().y) { velocity->y += this->velocity->y * -2.0f; } // Detect spherical collision if( ( itr->first.find("Ball") != string::npos || itr->first == "Bumper" /*|| itr->first == "Flipper1"*/) && itr->second != this && ( (thisCenter.x - otherCenter.x) * (thisCenter.x - otherCenter.x) ) + ( (thisCenter.y - otherCenter.y) * (thisCenter.y - otherCenter.y) ) < ( combinedRadius.x * combinedRadius.x) ) { // Get the vector in between the two objects Vector4 hyp( (thisCenter.x - otherCenter.x), (thisCenter.y - otherCenter.y), 0.0f, 0.0f ); // Get the normal vector to the colliding object Vector4 normal(hyp.normalize(hyp)); // Calculate a new velocity *velocity = normal * (velocity->dot(normal) * -2.0f) + *velocity; // Separate collided objects (upon collision 2 objects will slightly overlap so this is necessary) Matrix4::UpdatePositionMatrix(translationMatrix, velocity->x, velocity->y, 0); // NOTE: Ball-Ball collision sometimes only changes the velocity of one of the balls } // Angle of reflection (angle of flipper) float bounceAngle = 0.0f; if(itr->first == "Flipper1" && FlipperCollision(otherCenter, *(itr->second), bounceAngle)) { Vector4 flipperRadius(itr->second->sprite->GetRadius().x, itr->second->sprite->GetRadius().y, 0.0f, 0.0f); GLfloat cosAngle(itr->second->rotationMatrix[0][0]); GLfloat sinAngle(-itr->second->rotationMatrix[0][1]); // Calculate angle of impact GLfloat hitAngle = atan(velocity->y/velocity->x) + PI; if(velocity->x < 0) hitAngle += 180 * PI / 180; else if(velocity->x >= 0 && velocity->y < 0) hitAngle += 360 * PI / 180; if(hitAngle >= 2*PI - .0000002 && hitAngle <= 2*PI + .0000002) hitAngle = 0.0f; bounceAngle = PI - hitAngle - 2 * bounceAngle; if(bounceAngle < 0) bounceAngle += 2 * PI; float length = velocity->length(); // How to get a vector based on this angle Vector4 normal(length * cos(bounceAngle), length * sin(bounceAngle), 0.0f, 0.0f); *velocity = normal; // Separate collided objects (upon collision 2 objects will slightly overlap so this is necessary) Matrix4::UpdatePositionMatrix(translationMatrix, velocity->x, velocity->y, 0); // NOTE: Corner wonky, need to implement with rotation } } }