Advertisement
Guest User

Untitled

a guest
Oct 10th, 2014
175
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Scala 9.95 KB | None | 0 0
  1. // Math utility object, define these in terms of libgdx or whatever
  2. object MathU {
  3.     def sqrt(a: Float) = Math.sqrt(a).toFloat
  4.     def cos(theta: Float) = Math.cos(theta).toFloat
  5.     def sin(theta: Float) = Math.sin(theta).toFloat
  6.     def min(a: Float, b: Float) = if (a < b) a else b
  7.     def max(a: Float, b: Float) = if (a > b) a else b
  8.     def minmax(values: List[Float]): Tuple2[Float, Float] = {
  9.         def f(v: List[Float], mini: Float, maxi: Float): Tuple2[Float, Float] = v match {
  10.             case Nil => (mini, maxi)
  11.             case x :: xs => f(xs, min(x, mini), max(x, maxi))
  12.         }
  13.         f(values.tail, values.head, values.head)
  14.     }
  15.     def clamp(v: Float, a: Float, b: Float) = v match {
  16.         case x if (x < a) => a
  17.         case x if (x > b) => b
  18.         case _ => v
  19.     }
  20. }
  21.  
  22. import MathU._
  23.  
  24. class Vec(var x: Float, var y: Float) {
  25.  
  26.     def +(that: Vec) = Vec(x+that.x, y+that.y)
  27.     def -(that:Vec) = Vec(x-that.x, y-that.y)
  28.     def *(s: Float) = Vec(s*x, s*y)
  29.     def *(that: Vec) = Vec(x*that.x, y*that.y)
  30.     def dot(that:Vec) = that.x*x + that.y*y
  31.     def normal = Vec(y, -x).normalize
  32.     def length = sqrt(x*x+y*y)
  33.     def normalize = this * (1/length)
  34.     def proj(b: Vec) = b * ((this dot b)/(b dot b))
  35.     def rej(b: Vec) = this - proj(b)
  36.  
  37.     //Destructive variants, saves the resulting vector in the current vector
  38.     def +!(that: Vec) = {
  39.         x += that.x
  40.         y += that.y
  41.     }
  42.     def -!(that: Vec) = {
  43.         x -= that.x
  44.         y -= that.y
  45.     }
  46.     def *!(s: Float) = {
  47.         x *= s
  48.         y *= s
  49.     }
  50.     def *!(that: Vec) = {
  51.         x *= that.x
  52.         y *= that.y
  53.     }
  54.     def normalize_! = this *! (1/length)
  55.  
  56.     override def toString = "[" + x + " " + y + "]"
  57. }
  58.  
  59. object Vec{
  60.     def apply(x: Float, y: Float) = new Vec(x,y)
  61.     val i = new Vec(1, 0)
  62.     val j = new Vec(0, 1)
  63. }
  64.  
  65. class Mat(private val arr: Array[Float]){
  66.  
  67.     def apply(i: Int, j: Int) = arr(i+j*3)
  68.     def update(i: Int, j: Int, f: Float) = {
  69.         arr(i+j*3) = f
  70.     }
  71.     def +(that: Mat) =  Mat(this(0,0)+that(0,0), this(1,0)+that(1,0), this(2,0)+that(2,0),
  72.                             this(0,1)+that(0,1), this(1,1)+that(1,1), this(2,1)+that(2,1),
  73.                             this(0,2)+that(0,2), this(1,2)+that(1,2), this(2,2)+that(2,2))
  74.     def *(s: Float) =   Mat(this(0,0)*s, this(1,0)*s, this(2,0)*s,
  75.                             this(0,1)*s, this(1,1)*s, this(2,1)*s,
  76.                             this(0,2)*s, this(1,2)*s, this(2,2)*s)
  77.     def *(v: Vec) = Vec(this(0,0)*v.x + this(1,0)*v.y+this(2,0), this(0,1)*v.x + this(1,1)*v.y+this(1,2))
  78.     def *(that: Mat) = Mat(this(0,0)*that(0,0) + this(1,0)*that(0,1) + this(2,0)*that(0,2),
  79.                            this(0,0)*that(1,0) + this(1,0)*that(1,1) + this(2,0)*that(1,2),
  80.                            this(0,0)*that(2,0) + this(1,0)*that(2,1) + this(2,0)*that(2,2),
  81.                            this(0,1)*that(0,0) + this(1,1)*that(0,1) + this(2,1)*that(0,2),
  82.                            this(0,1)*that(1,0) + this(1,1)*that(1,1) + this(2,1)*that(1,2),
  83.                            this(0,1)*that(2,0) + this(1,1)*that(2,1) + this(2,1)*that(2,2),
  84.                            this(0,2)*that(0,0) + this(1,2)*that(0,1) + this(2,2)*that(0,2),
  85.                            this(0,2)*that(1,0) + this(1,2)*that(1,1) + this(2,2)*that(1,2),
  86.                            this(0,2)*that(2,0) + this(1,2)*that(2,1) + this(2,2)*that(2,2))
  87.  
  88.     //Destructive variants, saves the resulting matrix in the current matrix
  89.     def +!(that: Mat) = {
  90.         this(0,0) += that(0,0); this(1,0) += that(1,0); this(2,0) += that(2,0)
  91.         this(0,1) += that(0,1); this(1,1) += that(1,1); this(2,1) += that(2,1)
  92.         this(0,2) += that(0,2); this(1,2) += that(1,2); this(2,2) += that(2,2)
  93.     }
  94.     def *!(s: Float) = {
  95.         this(0,0) *= s; this(1,0) *= s; this(2,0) *= s
  96.         this(0,1) *= s; this(1,1) *= s; this(2,1) *= s
  97.         this(0,2) *= s; this(1,2) *= s; this(2,2) *= s
  98.     }
  99.     // Saves result into the vector
  100.     def *!(v: Vec) = {
  101.         v.x = this(0,0)*v.x + this(1,0)*v.y + this(2,0)
  102.         v.y = this(0,1)*v.x + this(1,1)*v.y + this(1,2)
  103.     }
  104.     def *!(that: Mat) = {
  105.         this(0,0) = this(0,0)*that(0,0) + this(1,0)*that(0,1) + this(2,0)*that(0,2)
  106.         this(1,0) = this(0,0)*that(1,0) + this(1,0)*that(1,1) + this(2,0)*that(1,2)
  107.         this(2,0) = this(0,0)*that(2,0) + this(1,0)*that(2,1) + this(2,0)*that(2,2)
  108.         this(0,0) = this(0,1)*that(0,0) + this(1,1)*that(0,1) + this(2,1)*that(0,2)
  109.         this(1,0) = this(0,1)*that(1,0) + this(1,1)*that(1,1) + this(2,1)*that(1,2)
  110.         this(2,0) = this(0,1)*that(2,0) + this(1,1)*that(2,1) + this(2,1)*that(2,2)
  111.         this(0,0) = this(0,2)*that(0,0) + this(1,2)*that(0,1) + this(2,2)*that(0,2)
  112.         this(1,0) = this(0,2)*that(1,0) + this(1,2)*that(1,1) + this(2,2)*that(1,2)
  113.         this(2,0) = this(0,2)*that(2,0) + this(1,2)*that(2,1) + this(2,2)*that(2,2)
  114.     }
  115.  
  116.     override def toString = "[" + arr(0) + " " + arr(1) + " " + arr(2) + " | " +
  117.                                   arr(3) + " " + arr(4) + " " + arr(5) + " | " +  
  118.                                   arr(6) + " " + arr(7) + " " + arr(8) + "]"
  119. }
  120.  
  121. object Mat{
  122.     def apply(m00: Float, m10: Float, m20: Float,
  123.               m01: Float, m11: Float, m21: Float,
  124.               m02: Float, m12: Float, m22: Float): Mat = new Mat(Array(m00, m10, m20, m01, m11, m21, m02, m12, m22))
  125.     def apply(arr: Array[Float]): Mat = if (arr.size == 9) new Mat(arr) else I
  126.  
  127.     //Transformation matrices, compose transformations out of these
  128.     val I = Mat(1, 0, 0, 0, 1, 0, 0, 0, 1)
  129.     def translate(x: Float, y: Float) = Mat(1, 0, x, 0, 1, y, 0, 0, 1)
  130.     def scale(w: Float, h: Float) = Mat(w, 0, 0, 0, h, 0, 0, 0, 1)
  131.     def rotate(theta: Float) = {val c = cos(theta); val s = sin(theta); Mat(c, -s, 0, s, c, 0, 0, 0, 1)}
  132.     def shear(x: Float, y: Float) = Mat(1, x, 0, y, 1, 0, 0, 0, 1)
  133.     def reflect(v: Vec) = {val n = v.normalize; Mat(n.x*n.x-n.y*n.y, 2*n.x*n.y, 0, 2*n.x*n.y, n.y*n.y-n.x*n.x, 0, 0, 0, 1)}
  134.     def project(v: Vec) = {val n = v.normalize; Mat(n.x*n.x, n.x*n.y, 0, n.x*n.y, n.y*n.y, 0, 0, 0, 1)}
  135. }
  136.  
  137. import MathU._
  138.  
  139. sealed abstract class Shape
  140. case class Point(p: Vec) extends Shape
  141. case class Circle(p: Vec, r: Float) extends Shape
  142. case class AABB(p: Vec, w: Float, h: Float) extends Shape
  143. case class Polygon(p: Vec, vertices: List[Vec], normals: List[Vec]) extends Shape
  144.  
  145. object Polygon{
  146.     def apply(p: Vec, vs: List[Vec]): Polygon = new Polygon(p, vs,
  147.         getNormals(vs.head, vs.tail, (vs.head-vs(1)).normal :: Nil) reverse)
  148.  
  149.     def getNormals(f: Vec, vs: List[Vec], r: List[Vec]): List[Vec] = vs match {
  150.         case x :: Nil => (f-x).normal :: r
  151.         case x :: xs => getNormals(f, xs, (xs.head-x).normal :: r)
  152.     }
  153. }
  154.  
  155. object CollisionQ{
  156.     // ORTHOGONAL PROJETION OF A VECTOR v ON A LINE DESCRIBED BY A VECTOR l
  157.     //     v dot l
  158.     // p = ------- * l     or   p = (v dot l) * l if l is a unit vector
  159.     //     l dot l
  160.  
  161.     // All projection vectors should be normalized for these functions to work
  162.  
  163.     //Scalar shadows, shadow(a, l)*l would be the cartesian vector
  164.     def shadow(p: Point, line: Vec) = {
  165.         val po = p.p dot line
  166.         (po, po)
  167.     }
  168.     def shadow(cir: Circle, line: Vec) = {
  169.         val po = cir.p dot line
  170.         (-cir.r + po, +cir.r + po)
  171.     }
  172.     def shadow(box: AABB, line: Vec) = {
  173.         val s = minmax(List((box.p.x+box.w)*line.x+(box.p.y+box.h)*line.y,
  174.                             (box.p.x-box.w)*line.x+(box.p.y+box.h)*line.y,
  175.                             (box.p.x+box.w)*line.x+(box.p.y-box.h)*line.y,
  176.                             (box.p.x-box.w)*line.x+(box.p.y-box.h)*line.y))
  177.         val po = box.p dot line
  178.         (s._1 + po, s._2 + po)
  179.     }
  180.     def shadow(poly: Polygon, line: Vec) = {
  181.         val s = minmax(poly.vertices map (a => a dot line))
  182.         val po = poly.p dot line
  183.         (s._1 + po, s._2 + po)
  184.     }
  185.  
  186.     //Tests if two shadows intersect
  187.     def between(f: Float, r: Tuple2[Float, Float]) = (r._1 < f) && (f < r._2)
  188.     def intersects(a: Tuple2[Float, Float], b: Tuple2[Float, Float]) = between(a._1, b) || between(b._1, a)
  189.  
  190.     //Tests for intersection
  191.     def collides(p: Point, p2: Point): Boolean = (p.p.x == p2.p.x && p.p.y == p2.p.y)
  192.     def collides(p: Point, c: Circle): Boolean = {
  193.         val dist = p.p - c.p
  194.         dist.x*dist.x + dist.y*dist.y < c.r*c.r
  195.     }
  196.     def collides(p: Point, b: AABB): Boolean = {
  197.         val diff = p.p - b.p
  198.         (diff.x < b.w) && (diff.y < b.h)
  199.     }
  200.     def collides(p: Point, po: Polygon): Boolean = po.normals forall (n => between(p.p dot n, shadow(po, n)))
  201.     def collides(b: AABB, b2: AABB): Boolean = {
  202.         val diff = b.p - b2.p
  203.         (diff.x < b.w+b2.w) && (diff.y < b.h+b2.h)
  204.     }
  205.     def collides(b: AABB, c: Circle): Boolean =  {
  206.         val x = clamp(c.p.x, b.p.x-b.w, b.p.x+b.w)
  207.         val y = clamp(c.p.y, b.p.y-b.h, b.p.y+b.h)
  208.         x*x+y*y < c.r*c.r
  209.     }
  210.     def collides(b: AABB, po: Polygon): Boolean = {
  211.         val p = b.p; val w = b.w; val h = b.h
  212.         collides(Polygon(p, Vec(w, h) :: Vec(-w, h) :: Vec(-w, -h) :: Vec(w, -h) :: Nil), po)
  213.     }
  214.     def collides(c: Circle, c2: Circle): Boolean = {
  215.         val dist = c.p - c2.p; val rs = c.r+c2.r
  216.         dist.x*dist.x + dist.y*dist.y < rs*rs
  217.     }
  218.     def collides(c: Circle, po: Polygon): Boolean = {
  219.         def voronoi(p: Vec, poly: Polygon) = {
  220.             def d2(a: Vec, b: Vec) = {
  221.                 val x = (a.x-b.x)
  222.                 val y = (a.y-b.y)
  223.                 x*x+y*y
  224.             }
  225.             var closest = poly.vertices.head + poly.p
  226.             var cd2 = d2(closest, p)
  227.             for(v <- poly.vertices.tail) {
  228.                 val vd2 = d2(v + poly.p, p)
  229.                 if(vd2 < cd2) {
  230.                     closest = v + poly.p
  231.                     cd2 = vd2
  232.                 }
  233.             }
  234.             closest
  235.         }
  236.         val sep = po.p - c.p
  237.         def f(ns: List[Vec]): Boolean = ns match{
  238.             case Nil => true
  239.             case x :: xs => {
  240.                 val sp = sep dot x
  241.                 val sa = shadow(c, x)
  242.                 if(intersects((sa._1 + sp, sa._2 + sp), shadow(po, x))) f(xs) else false
  243.             }
  244.         }
  245.         f(po.normals) && {val sep = voronoi(c.p, po) - po.p
  246.             sep.normalize_!
  247.             f(sep :: Nil)}
  248.     }
  249.     def collides(po: Polygon, po2: Polygon): Boolean = {
  250.         val sep = po2.p - po.p
  251.         def f(ns: List[Vec]): Boolean = ns match {
  252.             case Nil => true
  253.             case x :: xs => {
  254.                 val sp = sep dot x
  255.                 val sa = shadow(po, x)
  256.                 if (intersects( (sa._1 + sp, sa._2 + sp) , shadow(po2, x))) f(xs) else false
  257.             }
  258.         }
  259.         f(po.normals) && f(po2.normals)
  260.     }
  261.  
  262.     def collides(a: Shape, b: Shape): Boolean = (a, b) match {
  263.         case(a: Point, b: Point) => collides(a,b)
  264.         case(a: Point, b: Circle) => collides(a,b)
  265.         case(a: Point, b: AABB) => collides(a,b)
  266.         case(a: Point, b: Polygon) => collides(a,b)
  267.         case(a: AABB, b: AABB) => collides(a,b)
  268.         case(a: AABB, b: Circle) => collides(a,b)
  269.         case(a: AABB, b: Polygon) => collides(a,b)
  270.         case(a: Circle, b: Circle) => collides(a,b)
  271.         case(a: Circle, b: Polygon) => collides(a,b)
  272.         case(a: Polygon, b: Polygon) => collides(a,b)
  273.         case(a, b) => collides(b,a)
  274.     }
  275. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement