mirror of
https://github.com/bloeys/assimp-go.git
synced 2025-12-29 08:28:20 +00:00
Full mesh parsing
This commit is contained in:
251
asig/asig.go
251
asig/asig.go
@ -10,17 +10,18 @@ package asig
|
|||||||
|
|
||||||
//Functions
|
//Functions
|
||||||
struct aiScene* aiImportFile(const char* pFile, unsigned int pFlags);
|
struct aiScene* aiImportFile(const char* pFile, unsigned int pFlags);
|
||||||
|
|
||||||
*/
|
*/
|
||||||
import "C"
|
import "C"
|
||||||
import "unsafe"
|
import (
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/bloeys/gglm/gglm"
|
||||||
|
)
|
||||||
|
|
||||||
type Node struct {
|
type Node struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type Mesh struct {
|
|
||||||
Vertices uint
|
|
||||||
}
|
|
||||||
|
|
||||||
type Material struct {
|
type Material struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -58,31 +59,259 @@ func ImportFile(file string, postProcessFlags uint) *Scene {
|
|||||||
|
|
||||||
cs := C.aiImportFile(cstr, C.uint(postProcessFlags))
|
cs := C.aiImportFile(cstr, C.uint(postProcessFlags))
|
||||||
scene := parseScene(cs)
|
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 {
|
func parseScene(cs *C.struct_aiScene) *Scene {
|
||||||
|
|
||||||
s := &Scene{}
|
s := &Scene{}
|
||||||
s.Meshes = parseMeshes(*cs.mMeshes, uint(cs.mNumMeshes))
|
s.Meshes = parseMeshes(cs.mMeshes, uint(cs.mNumMeshes))
|
||||||
|
|
||||||
return s
|
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)
|
meshes := make([]*Mesh, count)
|
||||||
cmeshes := unsafe.Slice(&cm, count)
|
cmeshes := unsafe.Slice(cm, count)
|
||||||
|
|
||||||
for i := 0; i < int(count); i++ {
|
for i := 0; i < int(count); i++ {
|
||||||
|
|
||||||
m := &Mesh{}
|
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
|
meshes[i] = m
|
||||||
}
|
}
|
||||||
|
|
||||||
return meshes
|
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
23
asig/enums.go
Executable 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
87
asig/mesh.go
Executable 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
|
||||||
|
}
|
||||||
2
go.mod
2
go.mod
@ -1,3 +1,5 @@
|
|||||||
module github.com/bloeys/assimp-go
|
module github.com/bloeys/assimp-go
|
||||||
|
|
||||||
go 1.17
|
go 1.17
|
||||||
|
|
||||||
|
require github.com/bloeys/gglm v0.2.6 // indirect
|
||||||
|
|||||||
2
go.sum
Executable file
2
go.sum
Executable file
@ -0,0 +1,2 @@
|
|||||||
|
github.com/bloeys/gglm v0.2.6 h1:+6m+GZuabU9GRhtEfqz7NS3fewO1xMcjJEenKVPRosM=
|
||||||
|
github.com/bloeys/gglm v0.2.6/go.mod h1:qwJQ0WzV191wAMwlGicbfbChbKoSedMk7gFFX6GnyOk=
|
||||||
12
main.go
12
main.go
@ -1,14 +1,22 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
"github.com/bloeys/assimp-go/asig"
|
"github.com/bloeys/assimp-go/asig"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|
||||||
scene := asig.ImportFile("obj.obj", 0)
|
scene := asig.ImportFile("obj.obj", 0)
|
||||||
println(scene)
|
|
||||||
// meshes := scene.MMeshes()
|
for i := 0; i < len(scene.Meshes); i++ {
|
||||||
|
|
||||||
|
println("Mesh:", i, "; Verts:", len(scene.Meshes[i].Vertices), "; Normals:", len(scene.Meshes[i].Normals))
|
||||||
|
for j := 0; j < len(scene.Meshes[i].Vertices); j++ {
|
||||||
|
fmt.Printf("V(%v): (%v, %v, %v)\n", j, scene.Meshes[i].Vertices[j].X(), scene.Meshes[i].Vertices[j].Y(), scene.Meshes[i].Vertices[j].Z())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// verts := meshes.Get(0).MVertices()
|
// verts := meshes.Get(0).MVertices()
|
||||||
// for i := 0; i < int(verts.Size()); i++ {
|
// for i := 0; i < int(verts.Size()); i++ {
|
||||||
|
|||||||
Reference in New Issue
Block a user