Skip to content

Commit 95b6070

Browse files
authored
feat: gltf transformation matrix
Respect transformation matrix inside GLTF
2 parents ce24c44 + bcfabf2 commit 95b6070

3 files changed

Lines changed: 67 additions & 24 deletions

File tree

main.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,16 +26,16 @@ func LoadPrimitives() error {
2626
// Note: requires LoadPrimitives() to be run beforehand if you want to get a primitive
2727
func GetModel(conf ModelReaderConf, desiredSize *MeshTypes.Vector) (*MeshTypes.Mesh, error) {
2828
var mesh *MeshTypes.Mesh
29+
var err error
2930

3031
if conf.File != nil && conf.Filename != nil && *conf.Filename != "" {
3132
filetype := filepath.Ext(*conf.Filename)
3233
switch filetype {
3334
case ".gltf", ".glb":
34-
meshes, err := FileHandlers.LoadGLTF(conf.File, desiredSize)
35+
mesh, err = FileHandlers.LoadGLTF(conf.File, desiredSize)
3536
if err != nil {
3637
return nil, err
3738
}
38-
mesh = meshes[0]
3939
case ".3ds":
4040
data, err := io.ReadAll(conf.File)
4141
if err != nil {

pkg/MeshTypes/mesh.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,10 @@ func (obj *Mesh) Copy() Mesh {
2121
return Mesh{Triangles: triangles}
2222
}
2323

24-
func (obj *Mesh) Add(mesh *Mesh) *Mesh {
25-
obj.Triangles = append(obj.Triangles, mesh.Triangles...)
24+
func (obj *Mesh) Add(mesh ...*Mesh) *Mesh {
25+
for _, element := range mesh {
26+
obj.Triangles = append(obj.Triangles, element.Triangles...)
27+
}
2628
return obj
2729
}
2830

pkg/file_handlers/gltf.go

Lines changed: 61 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)