Importing code from previous merged project
This commit is contained in:
		
						commit
						33a452ad83
					
				
							
								
								
									
										16
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,16 @@ | |||||||
|  | /assg3-distrib/ | ||||||
|  | *.pdf | ||||||
|  | *.log | ||||||
|  | *.swp | ||||||
|  | *.suo | ||||||
|  | *.html | ||||||
|  | presentation/ | ||||||
|  | final/ | ||||||
|  | .idea/ | ||||||
|  | *.zip | ||||||
|  | elm-stuff/** | ||||||
|  | !elm-stuff/packages/ | ||||||
|  | !elm-stuff/packages/Zinggi/ | ||||||
|  | !elm-stuff/packages/Zinggi/elm-obj-loader/ | ||||||
|  | !elm-stuff/packages/Zinggi/elm-obj-loader/1.0.3/ | ||||||
|  | !elm-stuff/packages/Zinggi/elm-obj-loader/1.0.3/** | ||||||
							
								
								
									
										39
									
								
								README.org
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								README.org
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,39 @@ | |||||||
|  | ### FPS Scene | ||||||
|  | 
 | ||||||
|  | You can walk around the scene with simple FPS controls. | ||||||
|  | Open `scene.html` with an http server, you can use the following; | ||||||
|  | 
 | ||||||
|  | ```python3 -m http.server 8000``` | ||||||
|  | 
 | ||||||
|  | Unfortunately, elm-reactor has issues with loading obj files so that's why the | ||||||
|  | python server is needed. | ||||||
|  | 
 | ||||||
|  |  | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | ##### Controls | ||||||
|  | 
 | ||||||
|  | Mouse - Look Rotation | ||||||
|  | 
 | ||||||
|  | WASD - Player movement | ||||||
|  | 
 | ||||||
|  | ◀ ▼ ▲ ▶ - Move the Robot | ||||||
|  | 
 | ||||||
|  | N and M - Rotate robot left and right | ||||||
|  | 
 | ||||||
|  | Y and H - Rotate robot arm up and down | ||||||
|  | 
 | ||||||
|  | U and J - Rotate robot hand up and down | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | ### PQTorusknot | ||||||
|  | 
 | ||||||
|  | Either open up `torus.html`, or use the command `elm-reactor`, if you want to be able to modify the source file and compile; | ||||||
|  | 
 | ||||||
|  | https://guide.elm-lang.org/install.html | ||||||
|  | 
 | ||||||
|  | Alternatively, here's the Ellie link | ||||||
|  | 
 | ||||||
|  | https://ellie-app.com/vVTgpBj77ra1 | ||||||
|  | 
 | ||||||
|  |  | ||||||
							
								
								
									
										379
									
								
								Scene.elm
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										379
									
								
								Scene.elm
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,379 @@ | |||||||
|  | module Scene exposing (..) | ||||||
|  | 
 | ||||||
|  | import Html exposing (Html) | ||||||
|  | import Html.Attributes exposing (width, height, style) | ||||||
|  | import AnimationFrame | ||||||
|  | import Time exposing (Time) | ||||||
|  | import Dict exposing (..) | ||||||
|  | import Math.Matrix4 as Mat4 exposing (Mat4) | ||||||
|  | import Math.Vector2 as Vec2 exposing (vec2, Vec2) | ||||||
|  | import Math.Vector3 as Vec3 exposing (vec3, Vec3) | ||||||
|  | import WebGL exposing (Mesh, Shader) | ||||||
|  | import Mouse | ||||||
|  | import Keyboard exposing (..) | ||||||
|  | import Task | ||||||
|  | import WebGL.Texture as Texture exposing (..) | ||||||
|  | import Color exposing (..) | ||||||
|  | import Window | ||||||
|  | import OBJ | ||||||
|  | import OBJ.Types | ||||||
|  | import Shaders exposing (..) | ||||||
|  | 
 | ||||||
|  | type alias ObjVert = OBJ.Types.Vertex | ||||||
|  | type alias ObjMesh = OBJ.Types.MeshWith ObjVert | ||||||
|  | 
 | ||||||
|  | main : Program Never Model Msg | ||||||
|  | main = Html.program | ||||||
|  |     { init = init | ||||||
|  |     , view = view | ||||||
|  |     , update = update | ||||||
|  |     , subscriptions = subscriptions } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | type alias Model = | ||||||
|  |     { texDict : Dict String Texture | ||||||
|  |     , objDict : Dict String ObjMesh | ||||||
|  |     , rot : Float | ||||||
|  |     , winSize : Window.Size | ||||||
|  |     , keys : Keys | ||||||
|  |     , pos : Vec3 | ||||||
|  |     , pitchAndYaw : ( Float , Float ) | ||||||
|  |     , lookDir : Vec3 | ||||||
|  |     , lastMousePos : Mouse.Position | ||||||
|  |     , robot : Robot } | ||||||
|  | 
 | ||||||
|  | type alias Robot = { pos : Vec3 , rot : Float , armRot : Float , handRot : Float } | ||||||
|  | 
 | ||||||
|  | type alias Keys = | ||||||
|  |     { left : Bool , down : Bool , up : Bool , right : Bool | ||||||
|  |     , w : Bool , a : Bool , s : Bool , d : Bool | ||||||
|  |     , y : Bool , h : Bool , u : Bool , j : Bool | ||||||
|  |     , n : Bool , m : Bool } | ||||||
|  | 
 | ||||||
|  | type Msg | ||||||
|  |     = TextureLoaded (Result Texture.Error (String , Texture)) | ||||||
|  |     | ObjLoaded (Result String (String , ObjMesh)) | ||||||
|  |     | Animate Time | ||||||
|  |     | WindowResized Window.Size | ||||||
|  |     | MouseMove Mouse.Position | ||||||
|  |     | KeyChange Bool Keyboard.KeyCode | ||||||
|  | 
 | ||||||
|  | init: ( Model , Cmd Msg ) | ||||||
|  | init = | ||||||
|  |     ( Model | ||||||
|  |         Dict.empty | ||||||
|  |         Dict.empty | ||||||
|  |         0 | ||||||
|  |         (Window.Size 1 1) | ||||||
|  |         -- God this is horrendous | ||||||
|  |         (Keys False False False False False False False False False False False False False False) | ||||||
|  |         (vec3 0 0 -10) | ||||||
|  |         (0 , -90) | ||||||
|  |         (vec3 0 0 1) | ||||||
|  |         { x = 0 , y = 0 } | ||||||
|  |         { pos = vec3 0 -0.5 -3 , rot = 45 , armRot = 0 , handRot = 0 } | ||||||
|  |     , Cmd.batch | ||||||
|  |         [ loadTex "Thwomp" "textures/thwomp-face.jpg" | ||||||
|  |         , loadTex "UV" "textures/uv_big.png" | ||||||
|  |         , loadTex "Tetra" "textures/tetra.png" | ||||||
|  |         , loadObj "Teapot" "models/suz.obj" | ||||||
|  |         , Task.perform WindowResized Window.size] ) | ||||||
|  | 
 | ||||||
|  | loadTex: String -> String -> Cmd Msg | ||||||
|  | loadTex id path = | ||||||
|  |     Task.attempt TextureLoaded (Texture.load path |> Task.map (\t -> (id , t) ) ) | ||||||
|  | 
 | ||||||
|  | loadObj: String -> String -> Cmd Msg | ||||||
|  | loadObj id path = | ||||||
|  |     OBJ.loadMeshWithoutTexture path (\ r -> Result.map (\ o -> (id , o)) r ) |> Cmd.map ObjLoaded | ||||||
|  | 
 | ||||||
|  | subscriptions: Model -> Sub Msg | ||||||
|  | subscriptions _ = | ||||||
|  |     Sub.batch | ||||||
|  |         [ AnimationFrame.diffs Animate | ||||||
|  |         , Window.resizes WindowResized | ||||||
|  |         , Mouse.moves MouseMove | ||||||
|  |         , Keyboard.downs (KeyChange True) | ||||||
|  |         , Keyboard.ups (KeyChange False) ] | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | update: Msg -> Model -> (Model , Cmd Msg) | ||||||
|  | update msg model = | ||||||
|  |     let m = case msg of | ||||||
|  |             KeyChange b k -> { model | keys = getKeys b k model.keys } | ||||||
|  |             Animate dt -> | ||||||
|  |                 { model | ||||||
|  |                 | pos = movePos | ||||||
|  |                     (model.keys.a , model.keys.s , model.keys.w , model.keys.d) | ||||||
|  |                     model.lookDir | ||||||
|  |                     model.pos | ||||||
|  |                     0.2 | ||||||
|  |                 , robot = updateRobot model dt | ||||||
|  |                 , rot = model.rot + 0.001 * dt} | ||||||
|  |             WindowResized size -> { model | winSize = size } | ||||||
|  |             TextureLoaded result -> | ||||||
|  |                 case result of | ||||||
|  |                     Ok (id , tex) -> { model | texDict = Dict.insert id tex model.texDict } | ||||||
|  |                     Err e -> model | ||||||
|  |             ObjLoaded result -> | ||||||
|  |                 case result of | ||||||
|  |                     Ok (id , obj) -> { model | objDict = Dict.insert id obj model.objDict } | ||||||
|  |                     Err e -> model |> Debug.log e | ||||||
|  |             MouseMove mp -> | ||||||
|  |                 let (ld , py) = getLookPos model.lastMousePos mp model.pitchAndYaw | ||||||
|  |                 in { model | lookDir = ld , lastMousePos = mp , pitchAndYaw = py } | ||||||
|  |     in ( m , Cmd.none ) | ||||||
|  | 
 | ||||||
|  | updateRobot: Model -> Time -> Robot | ||||||
|  | updateRobot { robot , keys } dt = | ||||||
|  |     let rr part = part + dt * 0.005 | ||||||
|  |         rl part = part - dt * 0.005 | ||||||
|  |         rot = radians robot.rot | ||||||
|  |     in { pos = | ||||||
|  |            movePos | ||||||
|  |                (keys.left, keys.down, keys.up, keys.right) | ||||||
|  |                (vec3 (sin rot) (sin rot) (cos rot)) | ||||||
|  |                robot.pos | ||||||
|  |                0.1 | ||||||
|  |     , rot = if keys.n then rr robot.rot else if keys.m then rl robot.rot else robot.rot | ||||||
|  |     , armRot = | ||||||
|  |         let angle = if keys.y then rr robot.armRot else if keys.h then rl robot.armRot else robot.armRot | ||||||
|  |         in clamp -0.5 2.5 angle | ||||||
|  |     , handRot = | ||||||
|  |         let angle = if keys.u then rr robot.handRot else if keys.j then rl robot.handRot else robot.handRot | ||||||
|  |         in clamp -1 1 angle} | ||||||
|  | 
 | ||||||
|  | view: Model -> Html Msg | ||||||
|  | view model = | ||||||
|  |     WebGL.toHtml | ||||||
|  |         [ width model.winSize.width , height model.winSize.height , style [ ( "display" , "block") ] ] | ||||||
|  |         ([ getEntity model wall texturedPlane "Thwomp" | ||||||
|  |         , getEntity model tetraB tetraBasic "UV" | ||||||
|  |         , getEntity model tetra tetraF "Tetra" | ||||||
|  |         , getRobot model | ||||||
|  |         , getModel model (Mat4.makeRotate model.rot Vec3.j) "Teapot" | ||||||
|  |         , getEntity model floor texturedPlane "UV" ] |> List.concat) | ||||||
|  | 
 | ||||||
|  | getRobot: Model -> List WebGL.Entity | ||||||
|  | getRobot model = | ||||||
|  |     let body = Mat4.makeTranslate model.robot.pos | ||||||
|  |             |> Mat4.rotate model.robot.rot Vec3.j | ||||||
|  |         arm  = Mat4.makeTranslate3 0 0 -0.35 | ||||||
|  |             |> Mat4.rotate model.robot.armRot Vec3.i | ||||||
|  |             |> Mat4.inverse |> Maybe.withDefault Mat4.identity | ||||||
|  |             |> Mat4.mul (Mat4.makeTranslate3 0 0.5 0.5) | ||||||
|  |             |> Mat4.mul body | ||||||
|  |         hand = Mat4.makeTranslate3 0 0 -0.25 | ||||||
|  |             |> Mat4.rotate model.robot.handRot Vec3.i | ||||||
|  |             |> Mat4.inverse |> Maybe.withDefault Mat4.identity | ||||||
|  |             |> Mat4.mul (Mat4.makeTranslate3 0 0 0.6) | ||||||
|  |             |> Mat4.mul arm | ||||||
|  |     in [ getEntity3 model (body |> Mat4.scale3 0.5 0.5 0.5) cube Color.blue | ||||||
|  |        , getEntity3 model (arm |> Mat4.scale3 0.2 0.2 0.5) cube Color.green | ||||||
|  |        , getEntity3 model (hand |> Mat4.scale3 0.15 0.15 0.45) cube Color.red | ||||||
|  |        ] |> List.concat | ||||||
|  | 
 | ||||||
|  | getModel: Model -> Mat4 -> String -> List WebGL.Entity | ||||||
|  | getModel model local id = | ||||||
|  |     case Dict.get id model.objDict of | ||||||
|  |         Just mesh -> | ||||||
|  |             case Dict.get "UV" model.texDict of | ||||||
|  |                 Just t -> [ WebGL.entity | ||||||
|  |                     diffuseVS | ||||||
|  |                     diffuseFS | ||||||
|  |                     (WebGL.indexedTriangles mesh.vertices mesh.indices) | ||||||
|  |                     (DiffuseColor | ||||||
|  |                         (projectionMatrix model) | ||||||
|  |                         (viewMatrix model) | ||||||
|  |                         local | ||||||
|  |                         (colorToVec3 Color.blue) | ||||||
|  |                         (vec3 1 1 0) | ||||||
|  |                         (vec3 1 0 1) | ||||||
|  |                         (vec3 0 0 1) | ||||||
|  |                         1.0) ] | ||||||
|  |                 Nothing -> [] | ||||||
|  |         Nothing -> [] | ||||||
|  | 
 | ||||||
|  | getEntity: Model -> Mat4 -> Mesh UTVertex -> String -> List WebGL.Entity | ||||||
|  | getEntity model local mesh texId = | ||||||
|  |     case Dict.get texId model.texDict of | ||||||
|  |         Just t -> | ||||||
|  |             [ WebGL.entity | ||||||
|  |                 unlitTexturedVS | ||||||
|  |                 unlitTexturedFS | ||||||
|  |                 mesh | ||||||
|  |                 (UnlitTextured (projectionMatrix model) (viewMatrix model ) local t) ] | ||||||
|  |         Nothing -> [] | ||||||
|  | 
 | ||||||
|  | getEntity2: Model -> Mat4 -> Mesh ObjVert -> Color -> List WebGL.Entity | ||||||
|  | getEntity2 model local mesh color = | ||||||
|  |     [ WebGL.entity | ||||||
|  |         unlitColorVS | ||||||
|  |         unlitColorFS | ||||||
|  |         mesh | ||||||
|  |         (UnlitColor (projectionMatrix model) (viewMatrix model ) local (colorToVec3 color) ) ] | ||||||
|  | 
 | ||||||
|  | getEntity3: Model -> Mat4 -> Mesh ObjVert -> Color -> List WebGL.Entity | ||||||
|  | getEntity3 model local mesh color = | ||||||
|  |     [ WebGL.entity | ||||||
|  |         diffuseVS | ||||||
|  |         diffuseFS | ||||||
|  |         mesh | ||||||
|  |         (DiffuseColor | ||||||
|  |             (projectionMatrix model) | ||||||
|  |             (viewMatrix model) | ||||||
|  |             local | ||||||
|  |             (colorToVec3 color) | ||||||
|  |             (vec3 1 1 0) | ||||||
|  |             (vec3 1 0 1) | ||||||
|  |             (vec3 0 0 1) | ||||||
|  |             1.0 ) ] | ||||||
|  | 
 | ||||||
|  | projectionMatrix: Model -> Mat4 | ||||||
|  | projectionMatrix model = | ||||||
|  |     Mat4.makePerspective 50 (toFloat model.winSize.width / toFloat model.winSize.height) 0.01 1000 | ||||||
|  | 
 | ||||||
|  | viewMatrix: Model -> Mat4 | ||||||
|  | viewMatrix model = | ||||||
|  |     Mat4.makeLookAt model.pos (Vec3.add model.pos model.lookDir) Vec3.j | ||||||
|  | 
 | ||||||
|  | getLookPos: Mouse.Position -> Mouse.Position -> ( Float , Float ) -> ( Vec3 , (Float , Float) ) | ||||||
|  | getLookPos lmp mp ( lastPitch , lastYaw ) = | ||||||
|  |     let sensitivity = 0.0039 | ||||||
|  |         rangeY = 89 | ||||||
|  |         ox = mp.x - lmp.x |> toFloat | ||||||
|  |         oy = lmp.y - mp.y |> toFloat | ||||||
|  |         yaw = ox * sensitivity + lastYaw |> radians | ||||||
|  |         pitch = -oy * sensitivity + lastPitch |> radians | ||||||
|  |         pitch_ = if pitch > rangeY then rangeY else if pitch < -rangeY then -rangeY else pitch | ||||||
|  |         lookDir = vec3 (cos yaw * cos pitch_) (sin pitch_) (sin yaw * cos pitch_) | ||||||
|  |     in (Vec3.normalize lookDir , ( pitch_ , yaw ) ) | ||||||
|  | 
 | ||||||
|  | colorToVec3: Color -> Vec3 | ||||||
|  | colorToVec3 color = | ||||||
|  |     let to01 x = toFloat x / 255 | ||||||
|  |         c = Color.toRgb color | ||||||
|  |     in vec3 (to01 c.red) (to01 c.green) (to01 c.blue) | ||||||
|  | 
 | ||||||
|  | movePos: (Bool, Bool, Bool, Bool) -> Vec3 -> Vec3 -> Float -> Vec3 | ||||||
|  | movePos ( left , down , up , right ) lookDir pos speed = | ||||||
|  |     let lookDir_ = Vec3.setY 0 lookDir | ||||||
|  |         forward = if up then 1 else if down then -1 else 0 | ||||||
|  |         strafe = if right then 1 else if left then -1 else 0 | ||||||
|  |         cross = Vec3.cross lookDir_ Vec3.j | ||||||
|  |         dir = Vec3.add (Vec3.scale strafe cross) (Vec3.scale forward lookDir_) | ||||||
|  |         dir_ = if Vec3.length dir <= 0 then dir else Vec3.normalize dir | ||||||
|  |     in Vec3.add pos <| Vec3.scale speed dir_ | ||||||
|  | 
 | ||||||
|  | getKeys: Bool -> KeyCode -> Keys -> Keys | ||||||
|  | getKeys isOn code keys = | ||||||
|  |     case code of | ||||||
|  |         -- ◀ ▼ ▲ ▶ | ||||||
|  |         37 -> { keys | left = isOn } | ||||||
|  |         40 -> { keys | down = isOn } | ||||||
|  |         38 -> { keys | up = isOn } | ||||||
|  |         39 -> { keys | right = isOn } | ||||||
|  |         -- WASD | ||||||
|  |         87 -> { keys | w = isOn } | ||||||
|  |         65 -> { keys | a = isOn } | ||||||
|  |         83 -> { keys | s = isOn } | ||||||
|  |         68 -> { keys | d = isOn } | ||||||
|  |         -- YHUJNM | ||||||
|  |         89 -> { keys | y = isOn } | ||||||
|  |         72 -> { keys | h = isOn } | ||||||
|  |         85 -> { keys | u = isOn } | ||||||
|  |         74 -> { keys | j = isOn } | ||||||
|  |         78 -> { keys | n = isOn } | ||||||
|  |         77 -> { keys | m = isOn } | ||||||
|  |         _ -> keys | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | ------------- | ||||||
|  | -- Geometry | ||||||
|  | ------------- | ||||||
|  | 
 | ||||||
|  | wall = Mat4.makeTranslate3 0 0 3 | ||||||
|  | floor = Mat4.makeTranslate3 0 -1 0 | ||||||
|  |         |> Mat4.rotate (pi / -2) ( vec3 1 0 0) | ||||||
|  |         |> Mat4.rotate pi ( vec3 0 0 1) | ||||||
|  |         |> Mat4.scale3 15 15 0 | ||||||
|  | tetraB = Mat4.makeTranslate3 -5 1.5 5 | ||||||
|  |         |> Mat4.scale3 2 2 2 | ||||||
|  | tetra = Mat4.makeTranslate3 5 0 5 | ||||||
|  | 
 | ||||||
|  | -- right/left front/back top/bottom | ||||||
|  | cube: Mesh ObjVert | ||||||
|  | cube = | ||||||
|  |     let rtf = vec3 1 1 1 | ||||||
|  |         ltf = vec3 -1 1 1 | ||||||
|  |         ltb = vec3 -1 1 -1 | ||||||
|  |         rtb = vec3 1 1 -1 | ||||||
|  |         rbb = vec3 1 -1 -1 | ||||||
|  |         rbf = vec3 1 -1 1 | ||||||
|  |         lbf = vec3 -1 -1 1 | ||||||
|  |         lbb = vec3 -1 -1 -1 | ||||||
|  |         front = Vec3.k | ||||||
|  |         back = Vec3.scale -1 front | ||||||
|  |         top = Vec3.j | ||||||
|  |         bottom = Vec3.scale -1 top | ||||||
|  |         right = Vec3.i | ||||||
|  |         left = Vec3.scale -1 right | ||||||
|  |     in | ||||||
|  |         [ face right rtf rbf rbb rtb | ||||||
|  |         , face left ltf lbf lbb ltb | ||||||
|  |         , face front rtf rbf lbf ltf | ||||||
|  |         , face back rtb rbb lbb ltb | ||||||
|  |         , face top rtf ltf ltb rtb | ||||||
|  |         , face bottom rbf lbf lbb rbb | ||||||
|  |         ] |> List.concat | ||||||
|  |           |> WebGL.triangles | ||||||
|  | 
 | ||||||
|  | face: Vec3 -> Vec3 -> Vec3 -> Vec3 -> Vec3 -> List (ObjVert , ObjVert , ObjVert) | ||||||
|  | face norm a b c d = | ||||||
|  |     let v pos = OBJ.Types.Vertex pos norm | ||||||
|  |     in [ ( v a , v b , v c ) , ( v c , v d , v a ) ] | ||||||
|  | 
 | ||||||
|  | tetraBasic: Mesh UTVertex | ||||||
|  | tetraBasic = | ||||||
|  |     let peak = UTVertex (vec3 0 1 0) (vec2 1 1) | ||||||
|  |         bottomLeft = UTVertex (vec3 -1 -1 -1) (vec2 0 0) | ||||||
|  |         bottomRight = UTVertex (vec3 -1 -1 1) (vec2 1 0) | ||||||
|  |         topLeft = UTVertex (vec3 1 -1 1) (vec2 0 0) | ||||||
|  |         topRight = UTVertex (vec3 1 -1 -1) (vec2 0 1) | ||||||
|  |     in [ ( peak , bottomLeft , bottomRight ) | ||||||
|  |        , ( peak , bottomLeft , topRight ) | ||||||
|  |        , ( peak , bottomRight , topLeft ) | ||||||
|  |        , ( peak , topRight , topLeft ) | ||||||
|  |        , ( bottomLeft , bottomRight , topRight) | ||||||
|  |        , ( bottomRight, topLeft , topRight ) ] | ||||||
|  |        |> WebGL.triangles | ||||||
|  | 
 | ||||||
|  | tetraF: Mesh UTVertex | ||||||
|  | tetraF = | ||||||
|  |     let f0a = UTVertex (vec3 -1 -1 1) (vec2 0 0.5) | ||||||
|  |         f0b = UTVertex (vec3 1 -1 1) (vec2 0.5 0.5) | ||||||
|  |         f0c = UTVertex (vec3 0 1 0) (vec2 0.25 1) | ||||||
|  | 
 | ||||||
|  |         f1a = UTVertex (vec3 -1 -1 -1) (vec2 0.5 0.5) | ||||||
|  |         f1b = UTVertex (vec3 -1 -1 1) (vec2 1 0.5) | ||||||
|  |         f1c = UTVertex (vec3 0 1 0) (vec2 0.75 1) | ||||||
|  | 
 | ||||||
|  |         f2a = UTVertex (vec3 1 -1 -1) (vec2 0 0) | ||||||
|  |         f2b = UTVertex (vec3 -1 -1 -1) (vec2 0.5 0) | ||||||
|  |         f2c = UTVertex (vec3 0 1 0) (vec2 0.25 0.5) | ||||||
|  | 
 | ||||||
|  |         f3a = UTVertex (vec3 1 -1 1) (vec2 0.5 0) | ||||||
|  |         f3b = UTVertex (vec3 1 -1 -1) (vec2 1 0) | ||||||
|  |         f3c = UTVertex (vec3 0 1 0) (vec2 0.75 0.5) | ||||||
|  |     in [ ( f0a , f0b , f0c ) , ( f1a , f1b , f1c ) , ( f2a , f2b , f2c ) , ( f3a , f3b , f3c ) ] | ||||||
|  |        |> WebGL.triangles | ||||||
|  | 
 | ||||||
|  | texturedPlane: Mesh UTVertex | ||||||
|  | texturedPlane = | ||||||
|  |     let topLeft = UTVertex (vec3 -1 1 1) (vec2 0 1) | ||||||
|  |         topRight = UTVertex (vec3 1 1 1) (vec2 1 1) | ||||||
|  |         bottomLeft = UTVertex (vec3 -1 -1 1) (vec2 0 0) | ||||||
|  |         bottomRight = UTVertex (vec3 1 -1 1) (vec2 1 0) | ||||||
|  |     in [ ( topLeft, topRight, bottomLeft ) , ( bottomLeft, topRight, bottomRight ) ] | ||||||
|  |        |> WebGL.triangles | ||||||
|  | 
 | ||||||
							
								
								
									
										130
									
								
								Shaders.elm
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										130
									
								
								Shaders.elm
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,130 @@ | |||||||
|  | module Shaders exposing (..) | ||||||
|  | 
 | ||||||
|  | import Math.Matrix4 as Mat4 exposing (Mat4) | ||||||
|  | import Math.Vector2 as Vec2 exposing (vec2, Vec2) | ||||||
|  | import Math.Vector3 as Vec3 exposing (vec3, Vec3) | ||||||
|  | import WebGL exposing (Mesh, Shader) | ||||||
|  | import WebGL.Texture as Texture exposing (..) | ||||||
|  | import OBJ | ||||||
|  | import OBJ.Types | ||||||
|  | 
 | ||||||
|  | type alias UTVertex = { position : Vec3 , coord : Vec2 } | ||||||
|  | type alias ColorVertex = { position : Vec3 , normal : Vec3 , color : Vec3 } | ||||||
|  | 
 | ||||||
|  | type alias UnlitColor = { projection : Mat4 , view : Mat4 , model : Mat4 , color : Vec3 } | ||||||
|  | type alias UnlitTextured = { projection : Mat4 , view : Mat4 , model : Mat4 , texture : Texture } | ||||||
|  | type alias DiffuseColor = | ||||||
|  |     { projection : Mat4 | ||||||
|  |     , view : Mat4 | ||||||
|  |     , model : Mat4 | ||||||
|  |     , color : Vec3 | ||||||
|  |     , ambient : Vec3 | ||||||
|  |     , diffuse : Vec3 | ||||||
|  |     , specular : Vec3 | ||||||
|  |     , shininess : Float } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | diffuseVS: Shader { position : Vec3 , normal : Vec3 } DiffuseColor { vlightWeight : Vec3 } | ||||||
|  | diffuseVS = | ||||||
|  |     [glsl| | ||||||
|  |         attribute vec3 position; | ||||||
|  |         attribute vec3 normal; | ||||||
|  |         uniform mat4 projection; | ||||||
|  |         uniform mat4 view; | ||||||
|  |         uniform mat4 model; | ||||||
|  |         uniform vec3 ambient; | ||||||
|  |         uniform vec3 diffuse; | ||||||
|  |         uniform vec3 specular; | ||||||
|  |         uniform float shininess; | ||||||
|  |         varying vec3 vlightWeight; | ||||||
|  | 
 | ||||||
|  |         void main() | ||||||
|  |         { | ||||||
|  |             gl_Position = projection * view * model * vec4(position, 1.0); | ||||||
|  | 
 | ||||||
|  |             vec3 lightDir = normalize(vec3(0.0, -0.0, -1.0)); | ||||||
|  |             vec4 norm =  model * vec4(normal, 0.0); | ||||||
|  |             vec3 n = norm.xyz; | ||||||
|  |             float dir = max(dot(n, lightDir), 0.0); | ||||||
|  |             float v = 0.5; | ||||||
|  |             vlightWeight = diffuse * dir + vec3(v, v, v); | ||||||
|  |         } | ||||||
|  |     |] | ||||||
|  | 
 | ||||||
|  | diffuseFS: Shader {} DiffuseColor { vlightWeight : Vec3 } | ||||||
|  | diffuseFS = | ||||||
|  |     [glsl| | ||||||
|  | 
 | ||||||
|  |         precision mediump float; | ||||||
|  |         uniform vec3 color; | ||||||
|  |         varying vec3 vlightWeight; | ||||||
|  | 
 | ||||||
|  |         void main() | ||||||
|  |         { | ||||||
|  |             gl_FragColor = vec4(color * vlightWeight, 1.0); | ||||||
|  |         } | ||||||
|  |     |] | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | unlitColorVS: Shader OBJ.Types.Vertex UnlitColor { vcolor : Vec3 } | ||||||
|  | unlitColorVS = | ||||||
|  |     [glsl| | ||||||
|  |         attribute vec3 position; | ||||||
|  |         attribute vec3 normal; | ||||||
|  |         uniform mat4 projection; | ||||||
|  |         uniform mat4 view; | ||||||
|  |         uniform mat4 model; | ||||||
|  |         uniform vec3 color; | ||||||
|  |         varying vec3 vcolor; | ||||||
|  | 
 | ||||||
|  |         void main() | ||||||
|  |         { | ||||||
|  |             gl_Position = projection * view * model * vec4(position, 1.0); | ||||||
|  |             vcolor = color; | ||||||
|  |         } | ||||||
|  |     |] | ||||||
|  | 
 | ||||||
|  | unlitColorFS: Shader {} UnlitColor { vcolor : Vec3 } | ||||||
|  | unlitColorFS = | ||||||
|  |     [glsl| | ||||||
|  | 
 | ||||||
|  |         precision mediump float; | ||||||
|  |         varying vec3 vcolor; | ||||||
|  | 
 | ||||||
|  |         void main() | ||||||
|  |         { | ||||||
|  |             gl_FragColor = vec4(vcolor, 1.0); | ||||||
|  |         } | ||||||
|  |     |] | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | unlitTexturedVS: Shader { position : Vec3 , coord : Vec2 } UnlitTextured { vcoord : Vec2 } | ||||||
|  | unlitTexturedVS = | ||||||
|  |     [glsl| | ||||||
|  |         attribute vec3 position; | ||||||
|  |         attribute vec2 coord; | ||||||
|  |         uniform mat4 projection; | ||||||
|  |         uniform mat4 view; | ||||||
|  |         uniform mat4 model; | ||||||
|  |         varying vec2 vcoord; | ||||||
|  | 
 | ||||||
|  |         void main() | ||||||
|  |         { | ||||||
|  |             gl_Position = projection * view * model * vec4(position, 1.0); | ||||||
|  |             vcoord = coord; | ||||||
|  |         } | ||||||
|  |     |] | ||||||
|  | 
 | ||||||
|  | unlitTexturedFS: Shader {} UnlitTextured { vcoord : Vec2 } | ||||||
|  | unlitTexturedFS = | ||||||
|  |     [glsl| | ||||||
|  | 
 | ||||||
|  |         precision mediump float; | ||||||
|  |         uniform sampler2D texture; | ||||||
|  |         varying vec2 vcoord; | ||||||
|  | 
 | ||||||
|  |         void main() | ||||||
|  |         { | ||||||
|  |             gl_FragColor = texture2D(texture, vcoord); | ||||||
|  |         } | ||||||
|  |     |] | ||||||
							
								
								
									
										22
									
								
								elm-package.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								elm-package.json
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,22 @@ | |||||||
|  | { | ||||||
|  |     "version": "1.0.0", | ||||||
|  |     "summary": "helpful summary of your project, less than 80 characters", | ||||||
|  |     "repository": "https://github.com/user/project.git", | ||||||
|  |     "license": "BSD3", | ||||||
|  |     "source-directories": [ | ||||||
|  |         "." | ||||||
|  |     ], | ||||||
|  |     "exposed-modules": [], | ||||||
|  |     "dependencies": { | ||||||
|  |         "Zinggi/elm-obj-loader": "1.0.3 <= v < 2.0.0", | ||||||
|  |         "elm-community/linear-algebra": "3.1.2 <= v < 4.0.0", | ||||||
|  |         "elm-community/webgl": "2.0.5 <= v < 3.0.0", | ||||||
|  |         "elm-lang/animation-frame": "1.0.1 <= v < 2.0.0", | ||||||
|  |         "elm-lang/core": "5.1.1 <= v < 6.0.0", | ||||||
|  |         "elm-lang/html": "2.0.0 <= v < 3.0.0", | ||||||
|  |         "elm-lang/keyboard": "1.0.1 <= v < 2.0.0", | ||||||
|  |         "elm-lang/mouse": "1.0.1 <= v < 2.0.0", | ||||||
|  |         "elm-lang/window": "1.0.1 <= v < 2.0.0" | ||||||
|  |     }, | ||||||
|  |     "elm-version": "0.18.0 <= v < 0.19.0" | ||||||
|  | } | ||||||
							
								
								
									
										6
									
								
								elm-stuff/packages/Zinggi/elm-obj-loader/1.0.3/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								elm-stuff/packages/Zinggi/elm-obj-loader/1.0.3/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,6 @@ | |||||||
|  | elm-stuff/ | ||||||
|  | index.html | ||||||
|  | src/Main.elm | ||||||
|  | documentation.json | ||||||
|  | # this is only for debugging | ||||||
|  | src/Native/ | ||||||
							
								
								
									
										21
									
								
								elm-stuff/packages/Zinggi/elm-obj-loader/1.0.3/LICENSE
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								elm-stuff/packages/Zinggi/elm-obj-loader/1.0.3/LICENSE
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,21 @@ | |||||||
|  | MIT License | ||||||
|  | 
 | ||||||
|  | Copyright (c) 2016 Florian Zinggeler | ||||||
|  | 
 | ||||||
|  | Permission is hereby granted, free of charge, to any person obtaining a copy | ||||||
|  | of this software and associated documentation files (the "Software"), to deal | ||||||
|  | in the Software without restriction, including without limitation the rights | ||||||
|  | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||||
|  | copies of the Software, and to permit persons to whom the Software is | ||||||
|  | furnished to do so, subject to the following conditions: | ||||||
|  | 
 | ||||||
|  | The above copyright notice and this permission notice shall be included in all | ||||||
|  | copies or substantial portions of the Software. | ||||||
|  | 
 | ||||||
|  | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||||
|  | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||||
|  | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||||
|  | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||||
|  | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||||
|  | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||||
|  | SOFTWARE. | ||||||
							
								
								
									
										34
									
								
								elm-stuff/packages/Zinggi/elm-obj-loader/1.0.3/README.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								elm-stuff/packages/Zinggi/elm-obj-loader/1.0.3/README.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,34 @@ | |||||||
|  | # elm-obj-loader | ||||||
|  | 
 | ||||||
|  | This is a small library for importing [wavefront .obj][objSpecs] files into your WebGL application. | ||||||
|  | 
 | ||||||
|  | # Demo/Examples | ||||||
|  |  * [Model viewer][modelViewer] | ||||||
|  |  * [Suzanne from Blender][suzanne] | ||||||
|  | 
 | ||||||
|  | [Src](/examples) | ||||||
|  | 
 | ||||||
|  | # Limitations | ||||||
|  | Only a small subset of the .obj file specification is supported. | ||||||
|  | 
 | ||||||
|  | The easiest is to export/convert your model from Blender or another 3D content creation tool as an .obj file. | ||||||
|  | 
 | ||||||
|  | The default export options from blender work fine. Make sure you keep 'Write Normals' selected. | ||||||
|  | 
 | ||||||
|  | Completely supported face types are those with vertex position, normals and optionally vertex texture coordinates. (`v`, `vn`, `vt`) | ||||||
|  | 
 | ||||||
|  | Smooth groups are ignored (`s n`).   | ||||||
|  | Your model needs vertex normals (`vn`).   | ||||||
|  | 
 | ||||||
|  | Only tris and quads are supported. (Tris might load slightly faster)     | ||||||
|  | No free-form curves/surfaces.     | ||||||
|  | No material library (mtllib) support.    | ||||||
|  | No negative indexing.    | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | [suzanne]: https://zinggi.github.io/randomDemos/webgl/objLoader_simple.html | ||||||
|  | [modelViewer]: https://zinggi.github.io/randomDemos/webgl/objLoader_modelViewer.html | ||||||
|  | [objSpecs]: http://www.martinreddy.net/gfx/3d/OBJ.spec | ||||||
							
								
								
									
										22
									
								
								elm-stuff/packages/Zinggi/elm-obj-loader/1.0.3/elm-package.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								elm-stuff/packages/Zinggi/elm-obj-loader/1.0.3/elm-package.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,22 @@ | |||||||
|  | { | ||||||
|  |     "version": "1.0.3", | ||||||
|  |     "summary": "Load wavefront .obj files in your WebGL scene.", | ||||||
|  |     "repository": "https://github.com/Zinggi/elm-obj-loader.git", | ||||||
|  |     "license": "MIT", | ||||||
|  |     "source-directories": [ | ||||||
|  |         "src" | ||||||
|  |     ], | ||||||
|  |     "exposed-modules": [ | ||||||
|  |         "OBJ", | ||||||
|  |         "OBJ.Types" | ||||||
|  |     ], | ||||||
|  |     "dependencies": { | ||||||
|  |         "Bogdanp/elm-combine": "3.1.1 <= v < 4.0.0", | ||||||
|  |         "Skinney/elm-array-exploration": "2.0.1 <= v < 3.0.0", | ||||||
|  |         "elm-community/linear-algebra": "3.1.0 <= v < 4.0.0", | ||||||
|  |         "elm-community/webgl": "2.0.0 <= v < 3.0.0", | ||||||
|  |         "elm-lang/core": "5.0.0 <= v < 6.0.0", | ||||||
|  |         "elm-lang/http": "1.0.0 <= v < 2.0.0" | ||||||
|  |     }, | ||||||
|  |     "elm-version": "0.18.0 <= v < 0.19.0" | ||||||
|  | } | ||||||
							
								
								
									
										3
									
								
								elm-stuff/packages/Zinggi/elm-obj-loader/1.0.3/examples/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								elm-stuff/packages/Zinggi/elm-obj-loader/1.0.3/examples/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | |||||||
|  | elm-stuff/ | ||||||
|  | index.html | ||||||
|  | testObjs/ | ||||||
							
								
								
									
										299
									
								
								elm-stuff/packages/Zinggi/elm-obj-loader/1.0.3/examples/ElmLogo.elm
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										299
									
								
								elm-stuff/packages/Zinggi/elm-obj-loader/1.0.3/examples/ElmLogo.elm
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,299 @@ | |||||||
|  | module ElmLogo exposing (..) | ||||||
|  | 
 | ||||||
|  | import AnimationFrame | ||||||
|  | import Dict exposing (Dict) | ||||||
|  | import Html exposing (Html, div, text) | ||||||
|  | import Html.Attributes as Attr | ||||||
|  | import Html.Events exposing (on, onInput, onCheck) | ||||||
|  | import Json.Decode as JD | ||||||
|  | import Math.Matrix4 as M4 exposing (Mat4) | ||||||
|  | import Math.Vector3 as V3 exposing (Vec3, vec3) | ||||||
|  | import Task | ||||||
|  | import WebGL as GL | ||||||
|  | import WebGL.Texture | ||||||
|  | import WebGL.Settings exposing (cullFace, front) | ||||||
|  | import WebGL.Settings.DepthTest as DepthTest | ||||||
|  | import Mouse | ||||||
|  | import Window | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | -- | ||||||
|  | 
 | ||||||
|  | import Shaders | ||||||
|  | import OBJ | ||||||
|  | import OBJ.Types exposing (ObjFile, Mesh(..)) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | main : Program Never Model Msg | ||||||
|  | main = | ||||||
|  |     Html.program | ||||||
|  |         { init = ( initModel, initCmd ) | ||||||
|  |         , view = view | ||||||
|  |         , subscriptions = subscriptions | ||||||
|  |         , update = update | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | -- MODEL | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | type alias Model = | ||||||
|  |     { time : Float | ||||||
|  |     , mesh : Result String ObjFile | ||||||
|  |     , currentModel : String | ||||||
|  |     , zoom : Float | ||||||
|  |     , diffText : Result String GL.Texture | ||||||
|  |     , normText : Result String GL.Texture | ||||||
|  |     , isDown : Bool | ||||||
|  |     , lastMousePos : Mouse.Position | ||||||
|  |     , mouseDelta : MouseDelta | ||||||
|  |     , windowSize : Window.Size | ||||||
|  |     , withTangent : Bool | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | type alias MouseDelta = | ||||||
|  |     { x : Float, y : Float } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | initModel : Model | ||||||
|  | initModel = | ||||||
|  |     { mesh = Err "loading ..." | ||||||
|  |     , currentModel = "meshes/elmLogo.obj" | ||||||
|  |     , time = 0 | ||||||
|  |     , zoom = 5 | ||||||
|  |     , diffText = Err "Loading texture..." | ||||||
|  |     , normText = Err "Loading texture..." | ||||||
|  |     , isDown = False | ||||||
|  |     , lastMousePos = Mouse.Position 0 0 | ||||||
|  |     , mouseDelta = MouseDelta 0 (pi / 2) | ||||||
|  |     , windowSize = Window.Size 800 600 | ||||||
|  |     , withTangent = True | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | models : List String | ||||||
|  | models = | ||||||
|  |     [ "meshes/elmLogo.obj" | ||||||
|  |     , "meshes/suzanneNoUV.obj" | ||||||
|  |     ] | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | initCmd : Cmd Msg | ||||||
|  | initCmd = | ||||||
|  |     Cmd.batch | ||||||
|  |         [ loadModel True "meshes/elmLogo.obj" | ||||||
|  |         , loadTexture "textures/elmLogoDiffuse.png" DiffTextureLoaded | ||||||
|  |         , loadTexture "textures/elmLogoNorm.png" NormTextureLoaded | ||||||
|  |         , Task.perform ResizeWindow Window.size | ||||||
|  |         ] | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | loadModel : Bool -> String -> Cmd Msg | ||||||
|  | loadModel withTangents url = | ||||||
|  |     OBJ.loadObjFileWith { withTangents = withTangents } url (LoadObj url) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | -- UPDATE | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | type Msg | ||||||
|  |     = Tick Float | ||||||
|  |     | LoadObj String (Result String (Dict String (Dict String Mesh))) | ||||||
|  |     | Zoom Float | ||||||
|  |     | MouseMove Mouse.Position | ||||||
|  |     | MouseDown Mouse.Position | ||||||
|  |     | MouseUp | ||||||
|  |     | DiffTextureLoaded (Result String GL.Texture) | ||||||
|  |     | NormTextureLoaded (Result String GL.Texture) | ||||||
|  |     | ResizeWindow Window.Size | ||||||
|  |     | SelectMesh String | ||||||
|  |     | SetUseTangent Bool | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | update : Msg -> Model -> ( Model, Cmd Msg ) | ||||||
|  | update msg model = | ||||||
|  |     case msg of | ||||||
|  |         Tick dt -> | ||||||
|  |             ( { model | time = model.time + dt / 1000 }, Cmd.none ) | ||||||
|  | 
 | ||||||
|  |         Zoom dy -> | ||||||
|  |             ( { model | zoom = max 0.01 (model.zoom + dy / 100) }, Cmd.none ) | ||||||
|  | 
 | ||||||
|  |         SelectMesh url -> | ||||||
|  |             ( model, loadModel model.withTangent url ) | ||||||
|  | 
 | ||||||
|  |         SetUseTangent t -> | ||||||
|  |             ( { model | withTangent = t }, loadModel t model.currentModel ) | ||||||
|  | 
 | ||||||
|  |         LoadObj url mesh -> | ||||||
|  |             ( { model | mesh = mesh, currentModel = url }, Cmd.none ) | ||||||
|  | 
 | ||||||
|  |         DiffTextureLoaded t -> | ||||||
|  |             ( { model | diffText = t }, Cmd.none ) | ||||||
|  | 
 | ||||||
|  |         NormTextureLoaded t -> | ||||||
|  |             ( { model | normText = t }, Cmd.none ) | ||||||
|  | 
 | ||||||
|  |         MouseDown p -> | ||||||
|  |             ( { model | isDown = True, lastMousePos = p }, Cmd.none ) | ||||||
|  | 
 | ||||||
|  |         MouseUp -> | ||||||
|  |             ( { model | isDown = False }, Cmd.none ) | ||||||
|  | 
 | ||||||
|  |         MouseMove p -> | ||||||
|  |             ( { model | mouseDelta = getDelta p model.lastMousePos model.mouseDelta, lastMousePos = p }, Cmd.none ) | ||||||
|  | 
 | ||||||
|  |         ResizeWindow w -> | ||||||
|  |             ( { model | windowSize = w }, Cmd.none ) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | -- VIEW / RENDER | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | renderModel : Model -> GL.Texture -> GL.Texture -> Mesh -> GL.Entity | ||||||
|  | renderModel model textureDiff textureNorm mesh = | ||||||
|  |     let | ||||||
|  |         ( camera, view, viewProjection, cameraPos ) = | ||||||
|  |             getCamera model | ||||||
|  | 
 | ||||||
|  |         modelM = | ||||||
|  |             M4.makeTranslate (vec3 -1 0 0) | ||||||
|  | 
 | ||||||
|  |         lightPos = | ||||||
|  |             vec3 (0.5 * cos (2 * model.time)) (1 + 0.5 * sin (2 * model.time)) 0.5 | ||||||
|  | 
 | ||||||
|  |         uniforms = | ||||||
|  |             { camera = camera | ||||||
|  |             , mvMat = M4.mul view modelM | ||||||
|  |             , modelViewProjectionMatrix = M4.mul viewProjection modelM | ||||||
|  |             , modelMatrix = modelM | ||||||
|  |             , viewPosition = cameraPos | ||||||
|  |             , textureDiff = textureDiff | ||||||
|  |             , textureNorm = textureNorm | ||||||
|  |             , lightPosition = lightPos | ||||||
|  |             } | ||||||
|  |     in | ||||||
|  |         case mesh of | ||||||
|  |             WithoutTexture { vertices, indices } -> | ||||||
|  |                 renderCullFace Shaders.simpleVert Shaders.simpleFrag (GL.indexedTriangles vertices indices) uniforms | ||||||
|  | 
 | ||||||
|  |             WithTexture { vertices, indices } -> | ||||||
|  |                 renderCullFace Shaders.noNormalVert Shaders.noNormalFrag (GL.indexedTriangles vertices indices) uniforms | ||||||
|  | 
 | ||||||
|  |             WithTextureAndTangent { vertices, indices } -> | ||||||
|  |                 renderCullFace Shaders.normalVert Shaders.normalFrag (GL.indexedTriangles vertices indices) uniforms | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | getCamera : Model -> ( Mat4, Mat4, Mat4, Vec3 ) | ||||||
|  | getCamera { mouseDelta, zoom, windowSize } = | ||||||
|  |     let | ||||||
|  |         ( mx, my ) = | ||||||
|  |             ( mouseDelta.x, mouseDelta.y ) | ||||||
|  | 
 | ||||||
|  |         aspect = | ||||||
|  |             toFloat windowSize.width / toFloat windowSize.height | ||||||
|  | 
 | ||||||
|  |         proj = | ||||||
|  |             M4.makePerspective 45 aspect 0.01 10000 | ||||||
|  | 
 | ||||||
|  |         position = | ||||||
|  |             vec3 (zoom * sin -mx * sin my) (-zoom * cos my + 1) (zoom * cos -mx * sin my) | ||||||
|  | 
 | ||||||
|  |         view = | ||||||
|  |             M4.makeLookAt (position) (vec3 0 1 0) (vec3 0 1 0) | ||||||
|  |     in | ||||||
|  |         ( proj, view, M4.mul proj view, position ) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | view : Model -> Html.Html Msg | ||||||
|  | view model = | ||||||
|  |     div [] | ||||||
|  |         [ selectModel model | ||||||
|  |         , case ( model.mesh, model.diffText, model.normText ) of | ||||||
|  |             ( Ok m, Ok td, Ok tn ) -> | ||||||
|  |                 GL.toHtmlWith [ GL.antialias, GL.depth 1 ] | ||||||
|  |                     [ onZoom | ||||||
|  |                     , Attr.width (model.windowSize.width) | ||||||
|  |                     , Attr.height (model.windowSize.height) | ||||||
|  |                     , Attr.style [ ( "position", "absolute" ) ] | ||||||
|  |                     ] | ||||||
|  |                     (Dict.values m | ||||||
|  |                         |> List.concatMap Dict.values | ||||||
|  |                         |> List.map (renderModel model td tn) | ||||||
|  |                     ) | ||||||
|  | 
 | ||||||
|  |             err -> | ||||||
|  |                 Html.div [] [ Html.text (toString err) ] | ||||||
|  |         ] | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | selectModel : Model -> Html Msg | ||||||
|  | selectModel model = | ||||||
|  |     div [ Attr.style [ ( "position", "absolute" ), ( "z-index", "2" ), ( "backgroundColor", "white" ) ] ] | ||||||
|  |         ([ Html.select [ onInput SelectMesh, Attr.value model.currentModel ] | ||||||
|  |             (List.map (\t -> Html.option [ Attr.value t ] [ text t ]) models) | ||||||
|  |          ] | ||||||
|  |             ++ if String.startsWith "meshes/elmLogo" model.currentModel then | ||||||
|  |                 [ text "\twith normal map: " | ||||||
|  |                 , Html.input [ Attr.type_ "checkbox", onCheck SetUseTangent, Attr.checked model.withTangent ] [] | ||||||
|  |                 ] | ||||||
|  |                else | ||||||
|  |                 [] | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | -- SUBS | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | subscriptions : Model -> Sub Msg | ||||||
|  | subscriptions model = | ||||||
|  |     Sub.batch | ||||||
|  |         ((if model.isDown then | ||||||
|  |             [ Mouse.moves MouseMove ] | ||||||
|  |           else | ||||||
|  |             [] | ||||||
|  |          ) | ||||||
|  |             ++ [ AnimationFrame.diffs Tick | ||||||
|  |                , Mouse.downs MouseDown | ||||||
|  |                , Mouse.ups (\_ -> MouseUp) | ||||||
|  |                , Window.resizes ResizeWindow | ||||||
|  |                ] | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | -- HELPERS | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | onZoom : Html.Attribute Msg | ||||||
|  | onZoom = | ||||||
|  |     on "wheel" (JD.map Zoom (JD.field "deltaY" JD.float)) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | getDelta : Mouse.Position -> Mouse.Position -> MouseDelta -> MouseDelta | ||||||
|  | getDelta curr lastP delta = | ||||||
|  |     MouseDelta (toFloat (curr.x - lastP.x) / 100 + delta.x) (clamp 0.01 pi (toFloat (curr.y - lastP.y) / 100 + delta.y)) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | loadTexture : String -> (Result String GL.Texture -> msg) -> Cmd msg | ||||||
|  | loadTexture url msg = | ||||||
|  |     WebGL.Texture.load url | ||||||
|  |         |> Task.attempt | ||||||
|  |             (\r -> | ||||||
|  |                 case r of | ||||||
|  |                     Ok t -> | ||||||
|  |                         msg (Ok t) | ||||||
|  | 
 | ||||||
|  |                     Err e -> | ||||||
|  |                         msg (Err ("Failed to load texture: " ++ toString e)) | ||||||
|  |             ) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | renderCullFace : GL.Shader a u v -> GL.Shader {} u v -> GL.Mesh a -> u -> GL.Entity | ||||||
|  | renderCullFace = | ||||||
|  |     GL.entityWith [ DepthTest.default, cullFace front ] | ||||||
							
								
								
									
										9
									
								
								elm-stuff/packages/Zinggi/elm-obj-loader/1.0.3/examples/README.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								elm-stuff/packages/Zinggi/elm-obj-loader/1.0.3/examples/README.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,9 @@ | |||||||
|  | # Running | ||||||
|  | Due to [a bug in elm reactor](https://github.com/elm-lang/elm-reactor/issues/217), the obj file will be served as an html page instead of `plain/text`. This screws up the parsing. | ||||||
|  | 
 | ||||||
|  | Using another file server works, e.g. | ||||||
|  | using [elm-live](https://github.com/tomekwi/elm-live) or `python -m http.server` | ||||||
|  | 
 | ||||||
|  | # Acknowledgements | ||||||
|  | 
 | ||||||
|  | Brick textures were taken from: http://www.textures.com/ | ||||||
							
								
								
									
										301
									
								
								elm-stuff/packages/Zinggi/elm-obj-loader/1.0.3/examples/Shaders.elm
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										301
									
								
								elm-stuff/packages/Zinggi/elm-obj-loader/1.0.3/examples/Shaders.elm
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,301 @@ | |||||||
|  | module Shaders exposing (..) | ||||||
|  | 
 | ||||||
|  | import WebGL | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | {-| This shader uses Spherical Environment Mapping (SEM). | ||||||
|  | Here are some relevant links: | ||||||
|  | 
 | ||||||
|  |   - [very cool demo](https://www.clicktorelease.com/code/spherical-normal-mapping/#) | ||||||
|  |   - <https://www.clicktorelease.com/blog/creating-spherical-environment-mapping-shader> | ||||||
|  |   - <http://www.ozone3d.net/tutorials/glsl_texturing_p04.php> | ||||||
|  | 
 | ||||||
|  | -} | ||||||
|  | reflectionVert = | ||||||
|  |     [glsl| | ||||||
|  | 
 | ||||||
|  | attribute vec3 position; | ||||||
|  | attribute vec3 normal; | ||||||
|  | uniform mat4 mvMat; | ||||||
|  | uniform mat4 camera; | ||||||
|  | varying vec3 vNormal; | ||||||
|  | 
 | ||||||
|  | void main() | ||||||
|  | { | ||||||
|  |     vec4 vertex4 = mvMat * vec4(position, 1.0); | ||||||
|  |     vNormal = vec3(mvMat * vec4(normal, 0.0)); | ||||||
|  |     vec3 nm_z = normalize(vec3(vertex4)); | ||||||
|  |     vec3 nm_x = cross(nm_z, vec3(0.0, 1.0, 0.0)); | ||||||
|  |     vec3 nm_y = cross(nm_x, nm_z); | ||||||
|  |     vNormal = vec3(dot(vNormal, nm_x), dot(vNormal, nm_y), dot(vNormal, nm_z)); | ||||||
|  |     gl_Position = camera * vertex4; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | |] | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | reflectionFrag = | ||||||
|  |     [glsl| | ||||||
|  | precision mediump float; | ||||||
|  | 
 | ||||||
|  | uniform sampler2D texture; | ||||||
|  | 
 | ||||||
|  | varying vec3 vNormal; | ||||||
|  | 
 | ||||||
|  | void main() | ||||||
|  | { | ||||||
|  |     vec2 texCoord = vec2(0.5 * vNormal.x + 0.5, - 0.5 * vNormal.y - 0.5); | ||||||
|  |     vec4 fragColor = texture2D(texture, texCoord); | ||||||
|  |     fragColor.a = 1.0; | ||||||
|  | 
 | ||||||
|  |     gl_FragColor = fragColor; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | |] | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | {-| normal mapping according to: | ||||||
|  | <http://www.gamasutra.com/blogs/RobertBasler/20131122/205462/Three_Normal_Mapping_Techniques_Explained_For_the_Mathematically_Uninclined.php?print=1> | ||||||
|  | -} | ||||||
|  | normalVert = | ||||||
|  |     [glsl| | ||||||
|  | attribute vec3 position; | ||||||
|  | attribute vec3 normal; | ||||||
|  | attribute vec2 texCoord; | ||||||
|  | attribute vec4 tangent; | ||||||
|  | 
 | ||||||
|  | varying vec2 vTexCoord; | ||||||
|  | varying vec3 vLightDirection; | ||||||
|  | varying vec3 vViewDirection; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | uniform mat4 modelViewProjectionMatrix; | ||||||
|  | uniform mat4 modelMatrix; | ||||||
|  | uniform vec3 lightPosition; | ||||||
|  | uniform vec3 viewPosition; | ||||||
|  | 
 | ||||||
|  | mat3 transpose(mat3 m) { | ||||||
|  |     return mat3(m[0][0], m[1][0], m[2][0], | ||||||
|  |                 m[0][1], m[1][1], m[2][1], | ||||||
|  |                 m[0][2], m[1][2], m[2][2]); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | void main() | ||||||
|  | { | ||||||
|  |     vec4 pos = vec4(position, 1.0 ); | ||||||
|  |     vec3 posWorld = (modelMatrix * pos).xyz; | ||||||
|  | 
 | ||||||
|  |     // Tangent, Bitangent, Normal space matrix TBN | ||||||
|  |     // this isn't entirely correct, it should use the normal matrix | ||||||
|  |     // In this special case it works out well, | ||||||
|  |     // since my model matrix does not contain any rotation or translation. | ||||||
|  |     // http://www.lighthouse3d.com/tutorials/glsl-12-tutorial/the-normal-matrix/ | ||||||
|  |     vec3 n = normalize((modelMatrix * vec4(normal, 0.0)).xyz); | ||||||
|  |     vec3 t = normalize((modelMatrix * vec4(tangent.xyz, 0.0)).xyz); | ||||||
|  |     vec3 b = normalize((modelMatrix * vec4((cross(normal, tangent.xyz) * tangent.w), 0.0)).xyz); | ||||||
|  |     mat3 tbn = transpose(mat3(t, b, n)); | ||||||
|  |     vLightDirection = tbn*(lightPosition - posWorld); | ||||||
|  |     vViewDirection = tbn*(viewPosition - posWorld); | ||||||
|  |     vTexCoord = texCoord; | ||||||
|  |     gl_Position = modelViewProjectionMatrix * pos; | ||||||
|  | } | ||||||
|  | |] | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | normalFrag = | ||||||
|  |     [glsl| | ||||||
|  | precision mediump float; | ||||||
|  | 
 | ||||||
|  | uniform sampler2D textureDiff; | ||||||
|  | uniform sampler2D textureNorm; | ||||||
|  | 
 | ||||||
|  | varying vec2 vTexCoord; | ||||||
|  | varying vec3 vLightDirection; | ||||||
|  | varying vec3 vViewDirection; | ||||||
|  | 
 | ||||||
|  | void main() { | ||||||
|  | 
 | ||||||
|  |     vec3 lightDir = normalize(vLightDirection); | ||||||
|  | 
 | ||||||
|  |     // Local normal, in tangent space | ||||||
|  |     vec3 pixelNormal = normalize(texture2D(textureNorm, vTexCoord).rgb*2.0 - 1.0); | ||||||
|  |     float lambert = max(dot(pixelNormal, lightDir), 0.0); | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |     // diffuse + lambert | ||||||
|  |     vec3 lightIntensities = vec3(1.5, 1.0, 1.0); | ||||||
|  |     vec3 diffuseColor = texture2D(textureDiff, vTexCoord).rgb; | ||||||
|  |     vec3 diffuse = lambert * diffuseColor * lightIntensities; | ||||||
|  | 
 | ||||||
|  |     // ambient | ||||||
|  |     vec3 ambient = 0.3 * diffuseColor; | ||||||
|  | 
 | ||||||
|  |     // specular | ||||||
|  |     float shininess = 32.0; | ||||||
|  |     vec3 viewDir = normalize(vViewDirection); | ||||||
|  |     vec3 reflectDir = reflect(-lightDir, pixelNormal); | ||||||
|  |     vec3 halfwayDir = normalize(lightDir + viewDir); | ||||||
|  |     float spec = pow(max(dot(pixelNormal, halfwayDir), 0.0), shininess); | ||||||
|  |     vec3 specular = vec3(0.2) * spec * lightIntensities; | ||||||
|  | 
 | ||||||
|  |     // attenuation | ||||||
|  |     float lightAttenuation = 0.3; | ||||||
|  |     float attenuation = 1.0 / (1.0 + lightAttenuation * pow(length(vLightDirection), 2.0)); | ||||||
|  | 
 | ||||||
|  |     vec3 final_color = ambient + (diffuse + specular) * attenuation; | ||||||
|  |     gl_FragColor = vec4(final_color, 1.0); | ||||||
|  | } | ||||||
|  | |] | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | {-| same as the normal mapping shader, but without deforming normals. | ||||||
|  | -} | ||||||
|  | noNormalVert = | ||||||
|  |     [glsl| | ||||||
|  | attribute vec3 position; | ||||||
|  | attribute vec3 normal; | ||||||
|  | attribute vec2 texCoord; | ||||||
|  | 
 | ||||||
|  | varying vec2 vTexCoord; | ||||||
|  | varying vec3 vLightDirection; | ||||||
|  | varying vec3 vViewDirection; | ||||||
|  | varying vec3 vNormal; | ||||||
|  | 
 | ||||||
|  | uniform mat4 modelViewProjectionMatrix; | ||||||
|  | uniform mat4 modelMatrix; | ||||||
|  | uniform vec3 lightPosition; | ||||||
|  | uniform vec3 viewPosition; | ||||||
|  | 
 | ||||||
|  | void main() | ||||||
|  | { | ||||||
|  |     vec4 pos = vec4(position, 1.0 ); | ||||||
|  |     vec3 posWorld = (modelMatrix * pos).xyz; | ||||||
|  | 
 | ||||||
|  |     vLightDirection = lightPosition - posWorld; | ||||||
|  |     vViewDirection = viewPosition - posWorld; | ||||||
|  |     vTexCoord = texCoord; | ||||||
|  |     // this is incorrect, it should use the normal matrix | ||||||
|  |     vNormal = mat3(modelMatrix) * normal; | ||||||
|  |     gl_Position = modelViewProjectionMatrix * pos; | ||||||
|  | } | ||||||
|  | |] | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | noNormalFrag = | ||||||
|  |     [glsl| | ||||||
|  | precision mediump float; | ||||||
|  | 
 | ||||||
|  | uniform sampler2D textureDiff; | ||||||
|  | 
 | ||||||
|  | varying vec2 vTexCoord; | ||||||
|  | varying vec3 vLightDirection; | ||||||
|  | varying vec3 vViewDirection; | ||||||
|  | varying vec3 vNormal; | ||||||
|  | 
 | ||||||
|  | void main() | ||||||
|  | { | ||||||
|  |     vec3 lightDir = normalize(vLightDirection); | ||||||
|  | 
 | ||||||
|  |     // lambert | ||||||
|  |     vec3 pixelNormal = normalize(vNormal); | ||||||
|  |     float lambert = max(dot(pixelNormal, lightDir), 0.0); | ||||||
|  | 
 | ||||||
|  |     // diffuse + lambert | ||||||
|  |     vec3 lightIntensities = vec3(1.5, 1.0, 1.0); | ||||||
|  |     vec3 diffuseColor = texture2D(textureDiff, vTexCoord).rgb; | ||||||
|  |     vec3 diffuse = lambert * diffuseColor * lightIntensities; | ||||||
|  | 
 | ||||||
|  |     // ambient | ||||||
|  |     vec3 ambient = 0.3 * diffuseColor; | ||||||
|  | 
 | ||||||
|  |     // specular | ||||||
|  |     float shininess = 32.0; | ||||||
|  |     vec3 viewDir = normalize(vViewDirection); | ||||||
|  |     vec3 reflectDir = reflect(-lightDir, pixelNormal); | ||||||
|  |     vec3 halfwayDir = normalize(lightDir + viewDir); | ||||||
|  |     float spec = pow(max(dot(pixelNormal, halfwayDir), 0.0), shininess); | ||||||
|  |     vec3 specular = vec3(0.2) * spec * lightIntensities; | ||||||
|  | 
 | ||||||
|  |     // attenuation | ||||||
|  |     float lightAttenuation = 0.3; | ||||||
|  |     float attenuation = 1.0 / (1.0 + lightAttenuation * pow(length(vLightDirection), 2.0)); | ||||||
|  | 
 | ||||||
|  |     vec3 final_color = ambient + (diffuse + specular) * attenuation; | ||||||
|  |     gl_FragColor = vec4(final_color, 1.0); | ||||||
|  | } | ||||||
|  | |] | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | {-| same as above, but without any textures. | ||||||
|  | -} | ||||||
|  | simpleVert = | ||||||
|  |     [glsl| | ||||||
|  | attribute vec3 position; | ||||||
|  | attribute vec3 normal; | ||||||
|  | 
 | ||||||
|  | varying vec3 vLightDirection; | ||||||
|  | varying vec3 vViewDirection; | ||||||
|  | varying vec3 vNormal; | ||||||
|  | 
 | ||||||
|  | uniform mat4 modelViewProjectionMatrix; | ||||||
|  | uniform mat4 modelMatrix; | ||||||
|  | uniform vec3 lightPosition; | ||||||
|  | uniform vec3 viewPosition; | ||||||
|  | 
 | ||||||
|  | void main() | ||||||
|  | { | ||||||
|  |     vec4 pos = vec4(position, 1.0 ); | ||||||
|  |     vec3 posWorld = (modelMatrix * pos).xyz; | ||||||
|  | 
 | ||||||
|  |     vLightDirection = lightPosition - posWorld; | ||||||
|  |     vViewDirection = viewPosition - posWorld; | ||||||
|  |     // this is incorrect, it should use the normal matrix, like this: | ||||||
|  |     // vNormal = mat3(normalMatrix) * normal; | ||||||
|  |     // it works in this case, since the modelMatrix is the identity matrix | ||||||
|  |     vNormal = normal; | ||||||
|  |     gl_Position = modelViewProjectionMatrix * pos; | ||||||
|  | } | ||||||
|  | |] | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | simpleFrag = | ||||||
|  |     [glsl| | ||||||
|  | precision mediump float; | ||||||
|  | 
 | ||||||
|  | varying vec3 vLightDirection; | ||||||
|  | varying vec3 vViewDirection; | ||||||
|  | varying vec3 vNormal; | ||||||
|  | 
 | ||||||
|  | void main() | ||||||
|  | { | ||||||
|  |     vec3 lightDir = normalize(vLightDirection); | ||||||
|  | 
 | ||||||
|  |     // lambert | ||||||
|  |     vec3 pixelNormal = normalize(vNormal); | ||||||
|  |     float lambert = max(dot(pixelNormal, lightDir), 0.0); | ||||||
|  | 
 | ||||||
|  |     // diffuse + lambert | ||||||
|  |     vec3 lightIntensities = vec3(1.5, 1.0, 1.0); | ||||||
|  |     vec3 diffuseColor = vec3(0.3, 0.2, 0.95); | ||||||
|  |     vec3 diffuse = lambert * diffuseColor * lightIntensities; | ||||||
|  | 
 | ||||||
|  |     // ambient | ||||||
|  |     vec3 ambient = 0.2 * diffuseColor; | ||||||
|  | 
 | ||||||
|  |     // specular | ||||||
|  |     float shininess = 32.0; | ||||||
|  |     vec3 viewDir = normalize(vViewDirection); | ||||||
|  |     vec3 reflectDir = reflect(-lightDir, pixelNormal); | ||||||
|  |     vec3 halfwayDir = normalize(lightDir + viewDir); | ||||||
|  |     float spec = pow(max(dot(pixelNormal, halfwayDir), 0.0), shininess); | ||||||
|  |     vec3 specular = vec3(0.2) * spec * lightIntensities; | ||||||
|  | 
 | ||||||
|  |     // attenuation | ||||||
|  |     float lightAttenuation = 0.3; | ||||||
|  |     float attenuation = 1.0 / (1.0 + lightAttenuation * pow(length(vLightDirection), 2.0)); | ||||||
|  | 
 | ||||||
|  |     vec3 final_color = ambient + (diffuse + specular) * attenuation; | ||||||
|  |     gl_FragColor = vec4(final_color, 1.0); | ||||||
|  | } | ||||||
|  | |] | ||||||
							
								
								
									
										148
									
								
								elm-stuff/packages/Zinggi/elm-obj-loader/1.0.3/examples/Suzanne.elm
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										148
									
								
								elm-stuff/packages/Zinggi/elm-obj-loader/1.0.3/examples/Suzanne.elm
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,148 @@ | |||||||
|  | module Suzanne exposing (..) | ||||||
|  | 
 | ||||||
|  | import AnimationFrame | ||||||
|  | import Html | ||||||
|  | import Html.Attributes as Attr | ||||||
|  | import Html.Events exposing (on) | ||||||
|  | import Json.Decode as JD | ||||||
|  | import Math.Matrix4 as M4 exposing (Mat4) | ||||||
|  | import Math.Vector3 as V3 exposing (Vec3, vec3) | ||||||
|  | import Task | ||||||
|  | import WebGL as GL | ||||||
|  | import WebGL.Texture | ||||||
|  | import WebGL.Settings exposing (cullFace, front) | ||||||
|  | import WebGL.Settings.DepthTest as DepthTest | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | -- | ||||||
|  | 
 | ||||||
|  | import OBJ | ||||||
|  | import OBJ.Types exposing (MeshWith, VertexWithTexture) | ||||||
|  | import Shaders exposing (reflectionVert, reflectionFrag) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | main : Program Never Model Msg | ||||||
|  | main = | ||||||
|  |     Html.program | ||||||
|  |         { init = ( initModel, initCmd ) | ||||||
|  |         , view = view | ||||||
|  |         , subscriptions = (\model -> AnimationFrame.diffs Tick) | ||||||
|  |         , update = update | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | -- MODEL | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | type alias Model = | ||||||
|  |     { time : Float | ||||||
|  |     , mesh : Result String (MeshWith VertexWithTexture) | ||||||
|  |     , zoom : Float | ||||||
|  |     , reflectionTexture : Result String GL.Texture | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | initModel : Model | ||||||
|  | initModel = | ||||||
|  |     { mesh = Err "loading ...", time = 0, zoom = 10, reflectionTexture = Err "Loading texture..." } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | initCmd : Cmd Msg | ||||||
|  | initCmd = | ||||||
|  |     Cmd.batch | ||||||
|  |         [ OBJ.loadMesh "meshes/suzanne.obj" LoadObj | ||||||
|  |         , loadTexture "textures/chavant.jpg" TextureLoaded | ||||||
|  |         ] | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | -- UPDATE | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | type Msg | ||||||
|  |     = Tick Float | ||||||
|  |     | LoadObj (Result String (MeshWith VertexWithTexture)) | ||||||
|  |     | Zoom Float | ||||||
|  |     | TextureLoaded (Result String GL.Texture) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | update : Msg -> Model -> ( Model, Cmd Msg ) | ||||||
|  | update msg model = | ||||||
|  |     case msg of | ||||||
|  |         Tick dt -> | ||||||
|  |             ( { model | time = model.time + dt / 1000 }, Cmd.none ) | ||||||
|  | 
 | ||||||
|  |         Zoom dy -> | ||||||
|  |             ( { model | zoom = model.zoom + dy / 100 }, Cmd.none ) | ||||||
|  | 
 | ||||||
|  |         LoadObj mesh -> | ||||||
|  |             ( { model | mesh = mesh }, Cmd.none ) | ||||||
|  | 
 | ||||||
|  |         TextureLoaded t -> | ||||||
|  |             ( { model | reflectionTexture = t }, Cmd.none ) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | -- VIEW / RENDER | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | renderModel : Model -> GL.Texture -> MeshWith VertexWithTexture -> GL.Entity | ||||||
|  | renderModel { zoom, time } texture { vertices, indices } = | ||||||
|  |     let | ||||||
|  |         ( camera, view ) = | ||||||
|  |             getCamera zoom time | ||||||
|  | 
 | ||||||
|  |         model = | ||||||
|  |             M4.makeRotate time (vec3 0 1 0) | ||||||
|  | 
 | ||||||
|  |         modelView = | ||||||
|  |             M4.mul view model | ||||||
|  |     in | ||||||
|  |         GL.entityWith [ DepthTest.default, cullFace front ] | ||||||
|  |             reflectionVert | ||||||
|  |             reflectionFrag | ||||||
|  |             (GL.indexedTriangles vertices indices) | ||||||
|  |             { camera = camera, mvMat = modelView, texture = texture } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | getCamera : Float -> Float -> ( Mat4, Mat4 ) | ||||||
|  | getCamera zoom t = | ||||||
|  |     ( (M4.makePerspective 45 1 0.01 10000) | ||||||
|  |     , (M4.makeLookAt (vec3 (zoom) (zoom / 2) (zoom)) (vec3 0 0 0) (vec3 0 1 0)) | ||||||
|  |     ) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | view : Model -> Html.Html Msg | ||||||
|  | view model = | ||||||
|  |     case ( model.mesh, model.reflectionTexture ) of | ||||||
|  |         ( Ok m, Ok t ) -> | ||||||
|  |             GL.toHtmlWith [ GL.antialias, GL.depth 1 ] | ||||||
|  |                 [ onZoom, Attr.width 400, Attr.height 400 ] | ||||||
|  |                 [ renderModel model t m ] | ||||||
|  | 
 | ||||||
|  |         ( a, b ) -> | ||||||
|  |             Html.div [] [ Html.text (toString a ++ "\n\n\n" ++ toString b) ] | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | -- HELPERS | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | loadTexture : String -> (Result String GL.Texture -> msg) -> Cmd msg | ||||||
|  | loadTexture url msg = | ||||||
|  |     WebGL.Texture.load url | ||||||
|  |         |> Task.attempt | ||||||
|  |             (\r -> | ||||||
|  |                 case r of | ||||||
|  |                     Ok t -> | ||||||
|  |                         msg (Ok t) | ||||||
|  | 
 | ||||||
|  |                     Err e -> | ||||||
|  |                         msg (Err ("Failed to load texture: " ++ toString e)) | ||||||
|  |             ) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | onZoom : Html.Attribute Msg | ||||||
|  | onZoom = | ||||||
|  |     on "wheel" (JD.map Zoom (JD.field "deltaY" JD.float)) | ||||||
							
								
								
									
										24
									
								
								elm-stuff/packages/Zinggi/elm-obj-loader/1.0.3/examples/elm-package.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								elm-stuff/packages/Zinggi/elm-obj-loader/1.0.3/examples/elm-package.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,24 @@ | |||||||
|  | { | ||||||
|  |     "version": "1.0.0", | ||||||
|  |     "summary": "helpful summary of your project, less than 80 characters", | ||||||
|  |     "repository": "https://github.com/Zinggi/elm-obj-loader.git", | ||||||
|  |     "license": "BSD3", | ||||||
|  |     "source-directories": [ | ||||||
|  |         ".", | ||||||
|  |         "../src" | ||||||
|  |     ], | ||||||
|  |     "exposed-modules": [], | ||||||
|  |     "dependencies": { | ||||||
|  |         "Bogdanp/elm-combine": "3.1.1 <= v < 4.0.0", | ||||||
|  |         "Skinney/elm-array-exploration": "2.0.1 <= v < 3.0.0", | ||||||
|  |         "elm-community/linear-algebra": "1.0.0 <= v < 2.0.0", | ||||||
|  |         "elm-community/webgl": "2.0.0 <= v < 3.0.0", | ||||||
|  |         "elm-lang/animation-frame": "1.0.1 <= v < 2.0.0", | ||||||
|  |         "elm-lang/core": "5.0.0 <= v < 6.0.0", | ||||||
|  |         "elm-lang/html": "2.0.0 <= v < 3.0.0", | ||||||
|  |         "elm-lang/http": "1.0.0 <= v < 2.0.0", | ||||||
|  |         "elm-lang/mouse": "1.0.1 <= v < 2.0.0", | ||||||
|  |         "elm-lang/window": "1.0.1 <= v < 2.0.0" | ||||||
|  |     }, | ||||||
|  |     "elm-version": "0.18.0 <= v < 0.19.0" | ||||||
|  | } | ||||||
							
								
								
									
										1576
									
								
								elm-stuff/packages/Zinggi/elm-obj-loader/1.0.3/examples/meshes/elmLogo.obj
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1576
									
								
								elm-stuff/packages/Zinggi/elm-obj-loader/1.0.3/examples/meshes/elmLogo.obj
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										2580
									
								
								elm-stuff/packages/Zinggi/elm-obj-loader/1.0.3/examples/meshes/suzanne.obj
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										2580
									
								
								elm-stuff/packages/Zinggi/elm-obj-loader/1.0.3/examples/meshes/suzanne.obj
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										1518
									
								
								elm-stuff/packages/Zinggi/elm-obj-loader/1.0.3/examples/meshes/suzanneNoUV.obj
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1518
									
								
								elm-stuff/packages/Zinggi/elm-obj-loader/1.0.3/examples/meshes/suzanneNoUV.obj
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								elm-stuff/packages/Zinggi/elm-obj-loader/1.0.3/examples/textures/chavant.jpg
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								elm-stuff/packages/Zinggi/elm-obj-loader/1.0.3/examples/textures/chavant.jpg
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 19 KiB | 
							
								
								
									
										
											BIN
										
									
								
								elm-stuff/packages/Zinggi/elm-obj-loader/1.0.3/examples/textures/elmLogoDiffuse.png
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								elm-stuff/packages/Zinggi/elm-obj-loader/1.0.3/examples/textures/elmLogoDiffuse.png
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 191 KiB | 
							
								
								
									
										
											BIN
										
									
								
								elm-stuff/packages/Zinggi/elm-obj-loader/1.0.3/examples/textures/elmLogoNorm.png
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								elm-stuff/packages/Zinggi/elm-obj-loader/1.0.3/examples/textures/elmLogoNorm.png
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 408 KiB | 
							
								
								
									
										169
									
								
								elm-stuff/packages/Zinggi/elm-obj-loader/1.0.3/src/OBJ.elm
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										169
									
								
								elm-stuff/packages/Zinggi/elm-obj-loader/1.0.3/src/OBJ.elm
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,169 @@ | |||||||
|  | module OBJ exposing (..) | ||||||
|  | 
 | ||||||
|  | {-| | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | # .obj file loader | ||||||
|  | 
 | ||||||
|  | The returned models can be rendered using `indexedTriangles` from `WebGL`. | ||||||
|  | 
 | ||||||
|  |     WebGL.indexedTriangles mesh.vertices mesh.indices | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | ## From URL | ||||||
|  | 
 | ||||||
|  | All these methods take an URL as the first parameter. | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | ### Single model | ||||||
|  | 
 | ||||||
|  | Use the methods from here if you know whats in your file | ||||||
|  | and if they only contain a single object with a single material. | ||||||
|  | These are just provided for convenience. | ||||||
|  | 
 | ||||||
|  | @docs loadMeshWithoutTexture, loadMesh, loadMeshWithTangent | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | ### General | ||||||
|  | 
 | ||||||
|  | Use these methods if you don't know what kind of files you'll get or | ||||||
|  | if your files contain multiple groups or materials. | ||||||
|  | 
 | ||||||
|  | @docs loadObjFile, loadObjFileWith, Settings, defaultSettings | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | ## From String | ||||||
|  | 
 | ||||||
|  | @docs parseObjStringWith | ||||||
|  | 
 | ||||||
|  | -} | ||||||
|  | 
 | ||||||
|  | import Dict exposing (Dict) | ||||||
|  | import Http | ||||||
|  | import OBJ.Assembler exposing (compile) | ||||||
|  | import OBJ.Parser exposing (parse) | ||||||
|  | import OBJ.Types exposing (Mesh, ObjFile) | ||||||
|  | import Task | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | -- | ||||||
|  | 
 | ||||||
|  | import OBJ.Assembler exposing (compile) | ||||||
|  | import OBJ.Parser exposing (parse) | ||||||
|  | import OBJ.Types exposing (..) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | {-| Load a model that doesn't have texture coordinates. | ||||||
|  | -} | ||||||
|  | loadMeshWithoutTexture : String -> (Result String (MeshWith Vertex) -> msg) -> Cmd msg | ||||||
|  | loadMeshWithoutTexture url msg = | ||||||
|  |     loadObjFile url | ||||||
|  |         (\res -> | ||||||
|  |             case res of | ||||||
|  |                 Ok f -> | ||||||
|  |                     case (Dict.values f |> List.map Dict.values) of | ||||||
|  |                         [ [ WithoutTexture m ] ] -> | ||||||
|  |                             msg (Ok m) | ||||||
|  | 
 | ||||||
|  |                         _ -> | ||||||
|  |                             msg (Err "file loaded correctly, but there were more than one models.") | ||||||
|  | 
 | ||||||
|  |                 Err e -> | ||||||
|  |                     msg (Err e) | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | {-| Load a model with texture coordinates. | ||||||
|  | -} | ||||||
|  | loadMesh : String -> (Result String (MeshWith VertexWithTexture) -> msg) -> Cmd msg | ||||||
|  | loadMesh url msg = | ||||||
|  |     loadObjFile url | ||||||
|  |         (\res -> | ||||||
|  |             case res of | ||||||
|  |                 Ok f -> | ||||||
|  |                     case (Dict.values f |> List.map Dict.values) of | ||||||
|  |                         [ [ WithTexture m ] ] -> | ||||||
|  |                             msg (Ok m) | ||||||
|  | 
 | ||||||
|  |                         _ -> | ||||||
|  |                             msg (Err "file loaded correctly, but there were more than one models.") | ||||||
|  | 
 | ||||||
|  |                 Err e -> | ||||||
|  |                     msg (Err e) | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | {-| Load a model with texture coordinate and calculate vertex tangents. | ||||||
|  | This is needed if you want to do tangent space normal mapping. | ||||||
|  | -} | ||||||
|  | loadMeshWithTangent : String -> (Result String (MeshWith VertexWithTextureAndTangent) -> msg) -> Cmd msg | ||||||
|  | loadMeshWithTangent url msg = | ||||||
|  |     loadObjFileWith { withTangents = True } | ||||||
|  |         url | ||||||
|  |         (\res -> | ||||||
|  |             case res of | ||||||
|  |                 Ok f -> | ||||||
|  |                     case (Dict.values f |> List.map Dict.values) of | ||||||
|  |                         [ [ WithTextureAndTangent m ] ] -> | ||||||
|  |                             msg (Ok m) | ||||||
|  | 
 | ||||||
|  |                         _ -> | ||||||
|  |                             msg (Err "file loaded correctly, but there were more than one models.") | ||||||
|  | 
 | ||||||
|  |                 Err e -> | ||||||
|  |                     msg (Err e) | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | {-| Load a .obj file from an URL | ||||||
|  | 
 | ||||||
|  |     loadObjFile url ObjFileLoaded | ||||||
|  | 
 | ||||||
|  | -} | ||||||
|  | loadObjFile : String -> (Result String ObjFile -> msg) -> Cmd msg | ||||||
|  | loadObjFile = | ||||||
|  |     loadObjFileWith defaultSettings | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | {-| withTangents : If true, vertex tangents will be calculated for meshes with texture coordinates. | ||||||
|  | This is needed if you want to do tangent space normal mapping. | ||||||
|  | -} | ||||||
|  | type alias Settings = | ||||||
|  |     { withTangents : Bool } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | {-| -} | ||||||
|  | defaultSettings : Settings | ||||||
|  | defaultSettings = | ||||||
|  |     { withTangents = False } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | {-| -} | ||||||
|  | loadObjFileWith : Settings -> String -> (Result String ObjFile -> msg) -> Cmd msg | ||||||
|  | loadObjFileWith settings url msg = | ||||||
|  |     Http.toTask (Http.getString url) | ||||||
|  |         |> Task.andThen | ||||||
|  |             (\s -> | ||||||
|  |                 parseObjStringWith settings s |> Task.succeed | ||||||
|  |             ) | ||||||
|  |         |> Task.onError (\e -> Task.succeed (Err ("failed to load:\n" ++ toString e))) | ||||||
|  |         |> Task.attempt | ||||||
|  |             (\r -> | ||||||
|  |                 case r of | ||||||
|  |                     Ok (Ok m) -> | ||||||
|  |                         msg (Ok m) | ||||||
|  | 
 | ||||||
|  |                     Ok (Err e) -> | ||||||
|  |                         msg (Err e) | ||||||
|  | 
 | ||||||
|  |                     Err e -> | ||||||
|  |                         msg (Err e) | ||||||
|  |             ) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | {-| Same as `loadObjFile`, but works on a string. | ||||||
|  | -} | ||||||
|  | parseObjStringWith : Settings -> String -> Result String ObjFile | ||||||
|  | parseObjStringWith config input = | ||||||
|  |     parse input | ||||||
|  |         |> Result.map (compile config) | ||||||
							
								
								
									
										463
									
								
								elm-stuff/packages/Zinggi/elm-obj-loader/1.0.3/src/OBJ/Assembler.elm
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										463
									
								
								elm-stuff/packages/Zinggi/elm-obj-loader/1.0.3/src/OBJ/Assembler.elm
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,463 @@ | |||||||
|  | module OBJ.Assembler exposing (..) | ||||||
|  | 
 | ||||||
|  | import Array.Hamt as Array exposing (Array) | ||||||
|  | import Dict exposing (Dict) | ||||||
|  | import Math.Vector2 as V2 exposing (Vec2) | ||||||
|  | import Math.Vector3 as V3 exposing (Vec3, vec3) | ||||||
|  | import Math.Vector4 as V4 exposing (Vec4, vec4) | ||||||
|  | import OBJ.Types exposing (..) | ||||||
|  | import OBJ.InternalTypes exposing (..) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | compile config lines = | ||||||
|  |     compileHelper (emptyCompileState config) lines | ||||||
|  |         |> addCurrentMesh | ||||||
|  |         |> addCurrentGroup | ||||||
|  |         |> .groups | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | emptyCompileState config = | ||||||
|  |     { -- this is a Dict (GroupName/String) Group | ||||||
|  |       -- it's the final output of this algorithm | ||||||
|  |       --  Group = Dict (MtlName/String) Mesh | ||||||
|  |       groups = Dict.empty | ||||||
|  |     , currentGroupName = "__default__" | ||||||
|  |     , currentMaterialName = "__default__" | ||||||
|  |     , currentMesh = Nothing | ||||||
|  |     , currentGroup = Dict.empty | ||||||
|  |     , vs = Array.empty | ||||||
|  |     , vts = Array.empty | ||||||
|  |     , vns = Array.empty | ||||||
|  |     , currentIndex = 0 | ||||||
|  |     , knownVertexTextures = Dict.empty | ||||||
|  |     , knownVertexTexturesTangents = Dict.empty | ||||||
|  |     , knownVertex = Dict.empty | ||||||
|  |     , config = config | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | compileHelper state lines = | ||||||
|  |     case lines of | ||||||
|  |         [] -> | ||||||
|  |             state | ||||||
|  | 
 | ||||||
|  |         l :: ls -> | ||||||
|  |             compileHelper (insertLine l state) ls | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | {-| | ||||||
|  | this 'inserts' a line into the state. | ||||||
|  | This means it manipulates the current state to reflect state changing commands | ||||||
|  | and buils meshes on the fly. | ||||||
|  | -} | ||||||
|  | insertLine line state = | ||||||
|  |     case line of | ||||||
|  |         Object s -> | ||||||
|  |             -- even though the specs doesn't give it any meaningful meaning, | ||||||
|  |             -- I treat is exactely like a group statement. | ||||||
|  |             -- This is because blender uses o instead of g per default. | ||||||
|  |             addCurrentGroup state | ||||||
|  |                 |> (\st -> { st | currentGroupName = s }) | ||||||
|  | 
 | ||||||
|  |         MtlLib s -> | ||||||
|  |             -- MtlLib statements are ignored, | ||||||
|  |             -- as I don't plan to support loading .mtl files | ||||||
|  |             state | ||||||
|  | 
 | ||||||
|  |         Group s -> | ||||||
|  |             addCurrentGroup state | ||||||
|  |                 |> (\st -> { st | currentGroupName = s }) | ||||||
|  | 
 | ||||||
|  |         Smooth s -> | ||||||
|  |             -- smooth groups are ignored. | ||||||
|  |             -- I tried to calculate these, but failed, | ||||||
|  |             -- since doing them correctly is more tricky than you might think: | ||||||
|  |             -- http://www.bytehazard.com/articles/vertnorm.html | ||||||
|  |             -- { state | activeSmoothGroup = s } | ||||||
|  |             state | ||||||
|  | 
 | ||||||
|  |         UseMtl s -> | ||||||
|  |             addCurrentMesh state | ||||||
|  |                 |> (\st -> { st | currentMaterialName = s }) | ||||||
|  | 
 | ||||||
|  |         V v -> | ||||||
|  |             { state | vs = Array.push v state.vs } | ||||||
|  | 
 | ||||||
|  |         Vt v -> | ||||||
|  |             { state | vts = Array.push v state.vts } | ||||||
|  | 
 | ||||||
|  |         Vn v -> | ||||||
|  |             { state | vns = Array.push v state.vns } | ||||||
|  | 
 | ||||||
|  |         F f -> | ||||||
|  |             triangulateFace f | ||||||
|  |                 |> List.foldr addFace state | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | triangulateFace f = | ||||||
|  |     case f of | ||||||
|  |         FVertexTextureNormal a -> | ||||||
|  |             triangulate a |> List.map FTVertexTextureNormal | ||||||
|  | 
 | ||||||
|  |         FVertexNormal a -> | ||||||
|  |             triangulate a |> List.map FTVertexNormal | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | addCurrentMesh state = | ||||||
|  |     -- this adds the current mesh, to the current group. | ||||||
|  |     -- We also normalize all values here that need normalizing | ||||||
|  |     case state.currentMesh of | ||||||
|  |         Just m -> | ||||||
|  |             { state | ||||||
|  |                 | currentGroup = Dict.insert state.currentMaterialName (finalizeMesh m) state.currentGroup | ||||||
|  |                 , currentMesh = Nothing | ||||||
|  |                 , knownVertexTextures = Dict.empty | ||||||
|  |                 , knownVertexTexturesTangents = Dict.empty | ||||||
|  |                 , knownVertex = Dict.empty | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |         _ -> | ||||||
|  |             state | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | finalizeMesh mesh = | ||||||
|  |     case mesh of | ||||||
|  |         WithTextureT m -> | ||||||
|  |             WithTexture m | ||||||
|  | 
 | ||||||
|  |         WithoutTextureT m -> | ||||||
|  |             WithoutTexture m | ||||||
|  | 
 | ||||||
|  |         WithTextureAndTangentT m -> | ||||||
|  |             WithTextureAndTangent | ||||||
|  |                 { m | ||||||
|  |                     | vertices = | ||||||
|  |                         Array.foldr | ||||||
|  |                             (\({ position, texCoord, normal, sdir, tdir } as v) acc -> | ||||||
|  |                                 let | ||||||
|  |                                     -- handedness: | ||||||
|  |                                     -- https://web.archive.org/web/20160409104130/http://www.terathon.com/code/tangent.html | ||||||
|  |                                     w = | ||||||
|  |                                         if V3.dot (V3.cross normal sdir) tdir < 0 then | ||||||
|  |                                             -1 | ||||||
|  |                                         else | ||||||
|  |                                             1 | ||||||
|  | 
 | ||||||
|  |                                     ( x, y, z ) = | ||||||
|  |                                         -- I have not seen this anywhere, but I added it because I sometimes got (0,0,0) | ||||||
|  |                                         if V3.lengthSquared sdir /= 0 then | ||||||
|  |                                             V3.toTuple <| V3.normalize (V3.sub sdir (V3.scale (V3.dot normal sdir) normal)) | ||||||
|  |                                         else | ||||||
|  |                                             V3.toTuple <| V3.cross (V3.normalize (V3.sub tdir (V3.scale (V3.dot normal tdir) normal))) normal | ||||||
|  |                                 in | ||||||
|  |                                     { position = position | ||||||
|  |                                     , texCoord = texCoord | ||||||
|  |                                     , normal = normal | ||||||
|  |                                     , tangent = vec4 x y z w | ||||||
|  |                                     } | ||||||
|  |                                         :: acc | ||||||
|  |                             ) | ||||||
|  |                             [] | ||||||
|  |                             m.vertices | ||||||
|  |                 } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | addCurrentGroup state = | ||||||
|  |     if Dict.isEmpty state.currentGroup then | ||||||
|  |         state | ||||||
|  |     else | ||||||
|  |         { state | ||||||
|  |             | groups = Dict.insert state.currentGroupName state.currentGroup state.groups | ||||||
|  |             , currentGroup = Dict.empty | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | addFace f state = | ||||||
|  |     -- this function adds a single face to the currentMesh | ||||||
|  |     -- for this it needs a dictionary containing the already known vertices, | ||||||
|  |     -- indexed using the v/vn etc. | ||||||
|  |     case state.currentMesh of | ||||||
|  |         Nothing -> | ||||||
|  |             -- we dont have a mesh yet, create one based on the type of the face | ||||||
|  |             addFaceToMesh f (createMesh state.config.withTangents f) { state | currentIndex = 0 } | ||||||
|  | 
 | ||||||
|  |         Just m -> | ||||||
|  |             addFaceToMesh f m state | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | addFaceToMesh f mesh ({ vs, vts, vns, currentIndex } as state) = | ||||||
|  |     -- add a face to the mesh | ||||||
|  |     case ( f, mesh ) of | ||||||
|  |         ( FTVertexTextureNormal ( v1, v2, v3 ), WithTextureT m ) -> | ||||||
|  |             let | ||||||
|  |                 ( newState, newVs, newIs ) = | ||||||
|  |                     applyForFace getOrInsertVTN ( v1, v2, v3 ) state | ||||||
|  | 
 | ||||||
|  |                 newMesh = | ||||||
|  |                     WithTextureT { m | indices = newIs :: m.indices, vertices = m.vertices ++ newVs } | ||||||
|  |             in | ||||||
|  |                 { newState | currentMesh = Just newMesh } | ||||||
|  | 
 | ||||||
|  |         ( FTVertexTextureNormal ( v1, v2, v3 ), WithTextureAndTangentT m ) -> | ||||||
|  |             let | ||||||
|  |                 tangents = | ||||||
|  |                     getFaceTangent ( v1, v2, v3 ) state | ||||||
|  | 
 | ||||||
|  |                 ( newState, newVs, newIs ) = | ||||||
|  |                     applyForFaceA (getOrInsertVTNT tangents) ( v1, v2, v3 ) state | ||||||
|  | 
 | ||||||
|  |                 newMesh = | ||||||
|  |                     WithTextureAndTangentT { m | indices = newIs :: m.indices, vertices = Array.append m.vertices newVs } | ||||||
|  |             in | ||||||
|  |                 { newState | currentMesh = Just newMesh } | ||||||
|  | 
 | ||||||
|  |         ( FTVertexNormal ( v1, v2, v3 ), WithoutTextureT m ) -> | ||||||
|  |             let | ||||||
|  |                 ( newState, newVs, newIs ) = | ||||||
|  |                     applyForFace getOrInsertVN ( v1, v2, v3 ) state | ||||||
|  | 
 | ||||||
|  |                 newMesh = | ||||||
|  |                     WithoutTextureT { m | indices = newIs :: m.indices, vertices = m.vertices ++ newVs } | ||||||
|  |             in | ||||||
|  |                 { newState | currentMesh = Just newMesh } | ||||||
|  | 
 | ||||||
|  |         _ -> | ||||||
|  |             -- TODO: lift this error into a Result type | ||||||
|  |             Debug.crash "mixed face types in the model!" | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | applyForFace f ( i1, i2, i3 ) s_0 = | ||||||
|  |     let | ||||||
|  |         ( s_1, vs_1, i_1 ) = | ||||||
|  |             f i1 s_0 | ||||||
|  | 
 | ||||||
|  |         ( s_2, vs_2, i_2 ) = | ||||||
|  |             f i2 s_1 | ||||||
|  | 
 | ||||||
|  |         ( s_3, vs_3, i_3 ) = | ||||||
|  |             f i3 s_2 | ||||||
|  |     in | ||||||
|  |         ( s_3, vs_1 ++ vs_2 ++ vs_3, ( i_3, i_2, i_1 ) ) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | applyForFaceA f ( i1, i2, i3 ) s_0 = | ||||||
|  |     let | ||||||
|  |         ( s_1, vs_1, i_1 ) = | ||||||
|  |             f i1 s_0 | ||||||
|  | 
 | ||||||
|  |         ( s_2, vs_2, i_2 ) = | ||||||
|  |             f i2 s_1 | ||||||
|  | 
 | ||||||
|  |         ( s_3, vs_3, i_3 ) = | ||||||
|  |             f i3 s_2 | ||||||
|  |     in | ||||||
|  |         ( s_3, Array.append (Array.append vs_1 vs_2) vs_3, ( i_3, i_2, i_1 ) ) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | getFaceTangent (( ( pi1, ti1, ni1 ), ( pi2, ti2, ni2 ), ( pi3, ti3, ni3 ) ) as index) { vs, vts, vns } = | ||||||
|  |     -- This is from here: | ||||||
|  |     -- https://web.archive.org/web/20160409104130/http://www.terathon.com/code/tangent.html | ||||||
|  |     -- But since the reference doesn't mention what to do in case the denominator is 0, | ||||||
|  |     -- This is probably not correct. | ||||||
|  |     case ( get3 ( pi1, pi2, pi3 ) vs vs vs, get3 ( ti1, ti2, ti3 ) vts vts vts ) of | ||||||
|  |         ( Just ( v1, v2, v3 ), Just ( w1, w2, w3 ) ) -> | ||||||
|  |             let | ||||||
|  |                 ( ( v1x, v1y, v1z ), ( v2x, v2y, v2z ), ( v3x, v3y, v3z ) ) = | ||||||
|  |                     t3map V3.toTuple ( v1, v2, v3 ) | ||||||
|  | 
 | ||||||
|  |                 ( ( w1x, w1y ), ( w2x, w2y ), ( w3x, w3y ) ) = | ||||||
|  |                     t3map V2.toTuple ( w1, w2, w3 ) | ||||||
|  | 
 | ||||||
|  |                 ( ( x1, x2 ), ( y1, y2 ), ( z1, z2 ) ) = | ||||||
|  |                     ( ( v2x - v1x, v3x - v1x ) | ||||||
|  |                     , ( v2y - v1y, v3y - v1y ) | ||||||
|  |                     , ( v2z - v1z, v3z - v1z ) | ||||||
|  |                     ) | ||||||
|  | 
 | ||||||
|  |                 ( ( s1, s2 ), ( t1, t2 ) ) = | ||||||
|  |                     ( ( w2x - w1x, w3x - w1x ), ( w2y - w1y, w3y - w1y ) ) | ||||||
|  | 
 | ||||||
|  |                 denom = | ||||||
|  |                     s1 * t2 - s2 * t1 | ||||||
|  | 
 | ||||||
|  |                 r = | ||||||
|  |                     if abs denom <= 0.000001 then | ||||||
|  |                         0.1 | ||||||
|  |                     else | ||||||
|  |                         1 / denom | ||||||
|  | 
 | ||||||
|  |                 sdir = | ||||||
|  |                     vec3 ((t2 * x1 - t1 * x2) * r) ((t2 * y1 - t1 * y2) * r) ((t2 * z1 - t1 * z2) * r) | ||||||
|  | 
 | ||||||
|  |                 tdir = | ||||||
|  |                     vec3 ((s1 * x2 - s2 * x1) * r) ((s1 * y2 - s2 * y1) * r) ((s1 * z2 - s2 * z1) * r) | ||||||
|  |             in | ||||||
|  |                 ( sdir, tdir ) | ||||||
|  | 
 | ||||||
|  |         _ -> | ||||||
|  |             -- TODO: lift this error into a Result type | ||||||
|  |             ( vec3 1 1 1, vec3 1 1 1 ) | ||||||
|  |                 |> log ("index " ++ toString index ++ " out of bounds!\nThis should never happen with a well formed file") | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | getOrInsertVTN index ({ vs, vts, vns, knownVertexTextures, currentIndex } as state) = | ||||||
|  |     case Dict.get index knownVertexTextures of | ||||||
|  |         Just i -> | ||||||
|  |             ( state, [], i ) | ||||||
|  | 
 | ||||||
|  |         Nothing -> | ||||||
|  |             case get3 index vs vts vns of | ||||||
|  |                 Just ( p, t, n ) -> | ||||||
|  |                     ( { state | ||||||
|  |                         | knownVertexTextures = Dict.insert index currentIndex knownVertexTextures | ||||||
|  |                         , currentIndex = currentIndex + 1 | ||||||
|  |                       } | ||||||
|  |                     , [ VertexWithTexture p t n ] | ||||||
|  |                     , currentIndex | ||||||
|  |                     ) | ||||||
|  | 
 | ||||||
|  |                 Nothing -> | ||||||
|  |                     -- TODO: lift this error into a Result type | ||||||
|  |                     ( state, [], -42 ) | ||||||
|  |                         |> log ("index " ++ toString index ++ " out of bounds!\nThis should never happen with a well formed file") | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | getOrInsertVTNT ( s_dir, t_dir ) index ({ vs, vts, vns, knownVertexTexturesTangents, currentIndex } as state) = | ||||||
|  |     case Dict.get index knownVertexTexturesTangents of | ||||||
|  |         Just i -> | ||||||
|  |             case state.currentMesh of | ||||||
|  |                 Just (WithTextureAndTangentT m) -> | ||||||
|  |                     ( { state | ||||||
|  |                         | currentMesh = | ||||||
|  |                             Just | ||||||
|  |                                 (WithTextureAndTangentT | ||||||
|  |                                     { m | ||||||
|  |                                         | vertices = | ||||||
|  |                                             updateArray i | ||||||
|  |                                                 (\({ sdir, tdir } as v) -> | ||||||
|  |                                                     { v | sdir = V3.add sdir s_dir, tdir = V3.add tdir t_dir } | ||||||
|  |                                                 ) | ||||||
|  |                                                 m.vertices | ||||||
|  |                                     } | ||||||
|  |                                 ) | ||||||
|  |                       } | ||||||
|  |                     , Array.empty | ||||||
|  |                     , i | ||||||
|  |                     ) | ||||||
|  | 
 | ||||||
|  |                 _ -> | ||||||
|  |                     -- should never happen | ||||||
|  |                     ( state, Array.empty, i ) | ||||||
|  | 
 | ||||||
|  |         Nothing -> | ||||||
|  |             case get3 index vs vts vns of | ||||||
|  |                 Just ( p, t, n ) -> | ||||||
|  |                     ( { state | ||||||
|  |                         | knownVertexTexturesTangents = Dict.insert index currentIndex knownVertexTexturesTangents | ||||||
|  |                         , currentIndex = currentIndex + 1 | ||||||
|  |                       } | ||||||
|  |                     , Array.fromList [ VertexWithTextureAndTangentT p t n s_dir t_dir ] | ||||||
|  |                     , currentIndex | ||||||
|  |                     ) | ||||||
|  | 
 | ||||||
|  |                 Nothing -> | ||||||
|  |                     -- TODO: lift this error into a Result type | ||||||
|  |                     ( state, Array.empty, -42 ) | ||||||
|  |                         |> log ("index " ++ toString index ++ " out of bounds!\nThis should never happen with a well formed file") | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | getOrInsertVN index ({ vs, vns, knownVertex, currentIndex } as state) = | ||||||
|  |     case Dict.get index knownVertex of | ||||||
|  |         Just i -> | ||||||
|  |             ( state, [], i ) | ||||||
|  | 
 | ||||||
|  |         Nothing -> | ||||||
|  |             case get2 index vs vns of | ||||||
|  |                 Just ( p, n ) -> | ||||||
|  |                     ( { state | ||||||
|  |                         | knownVertex = Dict.insert index currentIndex knownVertex | ||||||
|  |                         , currentIndex = currentIndex + 1 | ||||||
|  |                       } | ||||||
|  |                     , [ Vertex p n ] | ||||||
|  |                     , currentIndex | ||||||
|  |                     ) | ||||||
|  | 
 | ||||||
|  |                 Nothing -> | ||||||
|  |                     -- TODO: lift this error into a Result type | ||||||
|  |                     ( state, [], -42 ) | ||||||
|  |                         |> log ("index " ++ toString index ++ " out of bounds!\nThis should never happen with a well formed file") | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | fst2 ( a, b, c ) = | ||||||
|  |     ( a, b ) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | arrayUpdate i f a = | ||||||
|  |     case Array.get i a of | ||||||
|  |         Just e -> | ||||||
|  |             Array.set i (f e) a | ||||||
|  | 
 | ||||||
|  |         _ -> | ||||||
|  |             a | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | triangulate threeOrFour = | ||||||
|  |     case threeOrFour of | ||||||
|  |         Three t -> | ||||||
|  |             [ t ] | ||||||
|  | 
 | ||||||
|  |         Four ( a, b, c, d ) -> | ||||||
|  |             [ ( a, b, c ), ( d, a, c ) ] | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | createMesh withTangents f = | ||||||
|  |     let | ||||||
|  |         emptyMesh = | ||||||
|  |             { vertices = [], indices = [] } | ||||||
|  |     in | ||||||
|  |         case f of | ||||||
|  |             FTVertexTextureNormal _ -> | ||||||
|  |                 if withTangents then | ||||||
|  |                     WithTextureAndTangentT { emptyMesh | vertices = Array.empty } | ||||||
|  |                 else | ||||||
|  |                     WithTextureT emptyMesh | ||||||
|  | 
 | ||||||
|  |             FTVertexNormal _ -> | ||||||
|  |                 WithoutTextureT emptyMesh | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | -- | ||||||
|  | -- Some helpers: | ||||||
|  | -- | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | t3map f ( a, b, c ) = | ||||||
|  |     ( f a, f b, f c ) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | updateArray i f a = | ||||||
|  |     case Array.get i a of | ||||||
|  |         Just v -> | ||||||
|  |             Array.set i (f v) a | ||||||
|  | 
 | ||||||
|  |         Nothing -> | ||||||
|  |             a | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | get3 ( a, b, c ) a1 a2 a3 = | ||||||
|  |     case ( Array.get (a - 1) a1, Array.get (b - 1) a2, Array.get (c - 1) a3 ) of | ||||||
|  |         ( Just a_, Just b_, Just c_ ) -> | ||||||
|  |             Just ( a_, b_, c_ ) | ||||||
|  | 
 | ||||||
|  |         _ -> | ||||||
|  |             Nothing | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | get2 ( a, b ) a1 a2 = | ||||||
|  |     case ( Array.get (a - 1) a1, Array.get (b - 1) a2 ) of | ||||||
|  |         ( Just a_, Just b_ ) -> | ||||||
|  |             Just ( a_, b_ ) | ||||||
|  | 
 | ||||||
|  |         _ -> | ||||||
|  |             Nothing | ||||||
							
								
								
									
										102
									
								
								elm-stuff/packages/Zinggi/elm-obj-loader/1.0.3/src/OBJ/InternalTypes.elm
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										102
									
								
								elm-stuff/packages/Zinggi/elm-obj-loader/1.0.3/src/OBJ/InternalTypes.elm
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,102 @@ | |||||||
|  | module OBJ.InternalTypes exposing (..) | ||||||
|  | 
 | ||||||
|  | import Math.Vector3 exposing (Vec3) | ||||||
|  | import Math.Vector2 exposing (Vec2) | ||||||
|  | import Array.Hamt as Array exposing (Array) | ||||||
|  | import OBJ.Types exposing (..) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | -- | ||||||
|  | -- {- DEBUG -} | ||||||
|  | -- | ||||||
|  | -- import Native.Time | ||||||
|  | -- | ||||||
|  | -- | ||||||
|  | -- debugNow : () -> Float | ||||||
|  | -- debugNow = | ||||||
|  | --     Native.Time.now | ||||||
|  | -- | ||||||
|  | -- | ||||||
|  | -- time : String -> (() -> a) -> a | ||||||
|  | -- time name f = | ||||||
|  | --     let | ||||||
|  | --         a = | ||||||
|  | --             debugNow () | ||||||
|  | --     in | ||||||
|  | --         f () | ||||||
|  | --             |> (\r -> log (name ++ ": " ++ toString (debugNow () - a) ++ " ms") r) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | log s a = | ||||||
|  |     let | ||||||
|  |         _ = | ||||||
|  |             Debug.log s () | ||||||
|  |     in | ||||||
|  |         a | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | type MeshT | ||||||
|  |     = WithoutTextureT (MeshWith Vertex) | ||||||
|  |     | WithTextureT (MeshWith VertexWithTexture) | ||||||
|  |     | WithTextureAndTangentT (MeshWithT VertexWithTextureAndTangentT) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | type alias MeshWithT a = | ||||||
|  |     { vertices : Array a | ||||||
|  |     , indices : List Int3 | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | type alias VertexWithTextureAndTangentT = | ||||||
|  |     { position : Vec3, texCoord : Vec2, normal : Vec3, sdir : Vec3, tdir : Vec3 } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | type | ||||||
|  |     Line | ||||||
|  |     -- v 1 3 4 | ||||||
|  |     = V Vec3 | ||||||
|  |       -- vt 2 4 | ||||||
|  |     | Vt Vec2 | ||||||
|  |       -- vn 3 3 1 | ||||||
|  |     | Vn Vec3 | ||||||
|  |       -- f 1 2 4 | ||||||
|  |       -- f 1/3 2/3 1/7 | ||||||
|  |       -- f 1/2/3 7/4/2 8/12/90 | ||||||
|  |       -- f 4//8 4//1 6//2 | ||||||
|  |     | F Face | ||||||
|  |       -- steteful stuff | ||||||
|  |     | Object String | ||||||
|  |     | Group String | ||||||
|  |     | Smooth String | ||||||
|  |     | MtlLib String | ||||||
|  |     | UseMtl String | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | type Face | ||||||
|  |     = FVertexTextureNormal (ThreeOrFour Int3) | ||||||
|  |     | FVertexNormal (ThreeOrFour Int2) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | type FaceTriangle | ||||||
|  |     = FTVertexTextureNormal ( Int3, Int3, Int3 ) | ||||||
|  |     | FTVertexNormal ( Int2, Int2, Int2 ) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | type ThreeOrFour a | ||||||
|  |     = Three ( a, a, a ) | ||||||
|  |     | Four ( a, a, a, a ) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | type Group | ||||||
|  |     = GV { faces : List Int3 } | ||||||
|  |     | GVT { faces : List ( Int2, Int2, Int2 ) } | ||||||
|  |     | GVTN { faces : List ( Int3, Int3, Int3 ) } | ||||||
|  |     | GVN { faces : List ( Int2, Int2, Int2 ) } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | type alias Int2 = | ||||||
|  |     ( Int, Int ) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | type alias Int3 = | ||||||
|  |     ( Int, Int, Int ) | ||||||
							
								
								
									
										258
									
								
								elm-stuff/packages/Zinggi/elm-obj-loader/1.0.3/src/OBJ/Parser.elm
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										258
									
								
								elm-stuff/packages/Zinggi/elm-obj-loader/1.0.3/src/OBJ/Parser.elm
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,258 @@ | |||||||
|  | module OBJ.Parser exposing (..) | ||||||
|  | 
 | ||||||
|  | import Math.Vector3 as V3 exposing (Vec3, vec3) | ||||||
|  | import Math.Vector2 as V2 exposing (Vec2, vec2) | ||||||
|  | import Combine exposing (..) | ||||||
|  | import Json.Decode as JD | ||||||
|  | import Combine.Num exposing (..) | ||||||
|  | import Combine.Char exposing (..) | ||||||
|  | import OBJ.InternalTypes exposing (..) | ||||||
|  | import Regex exposing (find, HowMany(..)) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | -- TODO: figure out how nice error messages work | ||||||
|  | -- | ||||||
|  | -- The obj specs: | ||||||
|  | --  http://www.martinreddy.net/gfx/3d/OBJ.spec | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | parse : String -> Result String (List Line) | ||||||
|  | parse input = | ||||||
|  |     String.split "\n" input | ||||||
|  |         |> List.foldr parseLineAcc (Ok []) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | parseLineAcc : String -> Result String (List Line) -> Result String (List Line) | ||||||
|  | parseLineAcc line acc = | ||||||
|  |     case acc of | ||||||
|  |         Ok lines -> | ||||||
|  |             if canSkip line then | ||||||
|  |                 Ok lines | ||||||
|  |             else | ||||||
|  |                 parseLine line | ||||||
|  |                     |> Result.andThen | ||||||
|  |                         (\l -> | ||||||
|  |                             Ok (l :: lines) | ||||||
|  |                         ) | ||||||
|  | 
 | ||||||
|  |         Err e -> | ||||||
|  |             Err e | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | canSkip line = | ||||||
|  |     Regex.contains (Regex.regex "^((\\s*)|(\\s*#.*\\r?))$") line | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | parseLine l = | ||||||
|  |     case Combine.parse line l of | ||||||
|  |         Ok ( _, stream, result ) -> | ||||||
|  |             Ok result | ||||||
|  | 
 | ||||||
|  |         Err ( _, stream, errors ) -> | ||||||
|  |             Err (formatError errors stream) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | file : Parser s (List Line) | ||||||
|  | file = | ||||||
|  |     (many ignoredLines) | ||||||
|  |         *> sepBy (many1 ignoredLines) | ||||||
|  |             line | ||||||
|  |         <* (many ignoredLines) | ||||||
|  |         <* end | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | ignoredLines : Parser s () | ||||||
|  | ignoredLines = | ||||||
|  |     (skip eol) <|> (skip comment) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | objectName : Parser s String | ||||||
|  | objectName = | ||||||
|  |     regex "o[ \t]+" *> regex ".+" | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | mtllib : Parser s String | ||||||
|  | mtllib = | ||||||
|  |     regex "mtllib[ \t]+" *> regex ".+" | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | group : Parser s String | ||||||
|  | group = | ||||||
|  |     (regex "g[ \t]+" *> regex ".+") | ||||||
|  |         <|> (char 'g' *> succeed "") | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | smooth : Parser s String | ||||||
|  | smooth = | ||||||
|  |     regex "s[ \t]+" *> regex ".+" | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | usemtl : Parser s String | ||||||
|  | usemtl = | ||||||
|  |     regex "usemtl[ \t]+" *> regex ".+" | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | line : Parser s Line | ||||||
|  | line = | ||||||
|  |     choice | ||||||
|  |         [ V <$> vertex | ||||||
|  |         , Vt <$> vertexTexture | ||||||
|  |         , Vn <$> vertexNormal | ||||||
|  |         , F <$> face | ||||||
|  |         , Object <$> objectName | ||||||
|  |         , Group <$> group | ||||||
|  |         , Smooth <$> smooth | ||||||
|  |         , UseMtl <$> usemtl | ||||||
|  |         , MtlLib <$> mtllib | ||||||
|  |         ] | ||||||
|  |         <* regex "[ \t]*" | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | face : Parser s Face | ||||||
|  | face = | ||||||
|  |     regex "f[ \t]+" | ||||||
|  |         *> choice | ||||||
|  |             [ fVertexTextureNormal | ||||||
|  |             , fVertexNormal | ||||||
|  |             , fVertex | ||||||
|  |             , fVertexTexture | ||||||
|  |             ] | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | fVertex : Parser s a | ||||||
|  | fVertex = | ||||||
|  |     threeOrFourValues int | ||||||
|  |         *> fail "Models with no precalculated vertex normals are not supported!" | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | fVertexTexture : Parser s a | ||||||
|  | fVertexTexture = | ||||||
|  |     threeOrFourValues int_int | ||||||
|  |         *> fail "Models with no precalculated vertex normals are not supported!" | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | fVertexTextureNormal : Parser s Face | ||||||
|  | fVertexTextureNormal = | ||||||
|  |     FVertexTextureNormal <$> threeOrFourValues int_int_int | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | fVertexNormal : Parser s Face | ||||||
|  | fVertexNormal = | ||||||
|  |     FVertexNormal <$> threeOrFourValues int__int | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | threeValues : (a -> a -> a -> b) -> Parser s a -> Parser s b | ||||||
|  | threeValues tagger vtype = | ||||||
|  |     tagger <$> (vtype) <*> (spaces *> vtype) <*> (spaces *> vtype) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | fourValues : (a -> a -> a -> a -> b) -> Parser s a -> Parser s b | ||||||
|  | fourValues tagger vtype = | ||||||
|  |     tagger <$> (vtype) <*> (spaces *> vtype) <*> (spaces *> vtype) <*> (spaces *> vtype) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | threeOrFourValues : Parser s a -> Parser s (ThreeOrFour a) | ||||||
|  | threeOrFourValues elements = | ||||||
|  |     (Four <$> (fourValues (,,,) elements)) | ||||||
|  |         <|> (Three <$> (threeValues (,,) elements)) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | int_int : Parser s ( Int, Int ) | ||||||
|  | int_int = | ||||||
|  |     (,) <$> int <*> (string "/" *> int) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | int_int_int : Parser s ( Int, Int, Int ) | ||||||
|  | int_int_int = | ||||||
|  |     (,,) <$> int <*> (string "/" *> int) <*> (string "/" *> int) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | int__int : Parser s ( Int, Int ) | ||||||
|  | int__int = | ||||||
|  |     (,) <$> int <*> (string "//" *> int) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | vertexNormal : Parser s Vec3 | ||||||
|  | vertexNormal = | ||||||
|  |     regex "vn[ \t]+" *> (V3.normalize <$> vector3) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | vertexTexture : Parser s Vec2 | ||||||
|  | vertexTexture = | ||||||
|  |     regex "vt[ \t]+" *> ((ignoreZ <$> vector3) <|> vector2) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | vertex : Parser s Vec3 | ||||||
|  | vertex = | ||||||
|  |     regex "v[ \t]+" *> vector3 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | comment : Parser s String | ||||||
|  | comment = | ||||||
|  |     regex "#" *> regex ".*" | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | vector3 : Parser s Vec3 | ||||||
|  | vector3 = | ||||||
|  |     threeValues vec3 betterFloat | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | spaces : Parser s String | ||||||
|  | spaces = | ||||||
|  |     regex "[ \t]+" | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | vector2 : Parser s Vec2 | ||||||
|  | vector2 = | ||||||
|  |     vec2 <$> betterFloat <*> (spaces *> betterFloat) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | betterFloat : Parser s Float | ||||||
|  | betterFloat = | ||||||
|  |     (\s -> Result.withDefault 0 (JD.decodeString JD.float s)) <$> regex "[-+]?[0-9]*\\.?[0-9]+([eE][-+]?[0-9]+)?" | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | formatError : List String -> InputStream -> String | ||||||
|  | formatError ms stream = | ||||||
|  |     let | ||||||
|  |         location = | ||||||
|  |             currentLocation stream | ||||||
|  | 
 | ||||||
|  |         separator = | ||||||
|  |             "| " | ||||||
|  | 
 | ||||||
|  |         expectationSeparator = | ||||||
|  |             "\n  * " | ||||||
|  | 
 | ||||||
|  |         lineNumberOffset = | ||||||
|  |             floor (logBase 10 (toFloat location.line)) + 1 | ||||||
|  | 
 | ||||||
|  |         separatorOffset = | ||||||
|  |             String.length separator | ||||||
|  | 
 | ||||||
|  |         padding = | ||||||
|  |             location.column + separatorOffset + 2 | ||||||
|  |     in | ||||||
|  |         "Parse error around line:\n\n" | ||||||
|  |             ++ toString location.line | ||||||
|  |             ++ separator | ||||||
|  |             ++ location.source | ||||||
|  |             ++ "\n" | ||||||
|  |             ++ String.padLeft padding ' ' "^" | ||||||
|  |             ++ "\nI expected one of the following:\n" | ||||||
|  |             ++ expectationSeparator | ||||||
|  |             ++ String.join expectationSeparator ms | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | toInt : String -> Int | ||||||
|  | toInt s = | ||||||
|  |     String.toInt s |> Result.withDefault 0 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | ignoreZ : Vec3 -> Vec2 | ||||||
|  | ignoreZ v = | ||||||
|  |     let | ||||||
|  |         ( x, y, _ ) = | ||||||
|  |             V3.toTuple v | ||||||
|  |     in | ||||||
|  |         vec2 x y | ||||||
							
								
								
									
										74
									
								
								elm-stuff/packages/Zinggi/elm-obj-loader/1.0.3/src/OBJ/Types.elm
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								elm-stuff/packages/Zinggi/elm-obj-loader/1.0.3/src/OBJ/Types.elm
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,74 @@ | |||||||
|  | module OBJ.Types exposing (..) | ||||||
|  | 
 | ||||||
|  | {-| | ||||||
|  | These are the types used by the obj loader. | ||||||
|  | 
 | ||||||
|  | @docs ObjFile, Mesh, MeshWith | ||||||
|  | 
 | ||||||
|  | -- | ||||||
|  | @docs Vertex, VertexWithTexture, VertexWithTextureAndTangent | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | -} | ||||||
|  | 
 | ||||||
|  | import Dict exposing (Dict) | ||||||
|  | import Math.Vector2 exposing (Vec2) | ||||||
|  | import Math.Vector3 exposing (Vec3) | ||||||
|  | import Math.Vector4 exposing (Vec4) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | {-| A .obj file is optionally divided into different groups/objects. | ||||||
|  | Each group/object is optionally made up of different meshes, each with it's own material. | ||||||
|  | 
 | ||||||
|  | So the keys of this dictionary are: | ||||||
|  | 
 | ||||||
|  |     Dict GroupNameOrObjectName (Dict MaterialName Mesh) | ||||||
|  | 
 | ||||||
|  | If no name is specified in the input file, "__default__" will be used instead. | ||||||
|  | -} | ||||||
|  | type alias ObjFile = | ||||||
|  |     Dict String (Dict String Mesh) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | {-| | ||||||
|  | A `Mesh` loaded by the obj loader is a record with a list of vertices and a list of indices. | ||||||
|  | Depending on the mesh type and the loading options you get a different kind of mesh. | ||||||
|  | They differ on what information a vertex contains. | ||||||
|  | 
 | ||||||
|  | These meshes are meant to be used with `WebGL.indexedTriangles mesh.vertices mesh.indices`. | ||||||
|  | -} | ||||||
|  | type Mesh | ||||||
|  |     = WithoutTexture (MeshWith Vertex) | ||||||
|  |     | WithTexture (MeshWith VertexWithTexture) | ||||||
|  |     | WithTextureAndTangent (MeshWith VertexWithTextureAndTangent) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | {-| | ||||||
|  | -} | ||||||
|  | type alias MeshWith a = | ||||||
|  |     { vertices : List a | ||||||
|  |     , indices : List ( Int, Int, Int ) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | {-| -} | ||||||
|  | type alias Vertex = | ||||||
|  |     { position : Vec3, normal : Vec3 } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | {-| -} | ||||||
|  | type alias VertexWithTexture = | ||||||
|  |     { position : Vec3, texCoord : Vec2, normal : Vec3 } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | {-| | ||||||
|  | The `tangent` is a vector pointing tangential to the object surface, in the direction of the `u` texture coordinate. | ||||||
|  | This is needed for doing tangent space normal mapping. | ||||||
|  | The 4th component is either 1 or -1 and has to be used to get the bitangent in the glsl shader, | ||||||
|  | e.g: `vec3 bitangent = cross(normal, tangent.xyz) * tangent.w` | ||||||
|  | 
 | ||||||
|  | more info here: | ||||||
|  | https://web.archive.org/web/20160409104130/http://www.terathon.com/code/tangent.html | ||||||
|  | -} | ||||||
|  | type alias VertexWithTextureAndTangent = | ||||||
|  |     { position : Vec3, texCoord : Vec2, normal : Vec3, tangent : Vec4 } | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user