#include "pch.h" #include "maths.h" void maths::enclosing_box(rectangle_type* rect1, rectangle_type* rect2, rectangle_type* dstRect) { int xPos1 = rect1->XPosition; int yPos1 = rect1->YPosition; int width1 = rect1->Width; int height1 = rect1->Height; int xPos2 = rect2->XPosition; bool rect2XPosLessRect1 = rect2->XPosition < rect1->XPosition; int yPos2 = rect2->YPosition; int width2 = rect2->Width; int height2 = rect2->Height; int xPos2_2 = rect2->XPosition; if (rect2XPosLessRect1) { width1 += xPos1 - xPos2; xPos1 = xPos2; } if (yPos2 < yPos1) { height1 += yPos1 - yPos2; yPos1 = yPos2; } if (width2 + xPos2 > xPos1 + width1) width1 = xPos2_2 + width2 - xPos1; int height1_2 = height1; if (height2 + yPos2 > height1 + yPos1) height1_2 = yPos2 + height2 - yPos1; dstRect->YPosition = yPos1; dstRect->Height = height1_2; dstRect->XPosition = xPos1; dstRect->Width = width1; } int maths::rectangle_clip(rectangle_type* rect1, rectangle_type* rect2, rectangle_type* dstRect) { int xPos1 = rect1->XPosition; int yPos1 = rect1->YPosition; int height1 = rect1->Height; int xRight2 = rect2->XPosition + rect2->Width; int width1 = rect1->Width; int yRight2 = rect2->YPosition + rect2->Height; if (xPos1 + width1 < rect2->XPosition) return 0; if (xPos1 >= xRight2) return 0; int yPos2 = yPos1; if (yPos1 + height1 < rect2->YPosition || yPos1 >= yRight2) return 0; if (xPos1 < rect2->XPosition) { width1 += xPos1 - rect2->XPosition; xPos1 = rect2->XPosition; } if (xPos1 + width1 > xRight2) width1 = xRight2 - xPos1; int height2 = height1; if (yPos1 < rect2->YPosition) { height2 = yPos1 - rect2->YPosition + height1; yPos2 = rect2->YPosition; } if (height2 + yPos2 > yRight2) height2 = yRight2 - yPos2; if (!width1 || !height2) return 0; if (dstRect) { dstRect->XPosition = xPos1; dstRect->YPosition = yPos2; dstRect->Width = width1; dstRect->Height = height2; } return 1; } int maths::overlapping_box(rectangle_type* rect1, rectangle_type* rect2, rectangle_type* dstRect) { int v3; int v4; int v6; int v7; if (rect1->XPosition >= rect2->XPosition) { dstRect->XPosition = rect2->XPosition; v3 = rect1->Width - rect2->XPosition; v4 = rect1->XPosition; } else { dstRect->XPosition = rect1->XPosition; v3 = rect2->Width - rect1->XPosition; v4 = rect2->XPosition; } dstRect->Width = v3 + v4 + 1; int v5 = rect1->YPosition; if (v5 >= rect2->YPosition) { dstRect->YPosition = rect2->YPosition; v6 = rect1->Height - rect2->YPosition; v7 = rect1->YPosition; } else { dstRect->YPosition = v5; v6 = rect2->Height - rect1->YPosition; v7 = rect2->YPosition; } dstRect->Height = v6 + v7 + 1; return dstRect->Width <= rect2->Width + rect1->Width && dstRect->Height <= rect2->Height + rect1->Height; } float maths::ray_intersect_circle(ray_type* ray, circle_type* circle) { // O - ray origin // D - ray direction // C - circle center // R - circle radius // L, C - O, vector between O and C float Lx = circle->Center.X - ray->Origin.X; float Ly = circle->Center.Y - ray->Origin.Y; // Tca, L dot D, projection of L on D float Tca = Ly * ray->Direction.Y + Lx * ray->Direction.X; if (Tca < 0.0) // No intersection if Tca is negative return 1000000000.0f; // L dot L, distance from ray origin to circle center float LMagSq = Ly * Ly + Lx * Lx; // If ray origin is inside of the circle // T0 = Tca - Sqrt(rad^2 - d^2). d = sqrt(L dot L - Tca dot Tca) if (LMagSq < circle->RadiusSq) return Tca - sqrt(circle->RadiusSq - LMagSq + Tca * Tca); // Thc^2 = rad^2 - d = rad^2 - L dot L + Tca dot Tca float ThcSq = circle->RadiusSq - LMagSq + Tca * Tca; if (ThcSq < 0.0) // No intersection if Thc is negative return 1000000000.0f; // T0 = Tca - Thc, distance from origin to first intersection float T0 = Tca - sqrt(ThcSq); if (T0 < 0.0 || T0 > ray->MaxDistance) return 1000000000.0f; return T0; } float maths::normalize_2d(vector_type* vec) { float mag = sqrt(vec->X * vec->X + vec->Y * vec->Y); if (0.0 != mag) { vec->X = 1.0f / mag * vec->X; vec->Y = 1.0f / mag * vec->Y; } return mag; } void maths::line_init(line_type* line, float x0, float y0, float x1, float y1) { float v9; bool lineDirection; float v11; line->Direction.X = x1 - x0; line->Direction.Y = y1 - y0; normalize_2d(&line->Direction); line->PerpendicularL.X = line->Direction.Y; line->PerpendicularL.Y = -line->Direction.X; line->PreComp1 = -(line->Direction.Y * x0) + (line->Direction.X * y0); if (line->Direction.X >= 0.000000001 || line->Direction.X <= -0.000000001) { v9 = x1; lineDirection = x0 >= x1; v11 = x0; } else { line->Direction.X = 0.0; v9 = y1; lineDirection = y0 >= y1; v11 = y0; } if (lineDirection) { line->OriginX = v9; line->OriginY = v11; } else { line->OriginY = v9; line->OriginX = v11; } } float maths::ray_intersect_line(ray_type* ray, line_type* line) { // Similar to https://rootllama.wordpress.com/2014/06/20/ray-line-segment-intersection-test-in-2d/ float perpDot; float result; float v4; bool v5; bool v6; float v7; perpDot = line->PerpendicularL.Y * ray->Direction.Y + ray->Direction.X * line->PerpendicularL.X; if (perpDot < 0.0) { result = -((ray->Origin.X * line->PerpendicularL.X + ray->Origin.Y * line->PerpendicularL.Y + line->PreComp1) / perpDot); if (result >= -ray->MinDistance && result <= ray->MaxDistance) { line->CompTmp1 = result * ray->Direction.X + ray->Origin.X; v4 = result * ray->Direction.Y + ray->Origin.Y; line->Unknown10 = v4; if (0.0 == line->Direction.X) { if (v4 >= line->OriginX) { v5 = v4 < line->OriginY; v6 = v4 == line->OriginY; if (v5 || v6) return result; return 1000000000.0; } } else if (line->OriginX <= line->CompTmp1) { v7 = line->CompTmp1; v5 = v7 < line->OriginY; v6 = v7 == line->OriginY; if (v5 || v6) return result; return 1000000000.0; } } } return 1000000000.0; } void maths::cross(vector_type* vec1, vector_type* vec2, vector_type* dstVec) { dstVec->X = vec2->Z * vec1->Y - vec2->Y * vec1->Z; dstVec->Y = vec2->X * vec1->Z - vec1->X * vec2->Z; dstVec->Z = vec1->X * vec2->Y - vec2->X * vec1->Y; } float maths::magnitude(vector_type* vec) { float result; auto magSq = vec->X * vec->X + vec->Y * vec->Y + vec->Z * vec->Z; if (magSq == 0.0) result = 0.0; else result = sqrt(magSq); return result; } void maths::vector_add(vector_type* vec1Dst, vector_type* vec2) { vec1Dst->X += vec2->X; vec1Dst->Y += vec2->Y; }