diff options
| author | Marc Sunet <jeannekamikaze@gmail.com> | 2012-08-30 19:32:58 +0200 |
|---|---|---|
| committer | Marc Sunet <jeannekamikaze@gmail.com> | 2012-08-30 19:32:58 +0200 |
| commit | a502bf0a62c38a789c1325d6f1082d5ff2af612c (patch) | |
| tree | 172f49eebad0af0b92598419ec3b99fd62939efc | |
| parent | 83876d723d598111741c83e570db74139cc0d22d (diff) | |
Simplified collision interface
| -rw-r--r-- | Spear.cabal | 12 | ||||
| -rw-r--r-- | Spear.lkshs | 10 | ||||
| -rw-r--r-- | Spear/Collision.hs | 159 | ||||
| -rw-r--r-- | Spear/Collision/Collision.hs | 80 | ||||
| -rw-r--r-- | Spear/Collision/Collisioner.hs | 82 | ||||
| -rw-r--r-- | Spear/Collision/Types.hs | 6 | ||||
| -rw-r--r-- | Spear/Math/QuadTree.hs | 2 | ||||
| -rw-r--r-- | Spear/Scene/GameObject.hs | 3 | ||||
| -rw-r--r-- | Spear/Scene/Loader.hs | 2 | ||||
| -rw-r--r-- | Spear/Scene/Scene.hs | 4 |
10 files changed, 170 insertions, 190 deletions
diff --git a/Spear.cabal b/Spear.cabal index bc9f429..a893ce3 100644 --- a/Spear.cabal +++ b/Spear.cabal | |||
| @@ -19,13 +19,11 @@ library | |||
| 19 | exposed-modules: Spear.Scene.GameObject Spear.Math.QuadTree | 19 | exposed-modules: Spear.Scene.GameObject Spear.Math.QuadTree |
| 20 | Spear.Physics.Types Spear.App Spear.App.Application Spear.App.Input | 20 | Spear.Physics.Types Spear.App Spear.App.Application Spear.App.Input |
| 21 | Spear.Assets.Image Spear.Assets.Model Spear.Collision | 21 | Spear.Assets.Image Spear.Assets.Model Spear.Collision |
| 22 | Spear.Math.AABB Spear.Collision.Collision | 22 | Spear.Math.AABB Spear.Math.Circle Spear.Math.Triangle Spear.Game |
| 23 | Spear.Collision.Collisioner Spear.Math.Circle Spear.Math.Triangle | 23 | Spear.GLSL Spear.Math.Camera Spear.Math.Entity Spear.Math.Matrix3 |
| 24 | Spear.Collision.Types Spear.Game Spear.GLSL Spear.Math.Camera | 24 | Spear.Math.Matrix4 Spear.Math.MatrixUtils Spear.Math.Plane |
| 25 | Spear.Math.Entity Spear.Math.Matrix3 Spear.Math.Matrix4 | 25 | Spear.Math.Quaternion Spear.Math.Vector3 Spear.Math.Vector4 |
| 26 | Spear.Math.MatrixUtils Spear.Math.Plane Spear.Math.Quaternion | 26 | Spear.Physics Spear.Physics.Rigid Spear.Render.AnimatedModel |
| 27 | Spear.Math.Vector3 Spear.Math.Vector4 Spear.Physics | ||
| 28 | Spear.Physics.Rigid Spear.Render.AnimatedModel | ||
| 29 | Spear.Render.Material Spear.Render.Model Spear.Render.Program | 27 | Spear.Render.Material Spear.Render.Model Spear.Render.Program |
| 30 | Spear.Render.StaticModel Spear.Render.Texture Spear.Scene.Graph | 28 | Spear.Render.StaticModel Spear.Render.Texture Spear.Scene.Graph |
| 31 | Spear.Scene.Light Spear.Scene.Loader Spear.Scene.Scene | 29 | Spear.Scene.Light Spear.Scene.Loader Spear.Scene.Scene |
diff --git a/Spear.lkshs b/Spear.lkshs index 38c6f2c..1f6f16e 100644 --- a/Spear.lkshs +++ b/Spear.lkshs | |||
| @@ -1,18 +1,18 @@ | |||
| 1 | Version of session file format: | 1 | Version of session file format: |
| 2 | 1 | 2 | 1 |
| 3 | Time of storage: | 3 | Time of storage: |
| 4 | "Thu Aug 30 19:22:08 CEST 2012" | 4 | "Thu Aug 30 19:32:45 CEST 2012" |
| 5 | Layout: VerticalP (TerminalP {paneGroups = fromList [], paneTabs = Just TopP, currentPage = 2, detachedId = Nothing, detachedSize = Nothing}) (HorizontalP (TerminalP {paneGroups = fromList [("Browser",HorizontalP (TerminalP {paneGroups = fromList [], paneTabs = Nothing, currentPage = 0, detachedId = Nothing, detachedSize = Nothing}) (HorizontalP (TerminalP {paneGroups = fromList [], paneTabs = Nothing, currentPage = 0, detachedId = Nothing, detachedSize = Nothing}) (TerminalP {paneGroups = fromList [], paneTabs = Nothing, currentPage = 0, detachedId = Nothing, detachedSize = Nothing}) 357) 139)], paneTabs = Just BottomP, currentPage = 0, detachedId = Nothing, detachedSize = Nothing}) (TerminalP {paneGroups = fromList [], paneTabs = Nothing, currentPage = 0, detachedId = Nothing, detachedSize = Nothing}) 653) 954 | 5 | Layout: VerticalP (TerminalP {paneGroups = fromList [], paneTabs = Just TopP, currentPage = 0, detachedId = Nothing, detachedSize = Nothing}) (HorizontalP (TerminalP {paneGroups = fromList [("Browser",HorizontalP (TerminalP {paneGroups = fromList [], paneTabs = Nothing, currentPage = 0, detachedId = Nothing, detachedSize = Nothing}) (HorizontalP (TerminalP {paneGroups = fromList [], paneTabs = Nothing, currentPage = 0, detachedId = Nothing, detachedSize = Nothing}) (TerminalP {paneGroups = fromList [], paneTabs = Nothing, currentPage = 0, detachedId = Nothing, detachedSize = Nothing}) 353) 140)], paneTabs = Just BottomP, currentPage = 0, detachedId = Nothing, detachedSize = Nothing}) (TerminalP {paneGroups = fromList [], paneTabs = Nothing, currentPage = 0, detachedId = Nothing, detachedSize = Nothing}) 653) 954 |
| 6 | Population: [(Just (ErrorsSt ErrorsState),[SplitP RightP,SplitP TopP]),(Just (FilesSt FilesState),[SplitP RightP,SplitP TopP]),(Just (BufferSt (BufferState "/home/jeanne/programming/haskell/Spear/Spear/Scene/GameObject.hs" 447)),[SplitP LeftP]),(Just (InfoSt (InfoState Nothing)),[SplitP RightP,SplitP TopP,GroupP "Browser",SplitP BottomP,SplitP BottomP]),(Just (BufferSt (BufferState "/home/jeanne/programming/haskell/Spear/Spear/Scene/Loader.hs" 0)),[SplitP LeftP]),(Just (LogSt LogState),[SplitP RightP,SplitP BottomP]),(Just (ModulesSt (ModulesState 328 (PackageScope False,False) (Just (ModuleName ["Spear","Render","Renderable"]),Nothing) (ExpanderState {packageExp = ([],[]), packageExpNoBlack = ([[0,6],[0]],[]), packageDExp = ([],[]), packageDExpNoBlack = ([],[]), workspaceExp = ([],[]), workspaceExpNoBlack = ([],[]), workspaceDExp = ([],[]), workspaceDExpNoBlack = ([],[]), systemExp = ([],[]), systemExpNoBlack = ([],[])}))),[SplitP RightP,SplitP TopP,GroupP "Browser",SplitP BottomP,SplitP TopP]),(Just (BufferSt (BufferState "/home/jeanne/programming/haskell/Spear/Spear/Render/Program.hs" 248)),[SplitP LeftP]),(Just (WorkspaceSt WorkspaceState),[SplitP RightP,SplitP TopP,GroupP "Browser",SplitP TopP])] | 6 | Population: [(Just (BufferSt (BufferState "/home/jeanne/programming/haskell/Spear/Spear/Collision.hs" 3278)),[SplitP LeftP]),(Just (ErrorsSt ErrorsState),[SplitP RightP,SplitP TopP]),(Just (FilesSt FilesState),[SplitP RightP,SplitP TopP]),(Just (BufferSt (BufferState "/home/jeanne/programming/haskell/Spear/Spear/Scene/GameObject.hs" 402)),[SplitP LeftP]),(Just (InfoSt (InfoState Nothing)),[SplitP RightP,SplitP TopP,GroupP "Browser",SplitP BottomP,SplitP BottomP]),(Just (BufferSt (BufferState "/home/jeanne/programming/haskell/Spear/Spear/Scene/Loader.hs" 296)),[SplitP LeftP]),(Just (LogSt LogState),[SplitP RightP,SplitP BottomP]),(Just (ModulesSt (ModulesState 328 (PackageScope False,False) (Nothing,Nothing) (ExpanderState {packageExp = ([],[]), packageExpNoBlack = ([[0]],[]), packageDExp = ([],[]), packageDExpNoBlack = ([],[]), workspaceExp = ([],[]), workspaceExpNoBlack = ([],[]), workspaceDExp = ([],[]), workspaceDExpNoBlack = ([],[]), systemExp = ([],[]), systemExpNoBlack = ([],[])}))),[SplitP RightP,SplitP TopP,GroupP "Browser",SplitP BottomP,SplitP TopP]),(Just (BufferSt (BufferState "/home/jeanne/programming/haskell/Spear/Spear/Render/Program.hs" 248)),[SplitP LeftP]),(Just (WorkspaceSt WorkspaceState),[SplitP RightP,SplitP TopP,GroupP "Browser",SplitP TopP])] |
| 7 | Window size: (1820,939) | 7 | Window size: (1820,939) |
| 8 | Completion size: | 8 | Completion size: |
| 9 | (750,399) | 9 | (750,399) |
| 10 | Workspace: Just "/home/jeanne/programming/haskell/Spear/Spear.lkshw" | 10 | Workspace: Just "/home/jeanne/programming/haskell/Spear/Spear.lkshw" |
| 11 | Active pane: Just "Modules" | 11 | Active pane: Just "Collision.hs" |
| 12 | Toolbar visible: | 12 | Toolbar visible: |
| 13 | True | 13 | True |
| 14 | FindbarState: (False,FindState {entryStr = "", entryHist = ["VAO","'VAO'","\170","\\","^","scale","Vector4.","asdad","translv","Vector3.","Vector.","copy_tr"], replaceStr = "V3.", replaceHist = [], caseSensitive = True, entireWord = False, wrapAround = False, regex = False, lineNr = 1}) | 14 | FindbarState: (False,FindState {entryStr = "", entryHist = ["VAO","'VAO'","\170","\\","^","scale","Vector4.","asdad","translv","Vector3.","Vector.","copy_tr"], replaceStr = "V3.", replaceHist = [], caseSensitive = True, entireWord = False, wrapAround = False, regex = False, lineNr = 1}) |
| 15 | Recently opened files: | 15 | Recently opened files: |
| 16 | ["/home/jeanne/programming/haskell/Spear/Spear/Updatable.hs","/home/jeanne/programming/haskell/Spear/demos/simple-scene/main.hs","/home/jeanne/programming/haskell/Spear/demos/simple-scene/Game/GameObject/Utils.hs","/home/jeanne/programming/haskell/Spear/Spear/Render/Texture.hs","/home/jeanne/programming/haskell/Spear/demos/simple-scene/Game/GameObject/Player.hs","/home/jeanne/programming/haskell/Spear/Spear/GLSL.hs","/home/jeanne/programming/haskell/Spear/Spear/GLSL/VAO.hs","/home/jeanne/programming/haskell/Spear/Spear/GLSL/Uniform.hs","/home/jeanne/programming/haskell/Spear/Spear/GLSL/Texture.hs","/home/jeanne/programming/haskell/Spear/Spear/GLSL/Management.hs","/home/jeanne/programming/haskell/Spear/Spear/GLSL/Buffer.hs","/home/jeanne/programming/haskell/Spear/Spear/GLSL/Error.hs"] | 16 | ["/home/jeanne/programming/haskell/Spear/Spear/Math/QuadTree.hs","/home/jeanne/programming/haskell/Spear/Spear/Scene/Scene.hs","/home/jeanne/programming/haskell/Spear/Spear/Collision/Types.hs","/home/jeanne/programming/haskell/Spear/Spear/Collision/Collisioner.hs","/home/jeanne/programming/haskell/Spear/Spear/Collision/Collision.hs","/home/jeanne/programming/haskell/Spear/Spear/Updatable.hs","/home/jeanne/programming/haskell/Spear/demos/simple-scene/main.hs","/home/jeanne/programming/haskell/Spear/demos/simple-scene/Game/GameObject/Utils.hs","/home/jeanne/programming/haskell/Spear/Spear/Render/Texture.hs","/home/jeanne/programming/haskell/Spear/demos/simple-scene/Game/GameObject/Player.hs","/home/jeanne/programming/haskell/Spear/Spear/GLSL.hs","/home/jeanne/programming/haskell/Spear/Spear/GLSL/VAO.hs"] |
| 17 | Recently opened workspaces: | 17 | Recently opened workspaces: |
| 18 | ["/home/jeanne/programming/haskell/hagen/hagen.lkshw","/home/jeanne/programming/haskell/foo/foo.lkshw","/home/jeanne/programming/haskell/Spear/Spear.lkshw","/home/jeanne/programming/haskell/nexus/nexus.lkshw","/home/jeanne/leksah.lkshw"] \ No newline at end of file | 18 | ["/home/jeanne/programming/haskell/hagen/hagen.lkshw","/home/jeanne/programming/haskell/foo/foo.lkshw","/home/jeanne/programming/haskell/Spear/Spear.lkshw","/home/jeanne/programming/haskell/nexus/nexus.lkshw","/home/jeanne/leksah.lkshw"] \ No newline at end of file |
diff --git a/Spear/Collision.hs b/Spear/Collision.hs index 975f3cf..0dbebdb 100644 --- a/Spear/Collision.hs +++ b/Spear/Collision.hs | |||
| @@ -1,10 +1,161 @@ | |||
| 1 | module Spear.Collision | 1 | module Spear.Collision |
| 2 | ( | 2 | ( |
| 3 | module Spear.Collision.Collision | 3 | -- * Collision tests |
| 4 | , module Spear.Collision.Types | 4 | CollisionType(..) |
| 5 | , Collisionable(..) | ||
| 6 | -- * Collisioners | ||
| 7 | , Collisioner(..) | ||
| 8 | -- ** Construction | ||
| 9 | , aabbCollisioner | ||
| 10 | , sphereCollisioner | ||
| 11 | , buildAABB | ||
| 12 | -- ** Collision test | ||
| 13 | , collide | ||
| 14 | -- ** Manipulation | ||
| 15 | , move | ||
| 16 | -- * Helpers | ||
| 17 | , aabbFromCircle | ||
| 5 | ) | 18 | ) |
| 6 | where | 19 | where |
| 7 | 20 | ||
| 8 | 21 | ||
| 9 | import Spear.Collision.Collision | 22 | import Spear.Math.AABB |
| 10 | import Spear.Collision.Types | 23 | import Spear.Math.Circle |
| 24 | import Spear.Math.Plane | ||
| 25 | import Spear.Math.Vector2 | ||
| 26 | |||
| 27 | |||
| 28 | -- | Encodes several collision situations. | ||
| 29 | data CollisionType = NoCollision | Collision | FullyContains | FullyContainedBy | ||
| 30 | deriving (Eq, Show) | ||
| 31 | |||
| 32 | |||
| 33 | class Collisionable a where | ||
| 34 | collideBox :: AABB -> a -> CollisionType | ||
| 35 | collideSphere :: Circle -> a -> CollisionType | ||
| 36 | |||
| 37 | |||
| 38 | instance Collisionable AABB where | ||
| 39 | |||
| 40 | collideBox box1@(AABB min1 max1) box2@(AABB min2 max2) | ||
| 41 | | min1 > max2 = NoCollision | ||
| 42 | | max1 < min2 = NoCollision | ||
| 43 | | box1 `aabbpt` min2 && box1 `aabbpt` max2 = FullyContains | ||
| 44 | | box2 `aabbpt` min1 && box2 `aabbpt` max1 = FullyContainedBy | ||
| 45 | | (x max1) < (x min2) = NoCollision | ||
| 46 | | (x min1) > (x max2) = NoCollision | ||
| 47 | | (y max1) < (y min2) = NoCollision | ||
| 48 | | (y min1) > (y max2) = NoCollision | ||
| 49 | | otherwise = Collision | ||
| 50 | |||
| 51 | collideSphere sphere@(Circle c r) aabb@(AABB min max) | ||
| 52 | | test == FullyContains || test == FullyContainedBy = test | ||
| 53 | | normSq (c - boxC) > (l + r)^2 = NoCollision | ||
| 54 | | otherwise = Collision | ||
| 55 | where | ||
| 56 | test = aabb `collideBox` aabbFromCircle sphere | ||
| 57 | boxC = min + (max-min)/2 | ||
| 58 | l = norm $ min + (vec2 (x boxC) (y min)) - min | ||
| 59 | |||
| 60 | |||
| 61 | |||
| 62 | instance Collisionable Circle where | ||
| 63 | |||
| 64 | collideBox box sphere = case collideSphere sphere box of | ||
| 65 | FullyContains -> FullyContainedBy | ||
| 66 | FullyContainedBy -> FullyContains | ||
| 67 | x -> x | ||
| 68 | |||
| 69 | collideSphere s1@(Circle c1 r1) s2@(Circle c2 r2) | ||
| 70 | | distance_centers <= sub_radii = if (r1 > r2) then FullyContains else FullyContainedBy | ||
| 71 | | distance_centers <= sum_radii = Collision | ||
| 72 | | otherwise = NoCollision | ||
| 73 | where | ||
| 74 | distance_centers = normSq $ c1 - c2 | ||
| 75 | sum_radii = (r1 + r2)^2 | ||
| 76 | sub_radii = (r1 - r2)^2 | ||
| 77 | |||
| 78 | |||
| 79 | aabbPoints :: AABB -> [Vector2] | ||
| 80 | aabbPoints (AABB min max) = [p1,p2,p3,p4,p5,p6,p7,p8] | ||
| 81 | where | ||
| 82 | p1 = vec2 (x min) (y min) | ||
| 83 | p2 = vec2 (x min) (y min) | ||
| 84 | p3 = vec2 (x min) (y max) | ||
| 85 | p4 = vec2 (x min) (y max) | ||
| 86 | p5 = vec2 (x max) (y min) | ||
| 87 | p6 = vec2 (x max) (y min) | ||
| 88 | p7 = vec2 (x max) (y max) | ||
| 89 | p8 = vec2 (x max) (y max) | ||
| 90 | |||
| 91 | |||
| 92 | -- | A collisioner component. | ||
| 93 | data Collisioner | ||
| 94 | -- | An axis-aligned bounding box. | ||
| 95 | = AABBCol { getBox :: {-# UNPACK #-} !AABB } | ||
| 96 | -- | A bounding sphere. | ||
| 97 | | CircleCol { getCircle :: {-# UNPACK #-} !Circle } | ||
| 98 | |||
| 99 | |||
| 100 | -- | Create a collisioner from the specified box. | ||
| 101 | aabbCollisioner :: AABB -> Collisioner | ||
| 102 | aabbCollisioner = AABBCol | ||
| 103 | |||
| 104 | |||
| 105 | -- | Create a collisioner from the specified circle. | ||
| 106 | sphereCollisioner :: Circle -> Collisioner | ||
| 107 | sphereCollisioner = CircleCol | ||
| 108 | |||
| 109 | |||
| 110 | -- | Create the minimal AABB fully containing the specified collisioners. | ||
| 111 | buildAABB :: [Collisioner] -> AABB | ||
| 112 | buildAABB cols = aabb $ generatePoints cols | ||
| 113 | |||
| 114 | |||
| 115 | -- | Create the minimal AABB collisioner fully containing the specified circle. | ||
| 116 | boxFromSphere :: Circle -> Collisioner | ||
| 117 | boxFromSphere = AABBCol . aabbFromCircle | ||
| 118 | |||
| 119 | |||
| 120 | generatePoints :: [Collisioner] -> [Vector2] | ||
| 121 | generatePoints = foldr generate [] | ||
| 122 | where | ||
| 123 | generate (AABBCol (AABB min max)) acc = p1:p2:p3:p4:p5:p6:p7:p8:acc | ||
| 124 | where | ||
| 125 | p1 = vec2 (x min) (y min) | ||
| 126 | p2 = vec2 (x min) (y min) | ||
| 127 | p3 = vec2 (x min) (y max) | ||
| 128 | p4 = vec2 (x min) (y max) | ||
| 129 | p5 = vec2 (x max) (y min) | ||
| 130 | p6 = vec2 (x max) (y min) | ||
| 131 | p7 = vec2 (x max) (y max) | ||
| 132 | p8 = vec2 (x max) (y max) | ||
| 133 | |||
| 134 | generate (CircleCol (Circle c r)) acc = p1:p2:p3:p4:acc | ||
| 135 | where | ||
| 136 | p1 = c + unitx * (vec2 r r) | ||
| 137 | p2 = c - unitx * (vec2 r r) | ||
| 138 | p3 = c + unity * (vec2 r r) | ||
| 139 | p4 = c - unity * (vec2 r r) | ||
| 140 | |||
| 141 | |||
| 142 | -- | Collide the given collisioners. | ||
| 143 | collide :: Collisioner -> Collisioner -> CollisionType | ||
| 144 | collide (AABBCol box1) (AABBCol box2) = collideBox box1 box2 | ||
| 145 | collide (CircleCol s1) (CircleCol s2) = collideSphere s1 s2 | ||
| 146 | collide (AABBCol box) (CircleCol sphere) = collideBox box sphere | ||
| 147 | collide (CircleCol sphere) (AABBCol box) = collideSphere sphere box | ||
| 148 | |||
| 149 | |||
| 150 | -- | Move the collisioner. | ||
| 151 | move :: Vector2 -> Collisioner -> Collisioner | ||
| 152 | move v (AABBCol (AABB min max)) = AABBCol (AABB (min+v) (max+v)) | ||
| 153 | move v (CircleCol (Circle c r)) = CircleCol (Circle (c+v) r) | ||
| 154 | |||
| 155 | |||
| 156 | -- | Create the minimal box fully containing the specified circle. | ||
| 157 | aabbFromCircle :: Circle -> AABB | ||
| 158 | aabbFromCircle (Circle c r) = AABB bot top | ||
| 159 | where | ||
| 160 | bot = c - (vec2 r r) | ||
| 161 | top = c + (vec2 r r) | ||
diff --git a/Spear/Collision/Collision.hs b/Spear/Collision/Collision.hs deleted file mode 100644 index 60c2f03..0000000 --- a/Spear/Collision/Collision.hs +++ /dev/null | |||
| @@ -1,80 +0,0 @@ | |||
| 1 | module Spear.Collision.Collision | ||
| 2 | ( | ||
| 3 | Collisionable(..) | ||
| 4 | , aabbFromCircle | ||
| 5 | ) | ||
| 6 | where | ||
| 7 | |||
| 8 | |||
| 9 | import Spear.Collision.Types | ||
| 10 | import Spear.Math.AABB | ||
| 11 | import Spear.Math.Circle | ||
| 12 | import Spear.Math.Plane | ||
| 13 | import Spear.Math.Vector2 | ||
| 14 | |||
| 15 | |||
| 16 | class Collisionable a where | ||
| 17 | collideBox :: AABB -> a -> CollisionType | ||
| 18 | collideSphere :: Circle -> a -> CollisionType | ||
| 19 | |||
| 20 | |||
| 21 | instance Collisionable AABB where | ||
| 22 | |||
| 23 | collideBox box1@(AABB min1 max1) box2@(AABB min2 max2) | ||
| 24 | | min1 > max2 = NoCollision | ||
| 25 | | max1 < min2 = NoCollision | ||
| 26 | | box1 `aabbpt` min2 && box1 `aabbpt` max2 = FullyContains | ||
| 27 | | box2 `aabbpt` min1 && box2 `aabbpt` max1 = FullyContainedBy | ||
| 28 | | (x max1) < (x min2) = NoCollision | ||
| 29 | | (x min1) > (x max2) = NoCollision | ||
| 30 | | (y max1) < (y min2) = NoCollision | ||
| 31 | | (y min1) > (y max2) = NoCollision | ||
| 32 | | otherwise = Collision | ||
| 33 | |||
| 34 | collideSphere sphere@(Circle c r) aabb@(AABB min max) | ||
| 35 | | test == FullyContains || test == FullyContainedBy = test | ||
| 36 | | normSq (c - boxC) > (l + r)^2 = NoCollision | ||
| 37 | | otherwise = Collision | ||
| 38 | where | ||
| 39 | test = aabb `collideBox` aabbFromCircle sphere | ||
| 40 | boxC = min + (max-min)/2 | ||
| 41 | l = norm $ min + (vec2 (x boxC) (y min)) - min | ||
| 42 | |||
| 43 | |||
| 44 | |||
| 45 | instance Collisionable Circle where | ||
| 46 | |||
| 47 | collideBox box sphere = case collideSphere sphere box of | ||
| 48 | FullyContains -> FullyContainedBy | ||
| 49 | FullyContainedBy -> FullyContains | ||
| 50 | x -> x | ||
| 51 | |||
| 52 | collideSphere s1@(Circle c1 r1) s2@(Circle c2 r2) | ||
| 53 | | distance_centers <= sub_radii = if (r1 > r2) then FullyContains else FullyContainedBy | ||
| 54 | | distance_centers <= sum_radii = Collision | ||
| 55 | | otherwise = NoCollision | ||
| 56 | where | ||
| 57 | distance_centers = normSq $ c1 - c2 | ||
| 58 | sum_radii = (r1 + r2)^2 | ||
| 59 | sub_radii = (r1 - r2)^2 | ||
| 60 | |||
| 61 | |||
| 62 | aabbPoints :: AABB -> [Vector2] | ||
| 63 | aabbPoints (AABB min max) = [p1,p2,p3,p4,p5,p6,p7,p8] | ||
| 64 | where | ||
| 65 | p1 = vec2 (x min) (y min) | ||
| 66 | p2 = vec2 (x min) (y min) | ||
| 67 | p3 = vec2 (x min) (y max) | ||
| 68 | p4 = vec2 (x min) (y max) | ||
| 69 | p5 = vec2 (x max) (y min) | ||
| 70 | p6 = vec2 (x max) (y min) | ||
| 71 | p7 = vec2 (x max) (y max) | ||
| 72 | p8 = vec2 (x max) (y max) | ||
| 73 | |||
| 74 | |||
| 75 | -- | Create the minimal box fully containing the specified circle. | ||
| 76 | aabbFromCircle :: Circle -> AABB | ||
| 77 | aabbFromCircle (Circle c r) = AABB bot top | ||
| 78 | where | ||
| 79 | bot = c - (vec2 r r) | ||
| 80 | top = c + (vec2 r r) | ||
diff --git a/Spear/Collision/Collisioner.hs b/Spear/Collision/Collisioner.hs deleted file mode 100644 index dd41d61..0000000 --- a/Spear/Collision/Collisioner.hs +++ /dev/null | |||
| @@ -1,82 +0,0 @@ | |||
| 1 | module Spear.Collision.Collisioner | ||
| 2 | ( | ||
| 3 | Collisioner(..) | ||
| 4 | , CollisionType(..) | ||
| 5 | , aabbCollisioner | ||
| 6 | , sphereCollisioner | ||
| 7 | , buildAABB | ||
| 8 | , collide | ||
| 9 | , move | ||
| 10 | ) | ||
| 11 | where | ||
| 12 | |||
| 13 | |||
| 14 | import Spear.Collision.Collision as C | ||
| 15 | import Spear.Collision.Types | ||
| 16 | import Spear.Math.AABB | ||
| 17 | import Spear.Math.Circle | ||
| 18 | import Spear.Math.Vector2 | ||
| 19 | |||
| 20 | |||
| 21 | -- | A collisioner component. | ||
| 22 | data Collisioner | ||
| 23 | -- | An axis-aligned bounding box. | ||
| 24 | = AABBCol { getBox :: {-# UNPACK #-} !AABB } | ||
| 25 | -- | A bounding sphere. | ||
| 26 | | CircleCol { getCircle :: {-# UNPACK #-} !Circle } | ||
| 27 | |||
| 28 | |||
| 29 | -- | Create a 'Collisioner' from the specified box. | ||
| 30 | aabbCollisioner :: AABB -> Collisioner | ||
| 31 | aabbCollisioner = AABBCol | ||
| 32 | |||
| 33 | |||
| 34 | -- | Create a 'Collisioner' from the specified circle. | ||
| 35 | sphereCollisioner :: Circle -> Collisioner | ||
| 36 | sphereCollisioner = CircleCol | ||
| 37 | |||
| 38 | |||
| 39 | -- | Create the minimal 'AABB' fully containing the specified collisioners. | ||
| 40 | buildAABB :: [Collisioner] -> AABB | ||
| 41 | buildAABB cols = aabb $ generatePoints cols | ||
| 42 | |||
| 43 | |||
| 44 | -- | Create the minimal 'AABB' collisioner fully containing the specified circle. | ||
| 45 | boxFromSphere :: Circle -> Collisioner | ||
| 46 | boxFromSphere = AABBCol . aabbFromCircle | ||
| 47 | |||
| 48 | |||
| 49 | generatePoints :: [Collisioner] -> [Vector2] | ||
| 50 | generatePoints = foldr generate [] | ||
| 51 | where | ||
| 52 | generate (AABBCol (AABB min max)) acc = p1:p2:p3:p4:p5:p6:p7:p8:acc | ||
| 53 | where | ||
| 54 | p1 = vec2 (x min) (y min) | ||
| 55 | p2 = vec2 (x min) (y min) | ||
| 56 | p3 = vec2 (x min) (y max) | ||
| 57 | p4 = vec2 (x min) (y max) | ||
| 58 | p5 = vec2 (x max) (y min) | ||
| 59 | p6 = vec2 (x max) (y min) | ||
| 60 | p7 = vec2 (x max) (y max) | ||
| 61 | p8 = vec2 (x max) (y max) | ||
| 62 | |||
| 63 | generate (CircleCol (Circle c r)) acc = p1:p2:p3:p4:acc | ||
| 64 | where | ||
| 65 | p1 = c + unitx * (vec2 r r) | ||
| 66 | p2 = c - unitx * (vec2 r r) | ||
| 67 | p3 = c + unity * (vec2 r r) | ||
| 68 | p4 = c - unity * (vec2 r r) | ||
| 69 | |||
| 70 | |||
| 71 | -- | Collide the given collisioners. | ||
| 72 | collide :: Collisioner -> Collisioner -> CollisionType | ||
| 73 | collide (AABBCol box1) (AABBCol box2) = collideBox box1 box2 | ||
| 74 | collide (CircleCol s1) (CircleCol s2) = collideSphere s1 s2 | ||
| 75 | collide (AABBCol box) (CircleCol sphere) = collideBox box sphere | ||
| 76 | collide (CircleCol sphere) (AABBCol box) = collideSphere sphere box | ||
| 77 | |||
| 78 | |||
| 79 | -- | Move the collisioner. | ||
| 80 | move :: Vector2 -> Collisioner -> Collisioner | ||
| 81 | move v (AABBCol (AABB min max)) = AABBCol (AABB (min+v) (max+v)) | ||
| 82 | move v (CircleCol (Circle c r)) = CircleCol (Circle (c+v) r) | ||
diff --git a/Spear/Collision/Types.hs b/Spear/Collision/Types.hs deleted file mode 100644 index 61b224f..0000000 --- a/Spear/Collision/Types.hs +++ /dev/null | |||
| @@ -1,6 +0,0 @@ | |||
| 1 | module Spear.Collision.Types | ||
| 2 | where | ||
| 3 | |||
| 4 | -- | Encodes several collision situations. | ||
| 5 | data CollisionType = NoCollision | Collision | FullyContains | FullyContainedBy | ||
| 6 | deriving (Eq, Show) | ||
diff --git a/Spear/Math/QuadTree.hs b/Spear/Math/QuadTree.hs index 2e92265..e553c88 100644 --- a/Spear/Math/QuadTree.hs +++ b/Spear/Math/QuadTree.hs | |||
| @@ -9,7 +9,7 @@ module Spear.Math.QuadTree | |||
| 9 | ) | 9 | ) |
| 10 | where | 10 | where |
| 11 | 11 | ||
| 12 | import Spear.Collision.Types | 12 | import Spear.Collision |
| 13 | import Spear.Math.AABB | 13 | import Spear.Math.AABB |
| 14 | import Spear.Math.Vector2 | 14 | import Spear.Math.Vector2 |
| 15 | 15 | ||
diff --git a/Spear/Scene/GameObject.hs b/Spear/Scene/GameObject.hs index cfc825d..9886f35 100644 --- a/Spear/Scene/GameObject.hs +++ b/Spear/Scene/GameObject.hs | |||
| @@ -23,8 +23,7 @@ module Spear.Scene.GameObject | |||
| 23 | where | 23 | where |
| 24 | 24 | ||
| 25 | 25 | ||
| 26 | import Spear.Collision.Collision | 26 | import Spear.Collision as Col |
| 27 | import Spear.Collision.Collisioner as Col | ||
| 28 | import Spear.GLSL | 27 | import Spear.GLSL |
| 29 | import Spear.Math.AABB | 28 | import Spear.Math.AABB |
| 30 | import qualified Spear.Math.Camera as Cam | 29 | import qualified Spear.Math.Camera as Cam |
diff --git a/Spear/Scene/Loader.hs b/Spear/Scene/Loader.hs index 081b927..820ad51 100644 --- a/Spear/Scene/Loader.hs +++ b/Spear/Scene/Loader.hs | |||
| @@ -19,7 +19,7 @@ where | |||
| 19 | 19 | ||
| 20 | 20 | ||
| 21 | import Spear.Assets.Model as Model | 21 | import Spear.Assets.Model as Model |
| 22 | import Spear.Collision.Collisioner | 22 | import Spear.Collision |
| 23 | import qualified Spear.GLSL as GLSL | 23 | import qualified Spear.GLSL as GLSL |
| 24 | import Spear.Math.Matrix3 as M3 | 24 | import Spear.Math.Matrix3 as M3 |
| 25 | import Spear.Math.Matrix4 as M4 | 25 | import Spear.Math.Matrix4 as M4 |
diff --git a/Spear/Scene/Scene.hs b/Spear/Scene/Scene.hs index 0dfa459..b8366f3 100644 --- a/Spear/Scene/Scene.hs +++ b/Spear/Scene/Scene.hs | |||
| @@ -13,14 +13,14 @@ module Spear.Scene.Scene | |||
| 13 | -- * Update and render | 13 | -- * Update and render |
| 14 | , update | 14 | , update |
| 15 | , updateM | 15 | , updateM |
| 16 | , collide | 16 | , Spear.Scene.Scene.collide |
| 17 | , collideM | 17 | , collideM |
| 18 | , render | 18 | , render |
| 19 | ) | 19 | ) |
| 20 | where | 20 | where |
| 21 | 21 | ||
| 22 | 22 | ||
| 23 | import Spear.Collision.Types | 23 | import Spear.Collision |
| 24 | import Spear.Game (Game) | 24 | import Spear.Game (Game) |
| 25 | import Spear.Math.AABB | 25 | import Spear.Math.AABB |
| 26 | import Spear.Math.QuadTree as QT | 26 | import Spear.Math.QuadTree as QT |
