keid-geometry 0.1.0.1 → 0.1.1.1
raw patch · 7 files changed
+150/−157 lines, 7 filesdep −rio-app
Dependencies removed: rio-app
Files
- ChangeLog.md +10/−1
- keid-geometry.cabal +5/−2
- src/Geometry/Hit.hs +14/−0
- src/Geometry/Icosphere.hs +0/−154
- src/Geometry/Intersect.hs +40/−0
- src/Geometry/Plane.hs +61/−0
- src/Geometry/Ray.hs +20/−0
ChangeLog.md view
@@ -1,5 +1,14 @@ # Changelog for keid-geometry -## 1.0.0.1+## 0.1.1.1++- Added ray-plane intersection and related types.+- Removed unused deps.++## 0.1.1.0++- Removed older list-based icosphere generator.++## 0.1.0.1 - Added an icosphere generator backed by a mutable vector.
keid-geometry.cabal view
@@ -5,7 +5,7 @@ -- see: https://github.com/sol/hpack name: keid-geometry-version: 0.1.0.1+version: 0.1.1.1 synopsis: Geometry primitives for Keid engine. category: Game Engine author: IC Rainbow@@ -27,8 +27,12 @@ Geometry.Cube Geometry.Edge Geometry.Face+ Geometry.Hit Geometry.Icosphere+ Geometry.Intersect+ Geometry.Plane Geometry.Quad+ Geometry.Ray other-modules: Paths_keid_geometry hs-source-dirs:@@ -97,7 +101,6 @@ , keid-core , mtl , rio >=0.1.12.0- , rio-app , vector , vulkan default-language: Haskell2010
+ src/Geometry/Hit.hs view
@@ -0,0 +1,14 @@+module Geometry.Hit+ ( Hit(..)+ ) where++import RIO++import Geomancy (Vec3)++data Hit = Hit+ { distance :: Float+ , cosine :: Float+ , position :: Vec3+ }+ deriving (Eq, Ord, Show)
src/Geometry/Icosphere.hs view
@@ -3,19 +3,12 @@ , icofaces , icopoints-- , icosphere- , icotris_v1- , subNormal- , subdivide ) where import RIO -import Data.List (iterate, (!!)) import Geomancy.Vec3 (Vec3, vec3) import Geomancy.Vec3 qualified as Vec3-import Resource.Model qualified as Model import Data.Vector qualified as Vector import Data.Vector.Mutable qualified as Mutable import RIO.Vector.Partial ((!))@@ -184,150 +177,3 @@ ] where t = (1.0 + sqrt 5.0) / 2.0--icotris_v1 :: [[Vec3]]-icotris_v1 =- [ -- faces around point 0- [ icopoints ! 0- , icopoints ! 11- , icopoints ! 5- ]-- , [ icopoints ! 0- , icopoints ! 5- , icopoints ! 1- ]-- , [ icopoints ! 0- , icopoints ! 1- , icopoints ! 7- ]-{-- , [ icopoints ! 0- , icopoints ! 1- , icopoints ! 7- ]--}- , [ icopoints ! 0- , icopoints ! 7- , icopoints ! 10- ]-- , [ icopoints ! 0- , icopoints ! 10- , icopoints ! 11- ]-- -- 5 adjacent faces-- , [ icopoints ! 1- , icopoints ! 5- , icopoints ! 9- ]-- , [ icopoints ! 5- , icopoints ! 11- , icopoints ! 4- ]-- , [ icopoints ! 11- , icopoints ! 10- , icopoints ! 2- ]-- , [ icopoints ! 10- , icopoints ! 7- , icopoints ! 6- ]-- , [ icopoints ! 7- , icopoints ! 1- , icopoints ! 8- ]-- -- 5 adjacent faces around point 3-- , [ icopoints ! 3- , icopoints ! 9- , icopoints ! 4- ]-- , [ icopoints ! 3- , icopoints ! 4- , icopoints ! 2- ]-- , [ icopoints ! 3- , icopoints ! 2- , icopoints ! 6- ]-- , [ icopoints ! 3- , icopoints ! 6- , icopoints ! 8- ]-- , [ icopoints ! 3- , icopoints ! 8- , icopoints ! 9- ]-- -- 5 adjacent faces-- , [ icopoints ! 4- , icopoints ! 9- , icopoints ! 5- ]-- , [ icopoints ! 2- , icopoints ! 4- , icopoints ! 11- ]-- , [ icopoints ! 6- , icopoints ! 2- , icopoints ! 10- ]-- , [ icopoints ! 8- , icopoints ! 6- , icopoints ! 7- ]-- , [ icopoints ! 9- , icopoints ! 8- , icopoints ! 1- ]- ]--icosphere :: (Vec3 -> attrs) -> Int -> [Model.Vertex Vec3.Packed attrs]-icosphere mkAttrs n = do- v <- reverse . concat $ subNormal n icotris_v1- pure Model.Vertex- { vPosition = Vec3.Packed v- , vAttrs = mkAttrs v- }--subNormal :: Int -> [[Vec3]] -> [[Vec3]]-subNormal nu tris = map (map Vec3.normalize) $ subdivide nu tris--subdivide :: Int -> [[Vec3]] -> [[Vec3]]-subdivide frequency tris =- iterate (concatMap subdivideTri) tris !! (frequency - 1)- where- subdivideTri = \case- [v1, v2, v3] ->- let- a = midpoint v1 v2- b = midpoint v2 v3- c = midpoint v3 v1- in- [ [ v1, a, c ]- , [ v2, b, a ]- , [ v3, c, b ]- , [ a, b, c ]- ]- _ ->- error "subdivideTri: not a triangle somehow"-- midpoint a b = (a + b) / 2
+ src/Geometry/Intersect.hs view
@@ -0,0 +1,40 @@+module Geometry.Intersect+ ( Hit+ , ray'plane+ ) where++import RIO++import Geomancy.Vec3 (dot, (^*))++import Geometry.Hit (Hit(..))+import Geometry.Plane (Plane)+import Geometry.Plane qualified as Plane+import Geometry.Ray (Ray)+import Geometry.Ray qualified as Ray++ray'plane+ :: Ray+ -> Plane+ -> Maybe Hit+ray'plane ray plane =+ -- XXX: Ignore "glancing" hits from either side of a plane+ if (abs denom > eps) then+ Just Hit+ { distance = t+ , cosine = denom+ , position = hit+ }+ else+ Nothing+ where+ eps = 1/32++ denom =+ Plane.normal plane `dot` Ray.direction ray++ t =+ negate ((Plane.normal plane `dot` Ray.origin ray) + Plane.depth plane) / denom++ hit =+ Ray.origin ray + Ray.direction ray ^* t
+ src/Geometry/Plane.hs view
@@ -0,0 +1,61 @@+module Geometry.Plane+ ( Plane(..)+ , xyBack+ , xyFront+ , xzUp+ , xzDown+ , yzLeft+ , yzRight+ ) where++import RIO++import Geomancy (Vec3, vec3)++data Plane = Plane+ { normal :: Vec3+ , depth :: Float+ }+ deriving (Show)++-- | XY plane facing back.+xyBack :: Float -> Plane+xyBack d = Plane+ { normal = vec3 0 0 (-1)+ , depth = d+ }++-- | XY plane facing front.+xyFront :: Float -> Plane+xyFront d = Plane+ { normal = vec3 0 0 1+ , depth = d+ }++-- | XZ plane facing up.+xzUp :: Float -> Plane+xzUp d = Plane+ { normal = vec3 0 (-1) 0+ , depth = d+ }++-- | XZ plane facing down.+xzDown :: Float -> Plane+xzDown d = Plane+ { normal = vec3 0 1 0+ , depth = d+ }++-- | YZ plane facing left.+yzLeft :: Float -> Plane+yzLeft d = Plane+ { normal = vec3 (-1) 0 0+ , depth = d+ }++-- | YZ plane facing right.+yzRight :: Float -> Plane+yzRight d = Plane+ { normal = vec3 1 0 0+ , depth = d+ }
+ src/Geometry/Ray.hs view
@@ -0,0 +1,20 @@+module Geometry.Ray+ ( Ray(..)+ , fromSegment+ ) where++import RIO++import Geomancy (Vec3)++data Ray = Ray+ { origin :: Vec3+ , direction :: Vec3+ }+ deriving (Show)++fromSegment :: Vec3 -> Vec3 -> Ray+fromSegment origin target = Ray+ { origin = origin+ , direction = target - origin+ }