Full mesh parsing

This commit is contained in:
bloeys
2021-11-18 21:02:14 +04:00
parent e7e81afc7c
commit 77e62588fe
6 changed files with 364 additions and 13 deletions

View File

@ -10,17 +10,18 @@ package asig
//Functions
struct aiScene* aiImportFile(const char* pFile, unsigned int pFlags);
*/
import "C"
import "unsafe"
import (
"unsafe"
"github.com/bloeys/gglm/gglm"
)
type Node struct {
}
type Mesh struct {
Vertices uint
}
type Material struct {
}
@ -58,31 +59,259 @@ func ImportFile(file string, postProcessFlags uint) *Scene {
cs := C.aiImportFile(cstr, C.uint(postProcessFlags))
scene := parseScene(cs)
println("Num verts:", scene.Meshes[0].Vertices, "; Meshes:", len(scene.Meshes))
return &Scene{}
return scene
}
func parseScene(cs *C.struct_aiScene) *Scene {
s := &Scene{}
s.Meshes = parseMeshes(*cs.mMeshes, uint(cs.mNumMeshes))
s.Meshes = parseMeshes(cs.mMeshes, uint(cs.mNumMeshes))
return s
}
func parseMeshes(cm *C.struct_aiMesh, count uint) []*Mesh {
func parseMeshes(cm **C.struct_aiMesh, count uint) []*Mesh {
if cm == nil {
return []*Mesh{}
}
meshes := make([]*Mesh, count)
cmeshes := unsafe.Slice(&cm, count)
cmeshes := unsafe.Slice(cm, count)
for i := 0; i < int(count); i++ {
m := &Mesh{}
m.Vertices = uint(cmeshes[i].mNumVertices)
cmesh := cmeshes[i]
vertCount := uint(cmesh.mNumVertices)
m.Vertices = parseVec3s(cmesh.mVertices, vertCount)
m.Normals = parseVec3s(cmesh.mNormals, vertCount)
m.Tangents = parseVec3s(cmesh.mTangents, vertCount)
m.BitTangents = parseVec3s(cmesh.mBitangents, vertCount)
//Color sets
m.ColorSets = parseColorSet(cmesh.mColors, vertCount)
//Tex coords
m.TexCoords = parseTexCoords(cmesh.mTextureCoords, vertCount)
m.TexCoordChannelCount = [8]uint{}
for j := 0; j < len(cmesh.mTextureCoords); j++ {
//If a color set isn't available then it is nil
if cmesh.mTextureCoords[j] == nil {
continue
}
m.TexCoordChannelCount[j] = uint(cmeshes[j].mNumUVComponents[j])
}
//Faces
cFaces := unsafe.Slice(cmesh.mFaces, cmesh.mNumFaces)
m.Faces = make([]Face, cmesh.mNumFaces)
for j := 0; j < len(m.Faces); j++ {
m.Faces[j] = Face{
Indices: parseUInts(cFaces[j].mIndices, uint(cFaces[j].mNumIndices)),
}
}
//Other
m.Bones = parseBones(cmesh.mBones, uint(cmesh.mNumBones))
m.AnimMeshes = parseAnimMeshes(cmesh.mAnimMeshes, uint(cmesh.mNumAnimMeshes))
m.AABB = AABB{
Min: parseVec3(&cmesh.mAABB.mMin),
Max: parseVec3(&cmesh.mAABB.mMax),
}
m.MorphMethod = MorphMethod(cmesh.mMethod)
m.MaterialIndex = uint(cmesh.mMaterialIndex)
m.Name = parseAiString(cmesh.mName)
meshes[i] = m
}
return meshes
}
func parseVec3(cv *C.struct_aiVector3D) gglm.Vec3 {
return gglm.Vec3{
Data: [3]float32{
float32(cv.x),
float32(cv.y),
float32(cv.z),
},
}
}
func parseAnimMeshes(cam **C.struct_aiAnimMesh, count uint) []*AnimMesh {
if cam == nil {
return []*AnimMesh{}
}
animMeshes := make([]*AnimMesh, count)
cAnimMeshes := unsafe.Slice(cam, count)
for i := 0; i < int(count); i++ {
m := cAnimMeshes[i]
animMeshes[i] = &AnimMesh{
Name: parseAiString(m.mName),
Vertices: parseVec3s(m.mVertices, uint(m.mNumVertices)),
Normals: parseVec3s(m.mNormals, uint(m.mNumVertices)),
Tangents: parseVec3s(m.mTangents, uint(m.mNumVertices)),
BitTangents: parseVec3s(m.mBitangents, uint(m.mNumVertices)),
Colors: parseColorSet(m.mColors, uint(m.mNumVertices)),
TexCoords: parseTexCoords(m.mTextureCoords, uint(m.mNumVertices)),
Weight: float32(m.mWeight),
}
}
return animMeshes
}
func parseTexCoords(ctc [MaxTexCoords]*C.struct_aiVector3D, vertCount uint) [MaxTexCoords][]gglm.Vec3 {
texCoords := [MaxTexCoords][]gglm.Vec3{}
for j := 0; j < len(ctc); j++ {
//If a color set isn't available then it is nil
if ctc[j] == nil {
continue
}
texCoords[j] = parseVec3s(ctc[j], vertCount)
}
return texCoords
}
func parseColorSet(cc [MaxColorSets]*C.struct_aiColor4D, vertCount uint) [MaxColorSets][]gglm.Vec4 {
colorSet := [MaxColorSets][]gglm.Vec4{}
for j := 0; j < len(cc); j++ {
//If a color set isn't available then it is nil
if cc[j] == nil {
continue
}
colorSet[j] = parseColors(cc[j], vertCount)
}
return colorSet
}
func parseBones(cbs **C.struct_aiBone, count uint) []*Bone {
if cbs == nil {
return []*Bone{}
}
bones := make([]*Bone, count)
cbones := unsafe.Slice(cbs, count)
for i := 0; i < int(count); i++ {
cBone := cbones[i]
bones[i] = &Bone{
Name: parseAiString(cBone.mName),
Weights: parseVertexWeights(cBone.mWeights, uint(cBone.mNumWeights)),
OffsetMatrix: parseMat4(&cBone.mOffsetMatrix),
}
}
return bones
}
func parseMat4(cm4 *C.struct_aiMatrix4x4) gglm.Mat4 {
return gglm.Mat4{
Data: [4][4]float32{
{float32(cm4.a1), float32(cm4.b1), float32(cm4.c1), float32(cm4.d1)},
{float32(cm4.a2), float32(cm4.b2), float32(cm4.c2), float32(cm4.d2)},
{float32(cm4.a3), float32(cm4.b3), float32(cm4.c3), float32(cm4.d3)},
{float32(cm4.a4), float32(cm4.b4), float32(cm4.c4), float32(cm4.d4)},
},
}
}
func parseVertexWeights(cWeights *C.struct_aiVertexWeight, count uint) []VertexWeight {
vw := make([]VertexWeight, count)
cvw := unsafe.Slice(cWeights, count)
for i := 0; i < int(count); i++ {
vw[i] = VertexWeight{
VertIndex: uint(cvw[i].mVertexId),
Weight: float32(cvw[i].mWeight),
}
}
return vw
}
func parseAiString(aiString C.struct_aiString) string {
return C.GoStringN(&aiString.data[0], C.int(aiString.length))
}
func parseUInts(cui *C.uint, count uint) []uint {
if cui == nil {
return []uint{}
}
uints := make([]uint, count)
cUInts := unsafe.Slice(cui, count)
for i := 0; i < len(cUInts); i++ {
uints[i] = uint(cUInts[i])
}
return uints
}
func parseVec3s(cv *C.struct_aiVector3D, count uint) []gglm.Vec3 {
if cv == nil {
return []gglm.Vec3{}
}
carr := unsafe.Slice(cv, count)
verts := make([]gglm.Vec3, count)
for i := 0; i < int(count); i++ {
verts[i] = gglm.Vec3{
Data: [3]float32{
float32(carr[i].x),
float32(carr[i].y),
float32(carr[i].z),
},
}
}
return verts
}
func parseColors(cv *C.struct_aiColor4D, count uint) []gglm.Vec4 {
carr := unsafe.Slice(cv, count)
verts := make([]gglm.Vec4, count)
for i := 0; i < int(count); i++ {
verts[i] = gglm.Vec4{
Data: [4]float32{
float32(carr[i].r),
float32(carr[i].g),
float32(carr[i].b),
float32(carr[i].a),
},
}
}
return verts
}

23
asig/enums.go Executable file
View File

@ -0,0 +1,23 @@
package asig
type PrimitiveType int32
//Specifies types of primitives that can be present in a mesh
const (
PrimitiveTypePoint = 1 << 0
PrimitiveTypeLine = 1 << 1
PrimitiveTypeTriangle = 1 << 2
PrimitiveTypePolygon = 1 << 3
)
type MorphMethod int32
//Supported methods of mesh morphing
const (
//Interpolation between morph targets
MorphMethodVertexBlend = 0x1
//Normalized morphing between morph targets
MorphMethodMorphNormalized = 0x2
//Relative morphing between morph targets
MorphMethodMorphRelative = 0x3
)

87
asig/mesh.go Executable file
View File

@ -0,0 +1,87 @@
package asig
import "github.com/bloeys/gglm/gglm"
const (
MaxColorSets = 8
MaxTexCoords = 8
)
type Mesh struct {
//Bitwise combination of PrimitiveType enum
PrimitiveTypes PrimitiveType
Vertices []gglm.Vec3
Normals []gglm.Vec3
Tangents []gglm.Vec3
BitTangents []gglm.Vec3
//ColorSets vertex color sets where each set is either empty or has length=len(Vertices), with max number of sets=MaxColorSets
ColorSets [MaxColorSets][]gglm.Vec4
//TexCoords (aka UV channels) where each TexCoords[i] has NumUVComponents[i] channels, and is either empty or has length=len(Vertices), with max number of TexCoords per vertex = MaxTexCoords
TexCoords [MaxTexCoords][]gglm.Vec3
TexCoordChannelCount [MaxTexCoords]uint
Faces []Face
Bones []*Bone
AnimMeshes []*AnimMesh
AABB AABB
MorphMethod MorphMethod
MaterialIndex uint
Name string
}
type Face struct {
Indices []uint
}
type AnimMesh struct {
Name string
/** Replacement for Mes.Vertices. If this array is non-NULL,
* it *must* contain mNumVertices entries. The corresponding
* array in the host mesh must be non-NULL as well - animation
* meshes may neither add or nor remove vertex components (if
* a replacement array is NULL and the corresponding source
* array is not, the source data is taken instead)*/
Vertices []gglm.Vec3
Normals []gglm.Vec3
Tangents []gglm.Vec3
BitTangents []gglm.Vec3
Colors [MaxColorSets][]gglm.Vec4
TexCoords [MaxTexCoords][]gglm.Vec3
Weight float32
}
type AABB struct {
Min gglm.Vec3
Max gglm.Vec3
}
type Bone struct {
Name string
//The influence weights of this bone
Weights []VertexWeight
/** Matrix that transforms from bone space to mesh space in bind pose.
*
* This matrix describes the position of the mesh
* in the local space of this bone when the skeleton was bound.
* Thus it can be used directly to determine a desired vertex position,
* given the world-space transform of the bone when animated,
* and the position of the vertex in mesh space.
*
* It is sometimes called an inverse-bind matrix,
* or inverse bind pose matrix.
*/
OffsetMatrix gglm.Mat4
}
type VertexWeight struct {
VertIndex uint
//The strength of the influence in the range (0...1). The total influence from all bones at one vertex is 1
Weight float32
}