@@ -10,34 +10,67 @@ import (
1010 "github.com/qmuntal/gltf"
1111)
1212
13- func LoadGLTF (file io.Reader , desiredSize * Types.Vector ) ([] * Types.Mesh , error ) {
13+ func LoadGLTF (file io.Reader , desiredSize * Types.Vector ) (* Types.Mesh , error ) {
1414 var doc gltf.Document
1515 gltf .NewDecoder (file ).Decode (& doc )
1616
17- var meshes [] * Types.Mesh
17+ var meshes * Types.Mesh = & Types. Mesh {}
1818
19- for _ , m := range doc .Meshes {
19+ transformationMatrices := map [int ]Types.Matrix {}
20+
21+ for _ , node := range doc .Nodes {
22+ if node .Mesh == nil {
23+ continue
24+ }
25+ matrix := node .MatrixOrDefault ()
26+ transformationMatrices [* node .Mesh ] = Types.Matrix {
27+ X00 : matrix [0 ], X01 : matrix [4 ], X02 : matrix [8 ], X03 : matrix [12 ],
28+ X10 : matrix [1 ], X11 : matrix [5 ], X12 : matrix [9 ], X13 : matrix [13 ],
29+ X20 : matrix [2 ], X21 : matrix [6 ], X22 : matrix [10 ], X23 : matrix [14 ],
30+ X30 : matrix [3 ], X31 : matrix [7 ], X32 : matrix [11 ], X33 : matrix [15 ],
31+ }
32+ }
33+
34+ // calculate outer dimensions
35+ min := Types.Vector {}
36+ max := Types.Vector {}
37+ for meshindex , m := range doc .Meshes {
2038 for _ , p := range m .Primitives {
2139 // contains Min and Max attr (for dimension calc)
2240 posAccessor := doc.Accessors [p.Attributes [gltf.POSITION ]]
23- scaling := Types.Vector {X : 1 , Y : 1 , Z : 1 }
24- if desiredSize != nil {
25- scaling = Types.Vector {
26- // axes inverted to convert to correct coordinate system
27- X : desiredSize .X / (posAccessor .Max [0 ] - posAccessor .Min [0 ]),
28- Y : desiredSize .Y / (posAccessor .Max [2 ] - posAccessor .Min [2 ]),
29- Z : desiredSize .Z / (posAccessor .Max [1 ] - posAccessor .Min [1 ]),
30- }
31- }
32- positions , err := gltfVec3 (& doc , posAccessor , scaling )
41+ // do transformation before getting the outer dimensions
42+ tempMin := transformationMatrices [meshindex ].MulPosition (Types.Vector {
43+ X : posAccessor .Min [0 ],
44+ Y : posAccessor .Min [2 ],
45+ Z : posAccessor .Min [1 ],
46+ })
47+ tempMax := transformationMatrices [meshindex ].MulPosition (Types.Vector {
48+ X : posAccessor .Max [0 ],
49+ Y : posAccessor .Max [2 ],
50+ Z : posAccessor .Max [1 ],
51+ })
52+ min = min .Min (& tempMin )
53+ max = max .Max (& tempMax )
54+ }
55+ }
56+
57+ scaling := Types.Vector {X : 1 , Y : 1 , Z : 1 }
58+ if desiredSize != nil {
59+ scaling = desiredSize .Div (max .Sub (min ))
60+ }
61+
62+ for meshindex , m := range doc .Meshes {
63+ for _ , p := range m .Primitives {
64+ posAccessor := doc.Accessors [p.Attributes [gltf.POSITION ]]
65+ positions , err := gltfVec3 (& doc , posAccessor , transformationMatrices [meshindex ], scaling )
3366 if err != nil {
3467 return nil , err
3568 }
3669
3770 var normals []Types.Vector
3871 if nIdx , ok := p .Attributes [gltf .NORMAL ]; ok {
3972 normalAccessor := doc .Accessors [nIdx ]
40- normals , err = gltfVec3 (& doc , normalAccessor , Types.Vector {X : 1 , Y : 1 , Z : 1 })
73+ normals , err = gltfVec3 (& doc , normalAccessor , transformationMatrices [ meshindex ], Types.Vector {X : 1 , Y : 1 , Z : 1 })
4174 if err != nil {
4275 return nil , err
4376 }
@@ -68,14 +101,14 @@ func LoadGLTF(file io.Reader, desiredSize *Types.Vector) ([]*Types.Mesh, error)
68101 mesh .AddTriangle (& Types.Triangle {V0 : v0 , V1 : v1 , V2 : v2 })
69102 }
70103
71- meshes = append ( meshes , & mesh )
104+ meshes . Add ( & mesh )
72105 }
73106 }
74107 }
75108 return meshes , nil
76109}
77110
78- func gltfVec3 (doc * gltf.Document , acc * gltf.Accessor , scaling Types.Vector ) ([]Types.Vector , error ) {
111+ func gltfVec3 (doc * gltf.Document , acc * gltf.Accessor , transformationMatrix Types. Matrix , scaling Types.Vector ) ([]Types.Vector , error ) {
79112 bufView := doc .BufferViews [* acc .BufferView ]
80113 buffer := doc .Buffers [bufView .Buffer ]
81114
@@ -87,10 +120,18 @@ func gltfVec3(doc *gltf.Document, acc *gltf.Accessor, scaling Types.Vector) ([]T
87120 for i := 0 ; i < acc .Count ; i ++ {
88121 base := i * 12
89122 // axes inverted to convert to correct coordinate system
90- x := math .Float32frombits (binary .LittleEndian .Uint32 (raw [base + 0 :]))
91- y := - (math .Float32frombits (binary .LittleEndian .Uint32 (raw [base + 8 :])))
92- z := math .Float32frombits (binary .LittleEndian .Uint32 (raw [base + 4 :]))
93- vectors [i ] = Types.Vector {X : float64 (x ) * scaling .X , Y : float64 (y ) * scaling .Y , Z : float64 (z ) * scaling .Z }
123+ vec := Types.Vector {
124+ X : float64 (math .Float32frombits (binary .LittleEndian .Uint32 (raw [base + 0 :]))),
125+ Y : float64 (math .Float32frombits (binary .LittleEndian .Uint32 (raw [base + 4 :]))),
126+ Z : float64 (math .Float32frombits (binary .LittleEndian .Uint32 (raw [base + 8 :]))),
127+ }
128+ transformed := transformationMatrix .MulPosition (vec )
129+ scaled := Types.Vector {
130+ X : transformed .X ,
131+ Y : - transformed .Z ,
132+ Z : transformed .Y ,
133+ }.Mult (scaling )
134+ vectors [i ] = scaled // vec.Mult(scaling)
94135 }
95136
96137 return vectors , nil
0 commit comments