@@ -3,56 +3,58 @@ package utils
3
3
import "C"
4
4
5
5
import (
6
+ "encoding/gob"
6
7
"errors"
7
8
"fmt"
8
9
"github.com/go-gl/gl/v4.1-core/gl"
10
+ "github.com/go-gl/mathgl/mgl32"
9
11
"github.com/raedatoui/assimp"
10
- "strconv"
11
12
"os"
12
- "github.com/go-gl/mathgl/mgl32"
13
+ "strconv"
14
+ "strings"
13
15
"unsafe"
14
16
)
15
17
16
18
type Mesh struct {
17
- id int
18
- vertices []Vertex
19
- indices []uint32
20
- textures []Texture
21
- Vao uint32
19
+ Id int
20
+ Vertices []Vertex
21
+ Indices []uint32
22
+ Textures []Texture
23
+ vao uint32
22
24
vbo , ebo uint32
23
25
}
24
26
25
27
func NewMesh (v []Vertex , i []uint32 , t []Texture ) Mesh {
26
28
m := Mesh {
27
- vertices : v ,
28
- indices : i ,
29
- textures : t ,
29
+ Vertices : v ,
30
+ Indices : i ,
31
+ Textures : t ,
30
32
}
31
33
m .setup ()
32
34
return m
33
35
}
34
36
35
37
func (m * Mesh ) setup () {
36
38
// size of the Vertex struct
37
- dummy := m .vertices [0 ]
39
+ dummy := m .Vertices [0 ]
38
40
structSize := int (unsafe .Sizeof (dummy ))
39
41
structSize32 := int32 (structSize )
40
42
41
43
// Create buffers/arrays
42
- gl .GenVertexArrays (1 , & m .Vao )
44
+ gl .GenVertexArrays (1 , & m .vao )
43
45
gl .GenBuffers (1 , & m .vbo )
44
46
gl .GenBuffers (1 , & m .ebo )
45
47
46
- gl .BindVertexArray (m .Vao )
48
+ gl .BindVertexArray (m .vao )
47
49
// Load data into vertex buffers
48
50
gl .BindBuffer (gl .ARRAY_BUFFER , m .vbo )
49
51
// A great thing about structs is that their memory layout is sequential for all its items.
50
52
// The effect is that we can simply pass a pointer to the struct and it translates perfectly to a gl.m::vec3/2 array which
51
53
// again translates to 3/2 floats which translates to a byte array.
52
- gl .BufferData (gl .ARRAY_BUFFER , len (m .vertices ) * structSize , gl .Ptr (m .vertices ), gl .STATIC_DRAW )
54
+ gl .BufferData (gl .ARRAY_BUFFER , len (m .Vertices ) * structSize , gl .Ptr (m .Vertices ), gl .STATIC_DRAW )
53
55
54
56
gl .BindBuffer (gl .ELEMENT_ARRAY_BUFFER , m .ebo )
55
- gl .BufferData (gl .ELEMENT_ARRAY_BUFFER , len (m .indices )* GL_FLOAT32_SIZE , gl .Ptr (m .indices ), gl .STATIC_DRAW )
57
+ gl .BufferData (gl .ELEMENT_ARRAY_BUFFER , len (m .Indices )* GL_FLOAT32_SIZE , gl .Ptr (m .Indices ), gl .STATIC_DRAW )
56
58
57
59
// Set the vertex attribute pointers
58
60
// Vertex Positions
@@ -91,12 +93,12 @@ func (m *Mesh) draw(program uint32) {
91
93
normalNr = 1
92
94
heightNr = 1
93
95
i = 0
94
- for i = 0 ; i < uint32 (len (m .textures )); i ++ {
96
+ for i = 0 ; i < uint32 (len (m .Textures )); i ++ {
95
97
gl .ActiveTexture (gl .TEXTURE0 + i ) // Active proper texture unit before binding
96
98
97
99
// Retrieve texture number (the N in diffuse_textureN)
98
100
ss := ""
99
- switch m .textures [i ].TextureType {
101
+ switch m .Textures [i ].TextureType {
100
102
case "texture_diffuse" :
101
103
ss = ss + strconv .FormatUint (diffuseNr , 10 ) // Transfer GLuint to stream
102
104
diffuseNr ++
@@ -112,20 +114,20 @@ func (m *Mesh) draw(program uint32) {
112
114
}
113
115
114
116
// Now set the sampler to the correct texture unit
115
- tu := m .textures [i ].TextureType + ss + "\x00 "
117
+ tu := m .Textures [i ].TextureType + ss + "\x00 "
116
118
117
119
gl .Uniform1i (gl .GetUniformLocation (program , gl .Str (tu )), int32 (i ))
118
120
// And finally bind the texture
119
- gl .BindTexture (gl .TEXTURE_2D , m .textures [i ].Id )
121
+ gl .BindTexture (gl .TEXTURE_2D , m .Textures [i ].id )
120
122
}
121
123
122
124
// Draw mesh
123
- gl .BindVertexArray (m .Vao )
124
- gl .DrawElements (gl .TRIANGLES , int32 (len (m .indices )), gl .UNSIGNED_INT , gl .PtrOffset (0 ))
125
+ gl .BindVertexArray (m .vao )
126
+ gl .DrawElements (gl .TRIANGLES , int32 (len (m .Indices )), gl .UNSIGNED_INT , gl .PtrOffset (0 ))
125
127
gl .BindVertexArray (0 )
126
128
127
129
// Always good practice to set everything back to defaults once configured.
128
- for i = 0 ; i < uint32 (len (m .textures )); i ++ {
130
+ for i = 0 ; i < uint32 (len (m .Textures )); i ++ {
129
131
gl .ActiveTexture (gl .TEXTURE0 + i )
130
132
gl .BindTexture (gl .TEXTURE_2D , 0 )
131
133
}
@@ -140,47 +142,104 @@ type Vertex struct {
140
142
}
141
143
142
144
type Texture struct {
143
- Id uint32
145
+ id uint32
144
146
TextureType string
145
147
Path string
146
148
}
147
149
148
150
type Model struct {
149
151
texturesLoaded map [string ]Texture
150
- meshes []Mesh
151
- director string
152
- gammaCorrection bool
153
- basePath string
154
- fileName string
152
+ Meshes []Mesh
153
+ GammaCorrection bool
154
+ BasePath string
155
+ FileName string
156
+ GobName string
155
157
}
156
158
157
159
func NewModel (b , f string , g bool ) (Model , error ) {
158
-
160
+ t := strings .Split (f , "." )
161
+ gf := t [0 ] + ".gob"
159
162
m := Model {
160
- basePath : b ,
161
- fileName : f ,
162
- gammaCorrection : g ,
163
+ BasePath : b ,
164
+ FileName : f ,
165
+ GobName : gf ,
166
+ GammaCorrection : g ,
163
167
}
164
168
m .texturesLoaded = make (map [string ]Texture )
165
- err := m .loadModel ()
169
+ gobFile := b + gf
170
+ if _ , err := os .Stat (gobFile ); os .IsNotExist (err ) {
171
+ err := m .loadModel ()
172
+ //m.Export()
173
+ return m , err
174
+ }
175
+ err := m .Import ()
166
176
return m , err
167
177
}
168
178
169
179
func (m * Model ) Draw (shader uint32 ) {
170
- for i := 0 ; i < len (m .meshes ); i ++ {
171
- m .meshes [i ].draw (shader )
180
+ for i := 0 ; i < len (m .Meshes ); i ++ {
181
+ m .Meshes [i ].draw (shader )
182
+ }
183
+ }
184
+
185
+ func (m * Model ) Export () error {
186
+ // export a gob file
187
+ f := m .BasePath + m .GobName
188
+
189
+ dataFile , err := os .Create (f )
190
+ if err != nil {
191
+ return err
192
+ }
193
+ defer dataFile .Close ()
194
+
195
+ dataEncoder := gob .NewEncoder (dataFile )
196
+ dataEncoder .Encode (m )
197
+
198
+ return nil
199
+ }
200
+
201
+ func (m * Model ) Import () error {
202
+ f := m .BasePath + m .GobName
203
+ dataFile , err := os .Open (f )
204
+
205
+ if err != nil {
206
+ return err
207
+ }
208
+ defer dataFile .Close ()
209
+
210
+ dataDecoder := gob .NewDecoder (dataFile )
211
+ err = dataDecoder .Decode (& m )
212
+
213
+ if err != nil {
214
+ return nil
215
+ }
216
+ for _ , mesh := range m .Meshes {
217
+ mesh .setup ()
218
+
219
+ fmt .Printf ("vertices: %d, indices: %d, textures: %d\n " , len (mesh .Vertices ), len (mesh .Indices ), len (mesh .Textures ))
220
+
221
+ for _ , tex := range mesh .Textures {
222
+ if val , ok := m .texturesLoaded [tex .Path ]; ok {
223
+ fmt .Println ( val )
224
+ } else {
225
+
226
+ tex .id = m .textureFromFile (tex .Path )
227
+ m .texturesLoaded [tex .Path ] = tex
228
+ }
229
+ }
172
230
}
231
+ return nil
173
232
}
174
233
175
234
// Loads a model with supported ASSIMP extensions from file and stores the resulting meshes in the meshes vector.
176
235
func (m * Model ) loadModel () error {
177
236
// Read file via ASSIMP
178
- path := m .basePath + m .fileName
237
+ path := m .BasePath + m .FileName
179
238
scene := assimp .ImportFile (path , uint (
180
239
assimp .Process_Triangulate | assimp .Process_FlipUVs ))
181
240
182
241
// Check for errors
183
- if scene .Flags () & assimp .SceneFlags_Incomplete != 0 { // if is Not Zero
242
+ if scene .Flags ()& assimp .SceneFlags_Incomplete != 0 { // if is Not Zero
184
243
fmt .Println ("ERROR::ASSIMP:: %s\n " , scene .Flags ())
185
244
return errors .New ("shit failed" )
186
245
}
@@ -198,37 +257,30 @@ func (m *Model) processNode(n *assimp.Node, s *assimp.Scene) {
198
257
// The scene contains all the data, node is just to keep stuff organized (like relations between nodes).
199
258
mesh := s .Meshes ()[n .Meshes ()[i ]]
200
259
ms := m .processMesh (mesh , s )
201
- ms .id = i
202
- m .meshes = append (m .meshes , ms )
260
+ ms .Id = i
261
+ fmt .Printf ("vertices: %d, indices: %d, textures: %d\n " , len (ms .Vertices ), len (ms .Indices ), len (ms .Textures ))
262
+ m .Meshes = append (m .Meshes , ms )
203
263
}
204
264
205
265
// After we've processed all of the meshes (if any) we then recursively process each of the children nodes
206
266
c := n .Children ()
207
267
for j := 0 ; j < len (c ); j ++ {
268
+ //go func(n *assimp.Node, s *assimp.Scene) {
208
269
m .processNode (c [j ], s )
270
+ //}(c[j], s)
209
271
}
210
272
}
211
273
212
274
func (m * Model ) processMeshVertices (mesh * assimp.Mesh ) []Vertex {
213
275
// Walk through each of the mesh's vertices
214
276
vertices := []Vertex {}
215
- //p, _ := os.Create("data/positions"+ mesh.Name()+ ".txt")
216
- //n, _ := os.Create("data/normals"+ mesh.Name()+ ".txt")
217
- //t, _ := os.Create("data/texcoords"+ mesh.Name()+ ".txt")
218
- //
219
- //defer p.Close()
220
- //defer n.Close()
221
- //defer t.Close()
222
- //p.WriteString(mesh.Name() + "\n")
223
- //n.WriteString(mesh.Name() + "\n")
224
- //t.WriteString(mesh.Name() + "\n")
225
277
226
278
positions := mesh .Vertices ()
227
279
228
280
normals := mesh .Normals ()
229
281
useNormals := len (normals ) > 0
230
282
231
- tex := mesh .TextureCoords (0 )
283
+ tex := mesh .TextureCoords (0 )
232
284
useTex := true
233
285
if tex == nil {
234
286
useTex = false
@@ -259,7 +311,7 @@ func (m *Model) processMeshVertices(mesh *assimp.Mesh) []Vertex {
259
311
// Does the mesh contain texture coordinates?
260
312
// A vertex can contain up to 8 different texture coordinates. We thus make the assumption that we won't
261
313
// use models where a vertex can have multiple texture coordinates so we always take the first set (0).
262
- vertex .TexCoords = mgl32.Vec2 {tex [i ].X (), tex [i ].Y ()}
314
+ vertex .TexCoords = mgl32.Vec2 {tex [i ].X (), tex [i ].Y ()}
263
315
} else {
264
316
vertex .TexCoords = mgl32.Vec2 {0.0 , 0.0 }
265
317
}
@@ -282,16 +334,12 @@ func (m *Model) processMeshVertices(mesh *assimp.Mesh) []Vertex {
282
334
283
335
func (m * Model ) processMeshIndices (mesh * assimp.Mesh ) []uint32 {
284
336
indices := []uint32 {}
285
- ind , _ := os .Create ("data/indices" + mesh .Name ()+ ".txt" )
286
337
// Now wak through each of the mesh's faces (a face is a mesh its triangle) and retrieve the corresponding vertex indices.
287
338
for i := 0 ; i < mesh .NumFaces (); i ++ {
288
339
face := mesh .Faces ()[i ]
289
- t := face .CopyIndices ()
290
- ind .WriteString (fmt .Sprintf ("[%d, %d, %d]\n " , t [0 ], t [1 ], t [2 ]))
291
340
// Retrieve all indices of the face and store them in the indices vector
292
- indices = append (indices ,t ... )
341
+ indices = append (indices , face . CopyIndices () ... )
293
342
}
294
- ind .WriteString ("\n --------" )
295
343
return indices
296
344
}
297
345
@@ -324,12 +372,12 @@ func (m *Model) processMeshTextures(mesh *assimp.Mesh, s *assimp.Scene) []Textur
324
372
return textures
325
373
}
326
374
327
- func (ml * Model ) processMesh (m * assimp.Mesh , s * assimp.Scene ) Mesh {
375
+ func (m * Model ) processMesh (ms * assimp.Mesh , s * assimp.Scene ) Mesh {
328
376
// Return a mesh object created from the extracted mesh data
329
377
return NewMesh (
330
- ml .processMeshVertices (m ),
331
- ml .processMeshIndices (m ),
332
- ml .processMeshTextures (m , s ))
378
+ m .processMeshVertices (ms ),
379
+ m .processMeshIndices (ms ),
380
+ m .processMeshTextures (ms , s ))
333
381
}
334
382
335
383
func (m * Model ) loadMaterialTextures (ms * assimp.Material , tm assimp.TextureMapping , tt string ) []Texture {
@@ -339,20 +387,20 @@ func (m *Model) loadMaterialTextures(ms *assimp.Material, tm assimp.TextureMappi
339
387
340
388
for i := 0 ; i < textureCount ; i ++ {
341
389
file , _ , _ , _ , _ , _ , _ , _ := ms .GetMaterialTexture (textureType , 0 )
342
- filename := m .basePath + file
390
+ filename := m .BasePath + file
343
391
if val , ok := m .texturesLoaded [filename ]; ok {
344
392
result = append (result , val )
345
393
} else {
346
394
texId := m .textureFromFile (filename )
347
- texture := Texture {Id : texId , TextureType : tt , Path : file }
395
+ texture := Texture {id : texId , TextureType : tt , Path : filename }
348
396
result = append (result , texture )
349
397
m .texturesLoaded [filename ] = texture
350
398
}
351
399
}
352
400
return result
353
401
}
354
402
355
- func (ml * Model ) textureFromFile (f string ) uint32 {
403
+ func (m * Model ) textureFromFile (f string ) uint32 {
356
404
//Generate texture ID and load texture data
357
405
var textureID uint32
358
406
0 commit comments