;; mode is a bit of a dodge
;; it basically returns whatever the
;; last vertex positions mode was
;; GL_POINTS GL_LINES GL_TRIANGLE GL_QUADS or GL_POLYGON
(bind-func ai_build_mesh_vbo
(lambda (vao:VAO* mesh:aiMesh* xmesh:XTMMesh* modes:i32*)
;; (printf "... mesh vbo\n")
(let ((i:i32 0) (j:i32 0) (k:i64 0)
(vbodata:float* null)
(max_active_bones:i32 0) ;; most active bones on any 1 vertex
(num_bones:i32 (tref mesh 11))
(meshbones:XTMBone* (halloc num_bones))
(vbostride:i64 (i32toi64 (+ 16 (* 2 4)))) ;; 2d+4d+3d+3d+4d + 4 active bones * 2d space (weight+idx per bone)
(positions:i64 0)
(position_cnt:i64 -1)
(vertices:aiVector3D* (tref mesh 3))
(normals:aiVector3D* (tref mesh 4))
(num_vertices (tref mesh 1))
(num_faces:i32 (tref mesh 2))
(bones:aiBone** (tref mesh 12))
(faces (tref mesh 10))
(face:aiFace* null)
(num_indicies:i32 0)
(face_mode:i32 0)
(index:i32 0)
(dat:float* null)
(idat:i32* null)
(tmp:float 0.0)
(indicies:i32* null)
(colors:aiColor4D* (aref (tref-ptr mesh 7) 0)) ;; only use first 'set' of colors
(texturecoords:aiVector3D* (aref (tref-ptr mesh 8) 0))) ;; only use first 'set' of texcoords
(tset! xmesh 12 num_bones)
(tset! xmesh 13 meshbones)
;; precalc the total number of positions required
;; this is the total number of faces * the total number of
;; indexes per face
(dotimes (i num_faces)
(set! face (pref-ptr faces i))
(set! positions (+ positions (convert (tref face 0))))
(set! indicies (tref face 1))
(dotimes (j (tref face 0))
(set! index (pref indicies j))
;; (printf "index: %d:%d\n" (+ (- positions 3) j) index)
(if (or (< index 0) (> index num_vertices))
(printf "Bad Index Value: %d:%d (%d:%d) %d:%d\n" index num_vertices i j (pref indicies (+ j 1)) (pref indicies (+ j 2))))))
(printf "...mesh:> faces:%d vertices:%d bones:%d\n" num_faces positions num_bones)
(dotimes (i num_bones)
(println ".....bone:>" (tref-ptr (pref bones i) 0) "ptr:" (cast (pref bones i) i8*)))
;; 1d id + 4d position + 3d normal + 3d coord + 4d colors + (num_bones * ids) + (num_bones * weights)
;; where ids are i32 and everything else is a float
(let ((vbod:float* (halloc (* positions vbostride))))
;;(memset (cast vbod i8*) 0 (* positions vbostride 4))
(set! vbodata vbod))
(dotimes (i num_faces)
(set! face (pref-ptr faces i))
(set! num_indicies (tref face 0))
(if (<> num_indicies 3)
(printf "ERROR: all faces must be triangulated!!!!\n"))
(set! indicies (tref face 1))
(dotimes (j num_indicies)
(set! position_cnt (+ position_cnt 1))
(set! index (pref indicies j))
;; set index (as i32)
(pset! (cast (pref-ptr vbodata (+ 0 (* position_cnt vbostride))) i32*) 0 index)
;; (printf "index %d:%d:%d:%d:%p:%p:%p\n" j num_indicies index position_cnt face indicies faces)
(if (or (< index 0) (> index num_vertices))
(printf "...Bad Index Value: %d:%d\n" index num_vertices))
(pfill! (pref-ptr vbodata (+ 2 (* position_cnt vbostride)))
(tref (pref-ptr vertices index) 0) ;; x
(tref (pref-ptr vertices index) 1) ;; y
(tref (pref-ptr vertices index) 2) ;; z
1.0 ;; we are a position (i.e. w==1)
)
(if (null? normals)
(pfill! (pref-ptr vbodata (+ 6 (* position_cnt vbostride))) ;; offset 4
0.0 1.0 0.0) ;; normal pointing up Y
(pfill! (pref-ptr vbodata (+ 6 (* position_cnt vbostride))) ;; offset 4
(tref (pref-ptr normals index) 0) ;; x
(tref (pref-ptr normals index) 1) ;; y
(tref (pref-ptr normals index) 2) ;; z
))
(if (null? texturecoords)
(pfill! (pref-ptr vbodata (+ 9 (* position_cnt vbostride))) ;; offset 4+3
0.0 1.0 0.0) ;; normal pointing up Y
(pfill! (pref-ptr vbodata (+ 9 (* position_cnt vbostride)))
(tref (pref-ptr texturecoords index) 0) ;; x
(tref (pref-ptr texturecoords index) 1) ;; y
0.0 ;;(tref (pref-ptr texturecoords index) 2) ;; z
))
(if (null? colors) ;; if colors is null make vertex color white!
(pfill! (pref-ptr vbodata (+ 12 (* position_cnt vbostride))) ;; offset 4+3+3
1.0 1.0 1.0 1.0)
(pfill! (pref-ptr vbodata (+ 12 (* position_cnt vbostride))) ;; offset 4+3+3
(tref (pref-ptr colors index) 0) ;; r
(tref (pref-ptr colors index) 1) ;; g
(tref (pref-ptr colors index) 2) ;; b
(tref (pref-ptr colors index) 3) ;; a
))))
(if (<> (+ 1 position_cnt) positions)
(printf "Error: positions:%ld <> position_cnt:%ld" positions (+ position_cnt 1)))
(pset! modes 0 GL_TRIANGLES) ;; face_mode)
;; do bones!
(dotimes (i num_bones)
;; do bones!
(let ((bone:aiBone* (pref bones i))
(xbone:XTMBone* (pref-ptr meshbones i))
(num_weights:i32 (tref bone 1))
(weights:aiVertexWeight* (tref bone 2))
(weight:aiVertexWeight* null)
(offsetmat:aiMatrix4x4* (tref-ptr bone 3))
(xoffsetmat:float* (halloc 16))
(vidx:i32 0)
(vid:i32 0)
(looking:i1 #t)
(vertdat:float* null)
(boneidx:i32* null)
(boneweight:float* null)
(vertbones:i32 0)
(vweight:float 0.0)
(transform (pref bone 3)))
(memcpy (cast offsetmat i8*) (cast offsetmat i8*) (* 16 4))
(tfill! xbone (toString (tref-ptr bone 0)) i null xoffsetmat 0 null)
(dotimes (k positions)
(set! vertdat (pref-ptr vbodata (* k vbostride)))
(set! vertbones (pref (cast vertdat i32*) 1))
(set! vid (pref (cast vertdat i32*) 0))
(if (> vertbones 3)
(begin ;; keep overwriting last bone if more than 4!
(set! boneidx (pref-ptr (cast vertdat i32*) (+ 16 3)))
(set! boneweight (pref-ptr vertdat (+ 16 4 3))))
(begin
(set! boneidx (pref-ptr (cast vertdat i32*) (+ 16 vertbones)))
(set! boneweight (pref-ptr vertdat (+ 16 4 vertbones)))))
(set! looking #t)
(set! j 0)
(while (and looking (< j num_weights))
(set! weight (pref-ptr weights j))
(set! vidx (tref weight 0))
(set! vweight (tref weight 1))
(if (= vidx vid)
(begin (pset! boneidx 0 i)
(pset! boneweight 0 vweight)
(set! looking #f)
(set! vertbones (+ vertbones 1))
(pset! (cast vertdat i32*) 1 vertbones)
))
(if (> vertbones max_active_bones)
(set! max_active_bones vertbones))
(set! j (+ j 1))))))
(if (> max_active_bones 4)
(println "Warning! More than 4 active bones in mesh!"))
(println "MAX ACTIVE BONES:" max_active_bones)
(tset! xmesh 14 max_active_bones)
;; bone sanity check
(dotimes (k positions)
(set! tmp 0.0)
(set! dat (pref-ptr vbodata (+ 16 (i32toi64 num_bones) (* k vbostride))))
(set! idat (cast (pref-ptr vbodata (* k vbostride)) i32*))
(dotimes (i num_bones)
(set! tmp (+ tmp (pref dat i))))
;; (println "vertidx:" k "vid:" (pref idat 0) "bones:" (pref idat 1) "total-weight:" tmp))
(if (and (> tmp 0.01)
(< tmp 0.95))
(println "Error weight for vert:" k "bones:" (pref idat 1) "total:" tmp)
void))
;; return vbo
(let ((vbo (VBO vbodata (* positions vbostride) GL_STATIC_DRAW positions vbostride)))
(set_attribute vao vbo 0 4 (convert vbostride) 2)
(set_attribute vao vbo 1 3 (convert vbostride) 6)
(set_attribute vao vbo 2 3 (convert vbostride) 9)
(set_attribute vao vbo 3 4 (convert vbostride) 12)
;;; santiy check for num of bones
;; (dotimes (k positions)
;; (println "pos:" k "bones:" (pref (cast (pref-ptr vbodata (* k vbostride)) i32*) 1)))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(if (> num_bones 0)
(begin
(set_attribute vao vbo 4 4 (convert vbostride) 16) ;; bone ids
(set_attribute vao vbo 5 4 (convert vbostride) (+ 16 num_bones)))) ;; bone weights
(gl_print_error "error before setting GL_INT active")
(set_attribute vao vbo 6 1 (convert vbostride) 1) ;; active bones
(gl_print_error "error IN setting GL_INT active")
(glBindBuffer GL_ARRAY_BUFFER 0)
vbo))))