1 module ws.math.collision; 2 3 4 import 5 ws.math.math, 6 ws.math.vector; 7 8 9 struct Line { 10 float[3] origin; 11 float[3] dir; 12 } 13 14 struct Plane { 15 float[3] origin; 16 float[3] normal; 17 } 18 19 struct Cube { 20 float[3] origin; 21 float scale; 22 } 23 24 class Result { 25 bool hit; 26 } 27 28 class LinePlaneResult: Result { 29 float[3] pos; 30 } 31 32 class LineCubeResult: Result { 33 float[3] pos; 34 float[3] normal; 35 float distance; 36 } 37 38 LinePlaneResult collide(Line line, Plane plane){ 39 auto numerator = (plane.origin.vec - line.origin.vec) * plane.normal.vec; 40 auto denominator = line.dir.vec*plane.normal.vec; 41 auto res = new LinePlaneResult; 42 res.hit = numerator/denominator > 0.0001; 43 res.pos = line.origin.vec + line.dir.vec*(numerator/denominator); 44 return res; 45 } 46 47 48 LineCubeResult collide(Line line, Cube cube){ 49 50 auto lb = cube.origin.vec-vec(1,1,1)/2*cube.scale; 51 auto rt = cube.origin.vec+vec(1,1,1)/2*cube.scale; 52 53 float[3] dirfrac; 54 dirfrac.x = 1.0f / line.dir.x; 55 dirfrac.y = 1.0f / line.dir.y; 56 dirfrac.z = 1.0f / line.dir.z; 57 58 float t1 = (lb.x - line.origin.x)*dirfrac.x; 59 float t2 = (rt.x - line.origin.x)*dirfrac.x; 60 float t3 = (lb.y - line.origin.y)*dirfrac.y; 61 float t4 = (rt.y - line.origin.y)*dirfrac.y; 62 float t5 = (lb.z - line.origin.z)*dirfrac.z; 63 float t6 = (rt.z - line.origin.z)*dirfrac.z; 64 65 float tmin = fmax(fmax(fmin(t1, t2), fmin(t3, t4)), fmin(t5, t6)); 66 float tmax = fmin(fmin(fmax(t1, t2), fmax(t3, t4)), fmax(t5, t6)); 67 68 if (tmax < 0 || tmin > tmax) 69 return null; 70 71 auto res = new LineCubeResult; 72 res.distance = tmin; 73 res.pos = line.origin.vec + line.dir.vec*res.distance; 74 auto help = (res.pos.vec - cube.origin.vec)/cube.scale*2.0001; 75 res.normal = help.to!int.to!float; 76 return res; 77 } 78 79 80 float[3] line_plane(float[3] lineStart, float[3] lineDir, float[3] planeOrigin, float[3] planeNormal){ 81 auto numerator = (vec(planeOrigin) - vec(lineStart)) * vec(planeNormal); 82 auto denominator = vec(lineDir)*vec(planeNormal); 83 return vec(lineStart) + vec(lineDir)*(numerator/denominator); 84 }