/* This function reflects an animated circle on a static circle. It should first make sure that the animated circle is intersecting with the static one - Parameters - Center0s: The starting position of the animated circle's center - Center0e: The ending position of the animated circle's center - Radius0: The animated circle's radius - Center1: The static circle's center - Radius1: The static circle's radius - Pi: This will be used to store the intersection point's coordinates (In case there's an intersection) - R: Reflected vector R - Returned value: Intersection time t - -1.0f: If there's no intersection - Intersection time: If there's an intersection */ float ReflectAnimatedCircleOnStaticCircle(Vector2D *Center0s, Vector2D *Center0e, float Radius0, Vector2D *Center1, float Radius1, Vector2D *Pi, Vector2D *R) { Vector2D U; //(U is the adjusted normal) Vector2D M; //(M is from Ps to Pi) Vector2D Normal; float UScalar; float IntersectionTime = AnimatedCircleToStaticCircle(Center0s, Center0e, Radius0, Center1, Radius1, Pi); if (IntersectionTime == -1.0f) return -1.0f; // Calculating Normal Vector2DSub(&Normal, Pi, Center1); Vector2DNormalize(&Normal, &Normal); // Calculating Vector M (M is from Ps to Pi) Vector2DSub(&M, Center0s, Pi); //Calculating Vector U (U is the adjusted normal) UScalar = Vector2DDotProduct(&M, &Normal); Vector2DScale(&U, &Normal, UScalar); //Calculating R (R is the reflection Vector) Vector2DScale(&U, &U, 2.0f); Vector2DSub(R, &U, &M); Vector2DNormalize(R, R); return IntersectionTime; }
/* This function checks whether an animated circle is colliding with a line segment - Parameters - Ps: The center's starting location - Pe: The center's ending location - Radius: The circle's radius - LS: The line segment - Pi: This will be used to store the intersection point's coordinates (In case there's an intersection) - Returned value: Intersection time t - -1.0f: If there's no intersection - Intersection time: If there's an intersection */ float AnimatedCircleToStaticLineSegment(Vector2D *Ps, Vector2D *Pe, float Radius, LineSegment2D *LS, Vector2D *Pi) { Vector2D Vector; Vector2D P1Vector; Vector2D P0Vector; float InsideorOutside; float P1P0Dot; float IntersectionTime; float temp1; float temp2; if (StaticPointToStaticLineSegment(Ps, LS) < -Radius && StaticPointToStaticLineSegment(Pe, LS) < -Radius) { return NO_INTERSECTION; } else if (StaticPointToStaticLineSegment(Ps, LS) > Radius && StaticPointToStaticLineSegment(Pe, LS) > Radius) { return NO_INTERSECTION; } InsideorOutside = StaticPointToStaticLineSegment(Ps, LS); temp1 = Vector2DDotProduct(&LS->mN, Ps); temp1 = LS->mNdotP0 - temp1; if (InsideorOutside > 0) temp1 += Radius; else if (InsideorOutside < 0) temp1 -= Radius; Vector2DSub(&Vector, Pe, Ps); temp2 = Vector2DDotProduct(&LS->mN, &Vector); IntersectionTime = temp1 / temp2; if (IntersectionTime >= 0 && IntersectionTime <= 1) { Vector2DScale(&Vector, &Vector, IntersectionTime); Vector2DAdd(Pi, Ps, &Vector); Vector2DSub(&P1Vector, Pi, &LS->mP1); Vector2DSub(&P0Vector, Pi, &LS->mP0); P1P0Dot = Vector2DDotProduct(&P0Vector, &P1Vector); if (P1P0Dot < 0) { return IntersectionTime; } else { return NO_INTERSECTION; } } return NO_INTERSECTION; }
/* This function reflects an animated circle on a line segment. It should first make sure that the animated point is intersecting with the line - Parameters - Ps: The center's starting location - Pe: The center's ending location - Radius: The circle's radius - LS: The line segment - Pi: This will be used to store the intersection point's coordinates (In case there's an intersection) - R: Reflected vector R - Returned value: Intersection time t - -1.0f: If there's no intersection - Intersection time: If there's an intersection */ float ReflectAnimatedCircleOnStaticLineSegment(Vector2D *Ps, Vector2D *Pe, float Radius, LineSegment2D *LS, Vector2D *Pi, Vector2D *R) { float IntersectionTime = AnimatedCircleToStaticLineSegment(Ps, Pe, Radius, LS, Pi); float Scalar; Vector2D I; Vector2D S; Vector2D Vector; if (IntersectionTime == NO_INTERSECTION) { return NO_INTERSECTION; } Vector2DSub(&I, Pe, Pi); // Creates the I vector Scalar = Vector2DDotProduct(&I, &LS->mN); // Creates the scalar needed for the s vector Vector2DScale(&S, &LS->mN, Scalar); // Creates the S vector Vector2DSub(R, &I, &S); Vector2DSub(R, R, &S); return IntersectionTime; }
/* This function checks whether an animated point is colliding with a static circle - Parameters - Ps: The point's starting location - Pe: The point's ending location - Center: The circle's center - Radius: The circle's radius - Pi: This will be used to store the intersection point's coordinates (In case there's an intersection) - Returned value: Intersection time t - -1.0f: If there's no intersection - Intersection time: If there's an intersection */ float AnimatedPointToStaticCircle(Vector2D *Ps, Vector2D *Pe, Vector2D *Center, float Radius, Vector2D *Pi) { float A = 0; float B = 0; float C = 0; float Deter = 0; float IntersectionTime = 0; float Ti0 = 0; float Ti1 = 0; Vector2D PstoCenter; Vector2D Vector; Vector2D Temp; Vector2DSub(&Vector, Pe, Ps); Vector2DSub(&PstoCenter, Center, Ps); Vector2DSub(&Temp, Center, Ps); // A Solved Here! A = Vector2DDotProduct(&Vector, &Vector); // B Solved Here! Vector2DScale(&Temp, &PstoCenter, -2.0f); B = Vector2DDotProduct(&Temp, &Vector); // C Solved Here! C = Vector2DDotProduct(&PstoCenter, &PstoCenter); C -= (Radius * Radius); // Solving for (B^2 - 4AC) Deter += (B * B); Deter -= (4 * A * C); if (Deter < 0) return -1.0f; else if (Deter == 0) IntersectionTime = (-B / (2 * A)); else if (Deter > 0) { Ti0 = (-B - sqrt(Deter)) / (2 * A); Ti1 = (-B + sqrt(Deter)) / (2 * A); if (Ti0 > Ti1) IntersectionTime = Ti1; else IntersectionTime = Ti0; } Vector2DScaleAdd(Pi, &Vector, Ps, IntersectionTime); return IntersectionTime; }
/* This function checks whether an animated point is colliding with a line segment - Parameters - Ps: The point's starting location - Pe: The point's ending location - LS: The line segment - Pi: This will be used to store the intersection point's coordinates (In case there's an intersection) - Returned value: Intersection time t - -1.0f: If there's no intersection - Intersection time: If there's an intersection */ float AnimatedPointToStaticLineSegment(Vector2D *Ps, Vector2D *Pe, LineSegment2D *LS, Vector2D *Pi) { Vector2D Vector; Vector2D P1Vector; Vector2D P0Vector; float P1P0Dot; float IntersectionTime; float temp1; float temp2; temp1 = Vector2DDotProduct(&LS->mN, Ps); temp1 = LS->mNdotP0 - temp1; Vector2DSet(&Vector, Pe->x - Ps->x, Pe->y - Ps->y); temp2 = Vector2DDotProduct(&LS->mN, &Vector); IntersectionTime = temp1 / temp2; if (IntersectionTime >= 0 && IntersectionTime <= 1) { Vector2DScale(&Vector, &Vector, IntersectionTime); Vector2DAdd(Pi, Ps, &Vector); Vector2DSet(&P1Vector, Pi->x - LS->mP1.x, Pi->y - LS->mP1.y); Vector2DSet(&P0Vector, Pi->x - LS->mP0.x, Pi->y - LS->mP0.y); P1P0Dot = Vector2DDotProduct(&P0Vector, &P1Vector); if (P1P0Dot < 0) { return IntersectionTime; } else { return NO_INTERSECTION; } } else { return NO_INTERSECTION; } }
/* This function checks whether an animated circle is colliding with a static circle - Parameters - Center0s: The starting position of the animated circle's center - Center0e: The ending position of the animated circle's center - Radius0: The animated circle's radius - Center1: The static circle's center - Radius1: The static circle's radius - Pi: This will be used to store the intersection point's coordinates (In case there's an intersection) - Returned value: Intersection time t - -1.0f: If there's no intersection - Intersection time: If there's an intersection */ float AnimatedCircleToStaticCircle(Vector2D *Center0s, Vector2D *Center0e, float Radius0, Vector2D *Center1, float Radius1, Vector2D *Pi) { float A = 0; float B = 0; float C = 0; float Deter = 0; float IntersectionTime = 0; float Ti0 = 0; float Ti1 = 0; float M; Vector2D PstoCenter; Vector2D Vector; Vector2D Temp; Vector2DSub(&Vector, Center0e, Center0s); Vector2DSub(&PstoCenter, Center1, Center0s); Vector2DSub(&Temp, Center1, Center0s); M = Vector2DDotProduct(&PstoCenter, &Vector); if (M < 0) return -1.0f; // A Solved Here! A = Vector2DDotProduct(&Vector, &Vector); // B Solved Here! Vector2DScale(&Temp, &PstoCenter, -2.0f); B = Vector2DDotProduct(&Temp, &Vector); // C Solved Here! C = Vector2DDotProduct(&PstoCenter, &PstoCenter); C -= (Radius1 + Radius0) * (Radius1 + Radius0); // Solving for (B^2 - 4AC) Deter += (B * B); Deter -= (4 * A * C); if (Deter < 0) return -1.0f; else if (Deter == 0) IntersectionTime = (-B / (2 * A)); else if (Deter > 0) { Ti0 = (-B - sqrt(Deter)) / (2 * A); Ti1 = (-B + sqrt(Deter)) / (2 * A); if (Ti0 > Ti1) IntersectionTime = Ti1; else IntersectionTime = Ti0; } if (IntersectionTime > 0 && IntersectionTime < 1) { Vector2DScaleAdd(Pi, &Vector, Center0s, IntersectionTime); return IntersectionTime; } return -1.0f; }
int main() { Vector2D v1, v2, v3, result; float scale; Matrix2D id, m0, m1; Vector2D u; float d, x, y; long n; long i, j; float radius; v1.x = v1.y = 7.0f; Vector2DZero(&v1); result.x = result.y = 0.0f; printf("Vector2DZero: %s\n", (CompareVector2D(&result, &v1) < EPSILON) ? "Pass" : "Fail"); Vector2DSet(&v1, 1.0f, 2.0f); result.x = 1.0f; result.y = 2.0f; printf("Vector2DSet: %s\n", (CompareVector2D(&result, &v1) < EPSILON) ? "Pass" : "Fail"); v1.x = 2.0f; v1.y = -4.0f; Vector2DNeg(&v2, &v1); result.x = -2.0f; result.y = 4.0f; printf("Vector2DNeg: %s\n", (CompareVector2D(&result, &v2) < EPSILON) ? "Pass" : "Fail"); v1.x = 2.0f; v1.y = -4.0f; v2.x = 1.0f; v2.y = 7.0f; Vector2DAdd(&v3, &v1, &v2); result.x = result.y = 3.0f; printf("Vector2DAdd: %s\n", (CompareVector2D(&result, &v3) < EPSILON) ? "Pass" : "Fail"); v1.x = 2.0f; v1.y = -4.0f; v2.x = 1.0f; v2.y = 7.0f; Vector2DSub(&v3, &v1, &v2); result.x = 1.0f; result.y = -11.0f; printf("Vector2DSub: %s\n", (CompareVector2D(&result, &v3) < EPSILON) ? "Pass" : "Fail"); v1.x = 3.0f; v1.y = 4.0f; Vector2DNormalize(&v2, &v1); result.x = 0.6f; result.y = 0.8f; printf("Vector2DNormalize: %s\n", (CompareVector2D(&result, &v2) < EPSILON) ? "Pass" : "Fail"); v1.x = 2.0f; v1.y = -5.0f; Vector2DScale(&v2, &v1, 3.0f); result.x = 6.0f; result.y = -15.0f; printf("Vector2DScale: %s\n", (CompareVector2D(&result, &v2) < EPSILON) ? "Pass" : "Fail"); v1.x = 2.0f; v1.y = -5.0f; v2.x = 6.0f; v2.y = 2.0f; scale = 3.0f; Vector2DScaleAdd(&v3, &v1, &v2, scale); result.x = 12.0f; result.y = -13.0f; printf("Vector2DScaleAdd: %s\n", (CompareVector2D(&result, &v3) < EPSILON) ? "Pass" : "Fail"); Vector2DScaleSub(&v3, &v1, &v2, scale); result.x = 0.f; result.y = -17.f; printf("Vector2DScaleSub: %s\n", (CompareVector2D(&result, &v3) < EPSILON) ? "Pass" : "Fail"); v1.x = 3.0f; v1.y = -4.0f; printf("Vector2DLength: %s\n", (fabs(Vector2DLength(&v1) - 5.0f) < EPSILON) ? "Pass" : "Fail"); v1.x = 3.0f; v1.y = -4.0f; printf("Vector2DSquareLength: %s\n", (fabs(Vector2DSquareLength(&v1) - 25.0f) < EPSILON) ? "Pass" : "Fail"); v1.x = 2.0f; v1.y = 3.0f; v2.x = 4.0f; v2.y = -1.0f; printf("Vector2DDistance: %s\n", (fabs(Vector2DDistance(&v1, &v2) - 4.472136) < EPSILON) ? "Pass" : "Fail"); v1.x = 2.0f; v1.y = 3.0f; v2.x = 4.0f; v2.y = -1.0f; printf("Vector2DSquareDistance: %s\n", (fabs(Vector2DSquareDistance(&v1, &v2) - 20.0f) < EPSILON) ? "Pass" : "Fail"); v1.x = 3.0f; v1.y = 2.0f; v2.x = 4.0f; v2.y = -6.0f; printf("Vector2DDotProduct: %s\n", (fabs(Vector2DDotProduct(&v1, &v2)) < EPSILON) ? "Pass" : "Fail"); printf("\n------Testing StaticPointToStaticCircle------\n\n"); v1.x = 10.f; v1.y = 10.f; v2.x = 11.4f; v2.y = 11.4f; radius = 2.f; printf("StaticPointToStaticCircle Collision: %s\n", (StaticPointToStaticCircle(&v2, &v1, radius)) ? "Pass" : "Fail" ); v2.x = 12.f; v2.y = 12.f; printf("StaticPointToStaticCircle Non Collision: %s\n", (!StaticPointToStaticCircle(&v2, &v1, radius)) ? "Pass" : "Fail" ); printf("\n------Running Matrix Tests------\n\n"); // create an id matrix for reference for (i = 0; i < 3; i++) for (j = 0; j < 3; j++) id.m[j][i] = (i == j) ? 1.0f : 0.0f; // ==================== // test Matrix2DIdentity // ==================== Matrix2DIdentity(&m0); d = CompareMatrix2D(&id, &m0); printf("Matrix2DIdentity : %s\n", (CompareMatrix2D(&id, &m0) < EPSILON) ? "Pass" : "Fail"); // ==================== // test Matrix2DTrans // ==================== // generate 2 random numbers x = 2.0f * rand() / (float)(RAND_MAX) - 1.0f; y = 2.0f * rand() / (float)(RAND_MAX) - 1.0f; Matrix2DTranslate(&m0, x, y); m0.m[0][2] -= x; m0.m[1][2] -= y; printf("Matrix2DTranslate: %s\n", (CompareMatrix2D(&id, &m0) < EPSILON) ? "Pass" : "Fail"); // ==================== // test Matrix2DScale // ==================== // generate 2 random numbers x = 2.0f * rand() / (float)(RAND_MAX) - 1.0f; y = 2.0f * rand() / (float)(RAND_MAX) - 1.0f; Matrix2DScale(&m0, x, y); m0.m[0][0] /= x; m0.m[1][1] /= y; printf("Matrix2DScale : %s\n", (CompareMatrix2D(&id, &m0) < EPSILON) ? "Pass" : "Fail"); // ==================== // test Matrix2DConcat // ==================== // generate 2 random numbers x = 2.0f * rand() / (float)(RAND_MAX) - 1.0f; y = 2.0f * rand() / (float)(RAND_MAX) - 1.0f; Matrix2DTranslate (&m0, x, y); Matrix2DScale (&m1, x, y); Matrix2DConcat(&m0, &m0, &m1); m0.m[0][2] -= x; m0.m[1][2] -= y; m0.m[0][0] /= x; m0.m[1][1] /= y; printf("Matrix2DConcat 1 : %s\n", (CompareMatrix2D(&id, &m0) < EPSILON) ? "Pass" : "Fail"); // generate 2 random numbers x = 2.0f * rand() / (float)(RAND_MAX) - 1.0f; y = 2.0f * rand() / (float)(RAND_MAX) - 1.0f; Matrix2DTranslate (&m0, x, y); Matrix2DScale (&m1, x, y); Matrix2DConcat(&m0, &m1, &m0); m0.m[0][2] -= x * x; m0.m[1][2] -= y * y; m0.m[0][0] /= x; m0.m[1][1] /= y; printf("Matrix2DConcat 2 : %s\n", (CompareMatrix2D(&id, &m0) < EPSILON) ? "Pass" : "Fail"); // ==================== // test Matrix2DRotRad // ==================== n = (rand() % 16) + 15; Matrix2DIdentity(&m0); Matrix2DRotRad (&m1, 2.0f * PI / n); for (i = 0; i < n; i++) Matrix2DConcat(&m0, &m1, &m0); printf("Matrix2DRotRad : %s (%d)\n", (CompareMatrix2D(&id, &m0) < EPSILON) ? "Pass" : "Fail", n); // ==================== // test Matrix2DRotDeg // ==================== n = (rand() % 16) + 15; Matrix2DIdentity(&m0); Matrix2DRotDeg (&m1, 360.0f / n); for (i = 0; i < n; i++) Matrix2DConcat(&m0, &m1, &m0); printf("Matrix2DRotDeg : %s (%d)\n", (CompareMatrix2D(&id, &m0) < EPSILON) ? "Pass" : "Fail", n); // ==================== // test Matrix2DTranspose // ==================== Matrix2DRotRad (&m0, rand() / (float)(RAND_MAX) * 2.0f * PI); Matrix2DTranspose(&m1, &m0); Matrix2DConcat (&m0, &m1, &m0); printf("Matrix2DTranspose: %s\n", (CompareMatrix2D(&id, &m0) < EPSILON) ? "Pass" : "Fail"); // ==================== // test Matrix2DMultVec // ==================== // generate 2 random numbers x = 2.0f * rand() / (float)(RAND_MAX) - 1.0f; y = 2.0f * rand() / (float)(RAND_MAX) - 1.0f; n = (rand() % 16) + 15; Vector2DSet (&u, x, y); Matrix2DRotRad (&m0, 2.0f * PI / n); for (i = 0; i < n; i++) Matrix2DMultVec(&u, &m0, &u); printf("Matrix2DMultVec : %s\n", ((fabs(u.x - x) + fabs(u.y - y)) < EPSILON) ? "Pass" : "Fail"); // generate 2 random numbers x = 2.0f * rand() / (float)(RAND_MAX) - 1.0f; y = 2.0f * rand() / (float)(RAND_MAX) - 1.0f; n = (rand() % 16) + 15; Vector2DSet (&u, x, y); Matrix2DTranslate (&m0, x, y); for (i = 1; i < n; i++) Matrix2DMultVec(&u, &m0, &u); printf("Matrix2DMultVec : %s\n", ((fabs(u.x - x * n) + fabs(u.y - y * n)) < EPSILON) ? "Pass" : "Fail"); printf("\n------Testing New Collision Functions------\n\n"); //StaticPointToStaticRect Vector2DSet(&v1, 1.f, 1.f); //point Vector2DSet(&v2, 0.f, 0.f); //rect printf("StaticPointToStaticRect Collision: %s\n", (StaticPointToStaticRect(&v1, &v2, 2.f, 2.f) ? "Pass" : "Fail")); printf("StaticPointToStaticRect Non Collision: %s\n\n", (!StaticPointToStaticRect(&v1, &v2, 1.f, 1.f) ? "Pass" : "Fail")); //StaticCircleToStaticCircle Vector2DSet(&v1, 2.f, 0.f); printf("StaticCircleToStaticCircle Collision Touch: %s\n", (StaticCircleToStaticCircle(&v1, 1.f, &v2, 1.f) ? "Pass" : "Fail")); printf("StaticCircleToStaticCircle Collision: %s\n", (StaticCircleToStaticCircle(&v1, 2.f, &v2, 1.f) ? "Pass" : "Fail")); printf("StaticCircleToStaticCircle Non Collision: %s\n\n", (!StaticCircleToStaticCircle(&v1, 0.5f, &v2, 1.f) ? "Pass" : "Fail")); //StaticRectToStaticRect Vector2DSet(&v1, 2.f, 2.f); printf("StaticRectToStaticRect Non Collision: %s\n", (!StaticRectToStaticRect(&v1, 1.f, 1.f, &v2, 1.f, 1.f) ? "Pass" : "Fail")); printf("StaticRectToStaticRect Collision Touch: %s\n", (StaticRectToStaticRect(&v1, 2.f, 2.f, &v2, 2.f, 2.f) ? "Pass" : "Fail")); printf("StaticRectToStaticRect Collision Intersect: %s\n", (StaticRectToStaticRect(&v1, 3.f, 3.f, &v2, 3.f, 3.f) ? "Pass" : "Fail")); return 1; }
void Vector2DScaleSub(Vector2D &Result, const Vector2D &Vec0, const Vector2D &Vec1, float c) { Vector2DScale(Result, Vec0, c); Vector2DSub(Result, Result, Vec1); }
void Vector2DScaleAdd(Vector2D &Result, const Vector2D &Vec0, const Vector2D &Vec1, float c) { Vector2D tempScale; Vector2DScale(tempScale, Vec0, c); Vector2DAdd(Result, tempScale, Vec1); }
void Vector2DScaleSub(Vector2D *pResult, Vector2D *pVec0, Vector2D *pVec1, float c) { Vector2DScale(pResult, pVec0, c); Vector2DSub(pResult, pResult, pVec1); }
void Vector2DScaleAdd(Vector2D *pResult, Vector2D *pVec0, Vector2D *pVec1, float c) { Vector2DScale(pResult, pVec0, c); Vector2DAdd(pResult, pResult, pVec1); }
void Vector2DNormalize(Vector2D *pResult, Vector2D *pVec0) { Vector2DScale(pResult, pVec0, (1 / Vector2DLength(pVec0))); }