Skip to content

Commit

Permalink
Refactor the bodies module
Browse files Browse the repository at this point in the history
  • Loading branch information
w0rm committed Dec 7, 2023
1 parent a3304d9 commit df11d5b
Show file tree
Hide file tree
Showing 5 changed files with 185 additions and 223 deletions.
17 changes: 16 additions & 1 deletion src/Ball.elm
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
module Ball exposing (body, rack, radius, sphere)
module Ball exposing (body, entity, rack, radius)

import Color exposing (Color)
import Length exposing (Length, Meters)
import Mass exposing (Mass)
import Physics.Body as Body exposing (Body)
Expand All @@ -8,6 +9,8 @@ import Physics.Material as Material exposing (Material)
import Point2d exposing (Point2d)
import Point3d
import Quantity
import Scene3d exposing (Entity)
import Scene3d.Material as Material
import SketchPlane3d
import Sphere3d exposing (Sphere3d)
import Vector3d
Expand Down Expand Up @@ -53,6 +56,18 @@ body id =
|> Body.withBehavior (Body.dynamic weight)


entity : Material.Texture Color -> Material.Texture Float -> Entity BodyCoordinates
entity baseColor roughnessTexture =
Scene3d.sphereWithShadow
(Material.texturedPbr
{ baseColor = baseColor
, roughness = roughnessTexture
, metallic = Material.constant 0
}
)
sphere


rack : Point2d Meters WorldCoordinates -> (Int -> Maybe id) -> List (Body id)
rack footSpot fn =
let
Expand Down
177 changes: 1 addition & 176 deletions src/Bodies.elm
Original file line number Diff line number Diff line change
@@ -1,36 +1,6 @@
module Bodies exposing
( Id(..)
, areaBehindTheHeadStringEntity
, bodyToEntity
, cueBallEntity
, cueEntity
, world
)
module Bodies exposing (Id(..))

import Acceleration
import Angle
import Axis3d exposing (Axis3d)
import Ball
import Camera3d exposing (Camera3d)
import Color exposing (Color)
import Cue
import Dict exposing (Dict)
import Direction3d
import EightBall exposing (Ball)
import Length exposing (Length, Meters)
import Physics.Body as Body exposing (Body)
import Physics.Coordinates exposing (BodyCoordinates, WorldCoordinates)
import Physics.Material
import Physics.World as World exposing (World)
import Point3d
import Rectangle3d
import Scene3d exposing (Entity)
import Scene3d.Material as Material
import Table exposing (Table)



-- PHYSICAL WORLD


type Id
Expand All @@ -40,148 +10,3 @@ type Id
| Table
| Cushion
| Pocket


world : Table -> World Id
world table =
World.empty
|> World.withGravity
(Acceleration.metersPerSecondSquared 9.80665)
Direction3d.negativeZ
|> World.add
(Body.compound table.table Table
|> Body.withMaterial
(Physics.Material.custom
{ friction = 0.8
, bounciness = 0
}
)
)
|> World.add
(Body.compound table.cushions Cushion
|> Body.withMaterial
(Physics.Material.custom
{ friction = 0.1
, bounciness = 0.8
}
)
)
|> World.add (Body.compound table.pockets Pocket)
|> World.add
(Body.plane Floor
-- distance from the floor until the top of the table
|> Body.moveTo (Point3d.meters 0 0 -0.45)
)
|> (\w ->
List.foldl World.add w <|
Ball.rack
Table.footSpot
(EightBall.numberedBall >> Maybe.map Numbered)
)



-- VISUAL ENTITIES


bodyToEntity : Material.Texture Float -> Dict Int (Material.Texture Color) -> Table -> Body Id -> Entity WorldCoordinates
bodyToEntity roughnessTexture ballTextures table body =
Scene3d.placeIn (Body.frame body) <|
case Body.data body of
Floor ->
Scene3d.quad
(Material.matte (Color.rgb255 46 52 54))
(Point3d.meters -15 -15 0)
(Point3d.meters 15 -15 0)
(Point3d.meters 15 15 0)
(Point3d.meters -15 15 0)

