diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,5 +1,9 @@
 # Changelog for keid-resource-gltf
 
+## 0.1.1.0
+
+- Scene loader updated to follow geomancy-0.3 fixes and glTF spec.
+
 ## 0.1.0.2
 
 - Support Word8 index format.
diff --git a/keid-resource-gltf.cabal b/keid-resource-gltf.cabal
--- a/keid-resource-gltf.cabal
+++ b/keid-resource-gltf.cabal
@@ -1,11 +1,11 @@
 cabal-version: 1.12
 
--- This file has been generated from package.yaml by hpack version 0.35.2.
+-- This file has been generated from package.yaml by hpack version 0.38.1.
 --
 -- see: https://github.com/sol/hpack
 
 name:           keid-resource-gltf
-version:        0.1.0.2
+version:        0.1.1.0
 synopsis:       GLTF loader for Keid engine.
 category:       Game Engine
 author:         IC Rainbow
@@ -62,10 +62,10 @@
       base >=4.7 && <5
     , bytestring
     , containers
-    , geomancy >=0.2.6.0
+    , geomancy >=0.3.0.0
     , gl-block
     , gltf-codec
-    , keid-core
+    , keid-core >=0.1.11.0
     , rio >=0.1.12.0
     , vector
   default-language: GHC2021
diff --git a/src/Resource/Gltf/Scene.hs b/src/Resource/Gltf/Scene.hs
--- a/src/Resource/Gltf/Scene.hs
+++ b/src/Resource/Gltf/Scene.hs
@@ -13,6 +13,7 @@
 import Data.Tree qualified as Tree
 import Geomancy (Transform(..), quaternion)
 import Geomancy.Mat4 qualified as Mat4
+import Geomancy.Mat4.Internal qualified as Mat4 (fromMemory)
 import Geomancy.Transform qualified as Transform
 import Geomancy.Vec3 qualified as Vec3
 import RIO.Vector qualified as Vector
@@ -125,9 +126,24 @@
     adjustNode Stuff{..} = Stuff
       { sPositions = fmap applyTransform sPositions
       , sAttrs     = fmap applyAttrTransform sAttrs
-      , sIndices   = sIndices
+      , sIndices   = adjustIndices sIndices
       }
       where
+        {-
+          https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#instantiation
+
+          When a mesh primitive uses any triangle-based topology (i.e., triangles, triangle strip, or triangle fan),
+          the determinant of the node’s global transform defines the winding order of that primitive.
+
+          If the determinant is a positive value, the winding order triangle faces is counterclockwise;
+          in the opposite case, the winding order is clockwise.
+        -}
+        adjustIndices =
+          if Mat4.det transform < 0 then
+            Vector.reverse
+          else
+            id
+
         applyTransform pos =
           coerce $ Transform.apply (coerce pos) transform
 
@@ -150,7 +166,7 @@
   where
     go (parent, Tree.Node{rootLabel=(mmesh, node), subForest}) =
       let
-        collected = localTransform node <> parent
+        collected = mconcat $ parent : nodeTransforms node
       in
         ( (mmesh, collected, node)
         , map (collected,) subForest
@@ -210,45 +226,44 @@
         Just mesh ->
           Right (Just mesh)
 
-localTransform :: Node.Node -> Transform
-localTransform node = mconcat
-  [ nodeMatrix
-  , nodeScale, nodeRotate, nodeTranslate
-  ]
+nodeTransforms :: Node.Node -> [Transform]
+nodeTransforms node =
+  case nodeMatrix of
+    -- glTF spec says matrix should not be mixed with transforms...
+    Just takesPrecedence ->
+      -- ...but when that happens matrix takes precedence.
+      [takesPrecedence]
+    Nothing ->
+      catMaybes
+        [ nodeTranslate
+        , nodeRotate
+        , nodeScale
+        ]
   where
-    nodeScale = case Node.scale node of
-      Nothing ->
-        mempty
-      Just (sx, sy, sz) ->
+    nodeScale =
+      node.scale <&> \(sx, sy, sz) ->
         Transform.scale3 sx sy sz
 
     nodeTranslate =
-      case Node.translation node of
-        Nothing ->
-          mempty
-        Just (tx, ty, tz) ->
+      node.translation <&> \(tx, ty, tz) ->
           Transform.translate tx ty tz
 
-    nodeRotate = case Node.rotation node of
-      Nothing ->
-        mempty
-      Just (qx, qy, qz, qW) ->
+    nodeRotate =
+      node.rotation <&> \(qx, qy, qz, qW) ->
         Transform.rotateQ $ quaternion qW qx qy qz
 
-    nodeMatrix = case Node.matrix node of
-      Nothing ->
-        mempty
-      Just (Node.NodeMatrix memoryBytes) ->
-        case Vector.toList memoryBytes of
-          [ x1, x2, x3, x4,
-            y1, y2, y3, y4,
-            z1, z2, z3, z4,
-            w1, w2, w3, w4 ] ->
-              Mat4.colMajor @Transform
-                x1 y1 z1 w1
-                x2 y2 z2 w2
-                x3 y3 z3 w3
-                x4 y4 z4 w4
+    nodeMatrix =
+      node.matrix <&> \(Node.NodeMatrix memoryBytes) ->
+        Transform $ case Vector.toList memoryBytes of
+          [ e0, e1, e2, e3,
+            e4, e5, e6, e7,
+            e8, e9, eA, eB,
+            eC, eD, eE, eF ] ->
+              Mat4.fromMemory
+                e0 e1 e2 e3
+                e4 e5 e6 e7
+                e8 e9 eA eB
+                eC eD eE eF
           _ ->
             error "Node matrix isn't 16-element"
 
