| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168 |
- // Copyright 2016 The G3N Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style
- // license that can be found in the LICENSE file.
- package collada
- import (
- "fmt"
- "github.com/g3n/engine/core"
- "github.com/g3n/engine/gls"
- "github.com/g3n/engine/graphic"
- "github.com/g3n/engine/material"
- "github.com/g3n/engine/math32"
- "strings"
- )
- func (d *Decoder) NewScene() (core.INode, error) {
- sc := d.dom.Scene
- if sc == nil {
- return nil, fmt.Errorf("No Scene element found")
- }
- ivs := sc.InstanceVisualScene
- if ivs == nil {
- return nil, fmt.Errorf("No InstanceVisualScene element found")
- }
- vs := findVisualScene(&d.dom, ivs.Url)
- if vs == nil {
- return nil, fmt.Errorf("VisualScene id:%s not found", ivs.Url)
- }
- // Creates parent scene
- scene := core.NewNode()
- // Rotate scene if necessary
- if d.dom.Asset.UpAxis == "Z_UP" {
- scene.SetRotationX(-math32.Pi / 2)
- }
- // Creates each node and adds it to the scene
- for _, n := range vs.Node {
- node, err := d.newNode(n)
- if err != nil {
- return nil, err
- }
- scene.Add(node)
- }
- return scene, nil
- }
- func (d *Decoder) newNode(cnode *Node) (core.INode, error) {
- var node core.INode
- switch nt := cnode.Instance.(type) {
- // Empty Node
- case nil:
- node = core.NewNode()
- // Geometry
- case *InstanceGeometry:
- // Get geometry instance
- geomi, gtype, err := d.GetGeometry(nt.Url)
- if err != nil {
- return nil, err
- }
- switch gtype {
- case gls.TRIANGLES:
- mesh := graphic.NewMesh(geomi, nil)
- geom := geomi.GetGeometry()
- // Associates the material in <bind_material> with the geometry group material
- for _, im := range nt.BindMaterial.TechniqueCommon.InstanceMaterial {
- matid := strings.TrimPrefix(im.Target, "#")
- for i := 0; i < geom.GroupCount(); i++ {
- group := geom.GroupAt(i)
- if group.Matid == matid {
- mat, err := d.GetMaterial(im.Target)
- if err != nil {
- return nil, err
- }
- mesh.AddGroupMaterial(mat, i)
- break
- }
- }
- }
- node = mesh
- case gls.POINTS:
- mat := material.NewPoint(math32.NewColor(0, 0, 0))
- mat.SetSize(1000)
- node = graphic.NewPoints(geomi, mat)
- case gls.LINES:
- mat := material.NewBasic()
- node = graphic.NewLines(geomi, mat)
- case gls.LINE_STRIP:
- mat := material.NewBasic()
- node = graphic.NewLineStrip(geomi, mat)
- default:
- return nil, fmt.Errorf("primitive not supported")
- }
- default:
- return nil, fmt.Errorf("instance geometry type:%T not supported", nt)
- }
- n := node.GetNode()
- n.SetLoaderID(cnode.Id)
- // Apply transformation elements to the node
- for _, tei := range cnode.TransformationElements {
- switch te := tei.(type) {
- case *Matrix:
- // Get math32.Matrix from the matrix data and
- // transpose to a column matrix
- var m math32.Matrix4
- m.FromArray(te.Data)
- m.Transpose()
- // Decompose the transformation matrix
- var position math32.Vector3
- var quaternion math32.Quaternion
- var scale math32.Vector3
- m.Decompose(&position, &quaternion, &scale)
- // Sets the node position, quaternion and scale
- n.SetPositionVec(&position)
- n.SetQuaternionQuat(&quaternion)
- n.SetScaleVec(&scale)
- case *Rotate:
- // Check angle of rotation
- if te.Data[3] == 0 {
- continue
- }
- var q math32.Quaternion
- axis := math32.Vector3{te.Data[0], te.Data[1], te.Data[2]}
- q.SetFromAxisAngle(&axis, math32.DegToRad(te.Data[3]))
- n.SetQuaternionQuat(&q)
- case *Scale:
- n.SetScale(te.Data[0], te.Data[1], te.Data[2])
- case *Translate:
- n.SetPosition(te.Data[0], te.Data[1], te.Data[2])
- default:
- return nil, fmt.Errorf("transformation element not supported")
- }
- }
- // Creates children nodes
- for _, child := range cnode.Node {
- c, err := d.newNode(child)
- if err != nil {
- return nil, err
- }
- n.Add(c)
- }
- return node, nil
- }
- func findVisualScene(dom *Collada, uri string) *VisualScene {
- id := strings.TrimPrefix(uri, "#")
- for _, vs := range dom.LibraryVisualScenes.VisualScene {
- if vs.Id == id {
- return vs
- }
- }
- return nil
- }
|