Numbered ball ->
let
colorTexture =
Dict.get (EightBall.ballNumber ball) ballTextures
|> Maybe.withDefault (Material.constant Color.black)

material =
Material.texturedPbr
{ baseColor = colorTexture
, roughness = roughnessTexture
, metallic = Material.constant 0
}
in
Scene3d.sphereWithShadow material Ball.sphere
-- rotate to see the numbers
|> Scene3d.rotateAround Axis3d.x (Angle.degrees 90)

CueBall ->
cueBallEntity True roughnessTexture

Table ->
Scene3d.meshWithShadow table.material table.mesh table.shadow

_ ->
Scene3d.nothing


cueBallEntity : Bool -> Material.Texture Float -> Scene3d.Entity BodyCoordinates
cueBallEntity isActive roughnessTexture =
Scene3d.sphereWithShadow
(Material.texturedPbr
{ baseColor =
if isActive then
Material.constant Color.white

else
Material.constant inactiveColor
, roughness = roughnessTexture
, metallic = Material.constant 0
}
)
Ball.sphere


{-| Highlight the area where the ball should be placed
-}
areaBehindTheHeadStringEntity : Entity WorldCoordinates
areaBehindTheHeadStringEntity =
case Rectangle3d.vertices Table.areaBehindTheHeadString of
[ v1, v2, v3, v4 ] ->
Scene3d.quad
(Material.nonmetal
{ baseColor = Color.rgb255 131 146 34
, roughness = 1
}
)
v1
v2
v3
v4

_ ->
Scene3d.nothing


cueEntity : Camera3d Meters WorldCoordinates -> Length -> Axis3d Meters WorldCoordinates -> Bool -> Scene3d.Entity WorldCoordinates
cueEntity camera3d clipDepth axis isActive =
case Cue.cylinder camera3d clipDepth axis of
Just cylinder ->
Scene3d.cylinderWithShadow
(Material.nonmetal
{ baseColor =
if isActive then
Color.white

else
inactiveColor
, roughness = 0.6
}
)
cylinder

Nothing ->
Scene3d.nothing


inactiveColor : Color
inactiveColor =
Color.rgb255 130 130 130
55 changes: 37 additions & 18 deletions src/Cue.elm
Original file line number Diff line number Diff line change
@@ -1,16 +1,52 @@
module Cue exposing (cylinder, length, offset, radius)
module Cue exposing (entity, length, offset, radius)

import Axis3d exposing (Axis3d)
import Camera3d exposing (Camera3d)
import Color exposing (Color)
import Cylinder3d exposing (Cylinder3d)
import Length exposing (Length, Meters)
import Physics.Coordinates exposing (WorldCoordinates)
import Point3d
import Quantity
import Scene3d exposing (Entity)
import Scene3d.Material as Material
import SketchPlane3d
import Viewpoint3d


length : Length
length =
Length.centimeters 150


radius : Length
radius =
Length.millimeters 6


{-| Cue offset from the cue ball
-}
offset : Length
offset =
Length.centimeters 2


entity : Camera3d Meters WorldCoordinates -> Length -> Axis3d Meters WorldCoordinates -> Color -> Entity WorldCoordinates
entity camera3d clipDepth axis color =
case cylinder camera3d clipDepth axis of
Just trimmedCylinder ->
Scene3d.cylinderWithShadow
(Material.nonmetal
{ baseColor = color
, roughness = 0.6
}
)
trimmedCylinder

Nothing ->
Scene3d.nothing


cylinder : Camera3d Meters WorldCoordinates -> Length -> Axis3d Meters WorldCoordinates -> Maybe (Cylinder3d Meters WorldCoordinates)
cylinder camera3d clipDepth axis =
let
Expand Down Expand Up @@ -44,20 +80,3 @@ cylinder camera3d clipDepth axis =
(Point3d.along axis offset)
(Point3d.along axis (Quantity.plus trimmedCueLength offset))
radius


length : Length
length =
Length.centimeters 150


radius : Length
radius =
Length.millimeters 6


{-| Cue offset from the cue ball
-}
offset : Length
offset =
Length.centimeters 2
Loading

0 comments on commit df11d5b

Please sign in to comment.