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