Skip to content

Commit

Permalink
Adding support for collada triangles
Browse files Browse the repository at this point in the history
  • Loading branch information
wolfgarnet committed Jul 16, 2020
1 parent 391d397 commit 002283c
Show file tree
Hide file tree
Showing 2 changed files with 218 additions and 1 deletion.
177 changes: 176 additions & 1 deletion loader/collada/geometry.go
Expand Up @@ -308,7 +308,182 @@ func newMeshPolylist(m *Mesh, pels []interface{}) (*geometry.Geometry, uint32, e

func newMeshTriangles(m *Mesh, tr *Triangles) (*geometry.Geometry, uint32, error) {

return nil, 0, fmt.Errorf("not implemented yet")
// Get vertices positions
if len(m.Vertices.Input) != 1 {
return nil, 0, fmt.Errorf("Mesh.Vertices.Input length not supported")
}
vinp := m.Vertices.Input[0]
if vinp.Semantic != "POSITION" {
return nil, 0, fmt.Errorf("Mesh.Vertices.Input.Semantic:%s not supported", vinp.Semantic)
}

// Get vertices input source
inps := getMeshSource(m, vinp.Source)
if inps == nil {
return nil, 0, fmt.Errorf("Source:%s not found", vinp.Source)
}

// Get vertices input float array
// Ignore Accessor (??)
posArray, ok := inps.ArrayElement.(*FloatArray)
if !ok {
return nil, 0, fmt.Errorf("Mesh.Vertices.Input.Source not FloatArray")
}

// Creates buffers
positions := math32.NewArrayF32(0, 0)
normals := math32.NewArrayF32(0, 0)
uvs := math32.NewArrayF32(0, 0)
indices := math32.NewArrayU32(0, 0)

// Creates vertices attributes map for reusing indices
mVindex := make(map[[8]float32]uint32)
var index uint32
geomGroups := make([]geometry.Group, 0)
groupMatindex := 0

// Get VERTEX input
inpVertex := getInputSemantic(tr.Input, "VERTEX")
if inpVertex == nil {
return nil, 0, fmt.Errorf("VERTEX input not found")
}

// Get optional NORMAL input
inpNormal := getInputSemantic(tr.Input, "NORMAL")
var normArray *FloatArray
if inpNormal != nil {
// Get normals source
source := getMeshSource(m, inpNormal.Source)
if source == nil {
return nil, 0, fmt.Errorf("NORMAL source:%s not found", inpNormal.Source)
}
// Get normals source float array
normArray, ok = source.ArrayElement.(*FloatArray)
if !ok {
return nil, 0, fmt.Errorf("NORMAL source:%s not float array", inpNormal.Source)
}
}

// Get optional TEXCOORD input
inpTexcoord := getInputSemantic(tr.Input, "TEXCOORD")
var texArray *FloatArray
if inpTexcoord != nil {
// Get texture coordinates source
source := getMeshSource(m, inpTexcoord.Source)
if source == nil {
return nil, 0, fmt.Errorf("TEXCOORD source:%s not found", inpTexcoord.Source)
}
// Get texture coordinates source float array
texArray, ok = source.ArrayElement.(*FloatArray)
if !ok {
return nil, 0, fmt.Errorf("TEXCOORD source:%s not float array", inpTexcoord.Source)
}
}

// Initialize geometry group
groupStart := indices.Size()
// For each primitive index
inputCount := len(tr.Input)
for i := 0; i < len(tr.P); i += inputCount {
// Vertex attributes: position(3) + normal(3) + uv(2)
var vx [8]float32

// Vertex position
posIndex := tr.P[i+inpVertex.Offset] * 3
// Get position vector and appends to its buffer
vx[0] = posArray.Data[posIndex]
vx[1] = posArray.Data[posIndex+1]
vx[2] = posArray.Data[posIndex+2]

// Optional vertex normal
if inpNormal != nil {
// Get normal index from P
normIndex := tr.P[i+inpNormal.Offset] * 3
// Get normal vector and appends to its buffer
vx[3] = normArray.Data[normIndex]
vx[4] = normArray.Data[normIndex+1]
vx[5] = normArray.Data[normIndex+2]
}

// Optional vertex texture coordinate
if inpTexcoord != nil {
// Get normal index from P
texIndex := tr.P[i+inpTexcoord.Offset] * 2
// Get normal vector and appends to its buffer
vx[6] = texArray.Data[texIndex]
vx[7] = texArray.Data[texIndex+1]
}

// If this vertex and its attributes has already been appended,
// reuse it, adding its index to the index buffer
// to reuse its index
idx, ok := mVindex[vx]
if ok {
indices.Append(idx)
continue
}
// Appends new vertex position and attributes to its buffers
positions.Append(vx[0], vx[1], vx[2])
if inpNormal != nil {
normals.Append(vx[3], vx[4], vx[5])
}
if inpTexcoord != nil {
uvs.Append(vx[6], vx[7])
}
indices.Append(index)
// Save the index to this vertex position and attributes for
// future reuse
mVindex[vx] = index
index++
}
// Adds this geometry group to the list
geomGroups = append(geomGroups, geometry.Group{
Start: groupStart,
Count: indices.Size() - groupStart,
Matindex: groupMatindex,
Matid: tr.Material,
})

// Debug dump
//for i := 0; i < positions.Size()/3; i++ {
// vidx := i*3
// msg := fmt.Sprintf("i:%2d position:%v %v %v",
// i, positions.Get(vidx), positions.Get(vidx+1), positions.Get(vidx+2))
// if normals.Size() > 0 {
// msg += fmt.Sprintf("\tnormal:%v %v %v",
// normals.Get(vidx), normals.Get(vidx+1), normals.Get(vidx+2))
// }
// if uvs.Size() > 0 {
// msg += fmt.Sprintf("\tuv:%v %v", uvs.Get(i*2), uvs.Get(i*2+1))
// }
// log.Debug("%s", msg)
//}
//log.Debug("indices(%d):%v", indices.Size(), indices)
//log.Debug("groups:%v", geomGroups)

// Creates geometry
geom := geometry.NewGeometry()

// Creates VBO with vertex positions
geom.AddVBO(gls.NewVBO(positions).AddAttrib(gls.VertexPosition))

// Creates VBO with vertex normals
if normals.Size() > 0 {
geom.AddVBO(gls.NewVBO(normals).AddAttrib(gls.VertexNormal))
}

// Creates VBO with uv coordinates
if uvs.Size() > 0 {
geom.AddVBO(gls.NewVBO(uvs).AddAttrib(gls.VertexTexcoord))
}

// Sets the geometry indices buffer
geom.SetIndices(indices)

// Add material groups to the geometry
geom.AddGroupList(geomGroups)

return geom, gls.TRIANGLES, nil
}

func newMeshLines(m *Mesh, ln *Lines) (*geometry.Geometry, uint32, error) {
Expand Down
42 changes: 42 additions & 0 deletions loader/collada/library_geometries.go
Expand Up @@ -334,6 +334,14 @@ func (d *Decoder) decMesh(start xml.StartElement, geom *Geometry) error {
}
continue
}
// Decodes triangles
if child.Name.Local == "triangles" {
err = d.decTriangles(child, mesh)
if err != nil {
return err
}
continue
}
}
}

Expand Down Expand Up @@ -444,6 +452,40 @@ func (d *Decoder) decPolylist(start xml.StartElement, mesh *Mesh) error {
}
}

func (d *Decoder) decTriangles(start xml.StartElement, mesh *Mesh) error {
tr := &Triangles{}

tr.Name = findAttrib(start, "name").Value
tr.Count, _ = strconv.Atoi(findAttrib(start, "count").Value)
tr.Material = findAttrib(start, "material").Value
mesh.PrimitiveElements = append(mesh.PrimitiveElements, tr)

for {
// Get next child
child, data, err := d.decNextChild(start)
if err != nil || child.Name.Local == "" {
return err
}
// Decode input shared
if child.Name.Local == "input" {
inp, err := d.decInputShared(child)
if err != nil {
return err
}
tr.Input = append(tr.Input, inp)
continue
}
// Decode p (primitive)
if child.Name.Local == "p" {
p, err := d.decPrimitive(child, data)
if err != nil {
return err
}
tr.P = p
}
}
}

func (d *Decoder) decInputShared(start xml.StartElement) (InputShared, error) {

var inp InputShared
Expand Down

0 comments on commit 002283c

Please sign in to comment.