// 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 ( "encoding/xml" "fmt" "io" "strconv" ) // // Library Effects // type LibraryEffects struct { Id string Name string Asset *Asset Effect []*Effect } func (le *LibraryEffects) Dump(out io.Writer, indent int) { if le == nil { return } fmt.Fprintf(out, "%sLibraryEffects id:%s name:%s\n", sIndent(indent), le.Id, le.Name) for _, ef := range le.Effect { ef.Dump(out, indent+step) } } // // Effect // type Effect struct { Id string Name string Asset *Asset Profile []interface{} } func (ef *Effect) Dump(out io.Writer, indent int) { fmt.Printf("%sEffect id:%s name:%s\n", sIndent(indent), ef.Id, ef.Name) ind := indent + step for _, p := range ef.Profile { switch pt := p.(type) { case *ProfileCOMMON: pt.Dump(out, ind) break } } } // // Profile COMMON // type ProfileCOMMON struct { Id string Asset *Asset Newparam []*Newparam Technique struct { Id string Sid string Asset *Asset ShaderElement interface{} // Blinn|Constant|Lambert|Phong } } func (pc *ProfileCOMMON) Dump(out io.Writer, indent int) { fmt.Printf("%sProfileCOMMON id:%s\n", sIndent(indent), pc.Id) ind := indent + step for _, np := range pc.Newparam { np.Dump(out, ind) } fmt.Printf("%sTechnique id:%s sid:%s\n", sIndent(ind), pc.Technique.Id, pc.Technique.Sid) ind += step switch sh := pc.Technique.ShaderElement.(type) { case *Phong: sh.Dump(out, ind) break } } // // Newparam // type Newparam struct { Sid string Semantic string ParameterType interface{} } func (np *Newparam) Dump(out io.Writer, indent int) { fmt.Printf("%sNewparam sid:%s\n", sIndent(indent), np.Sid) ind := indent + step switch pt := np.ParameterType.(type) { case *Surface: pt.Dump(out, ind) case *Sampler2D: pt.Dump(out, ind) } } // // Surface // type Surface struct { Type string Init interface{} } func (sf *Surface) Dump(out io.Writer, indent int) { fmt.Printf("%sSurface type:%s\n", sIndent(indent), sf.Type) ind := indent + step switch it := sf.Init.(type) { case InitFrom: it.Dump(out, ind) } } // // Sampler2D // type Sampler2D struct { Source string } func (sp *Sampler2D) Dump(out io.Writer, indent int) { fmt.Printf("%sSampler2D\n", sIndent(indent)) ind := indent + step fmt.Printf("%sSource:%s\n", sIndent(ind), sp.Source) } // // Blinn // type Blinn struct { Emission interface{} Ambient interface{} Diffuse interface{} Specular interface{} Shininess interface{} Reflective interface{} Reflectivity interface{} Transparent interface{} Transparency interface{} IndexOfRefraction interface{} } func (bl *Blinn) Dump(out io.Writer, indent int) { fmt.Fprintf(out, "%sBlinn\n", sIndent(indent)) ind := indent + step DumpColorOrTexture("Emssion", bl.Emission, out, ind) DumpColorOrTexture("Ambient", bl.Ambient, out, ind) DumpColorOrTexture("Diffuse", bl.Diffuse, out, ind) DumpColorOrTexture("Specular", bl.Specular, out, ind) DumpFloatOrParam("Shininess", bl.Shininess, out, ind) DumpColorOrTexture("Reflective", bl.Reflective, out, ind) DumpFloatOrParam("Reflectivity", bl.Reflectivity, out, ind) DumpColorOrTexture("Transparent", bl.Transparent, out, ind) DumpFloatOrParam("Transparency", bl.Transparency, out, ind) DumpFloatOrParam("IndexOfRefraction", bl.IndexOfRefraction, out, ind) } // // Constant // type Constant struct { Emission interface{} Reflective interface{} Reflectivity interface{} Transparent interface{} Transparency interface{} IndexOfRefraction interface{} } // // Lambert // type Lambert struct { Emission interface{} Ambient interface{} Diffuse interface{} Reflective interface{} Reflectivity interface{} Transparent interface{} Transparency interface{} IndexOfRefraction interface{} } // // Phong // type Phong struct { Emission interface{} Ambient interface{} Diffuse interface{} Specular interface{} Shininess interface{} Reflective interface{} Reflectivity interface{} Transparent interface{} Transparency interface{} IndexOfRefraction interface{} } func (ph *Phong) Dump(out io.Writer, indent int) { fmt.Fprintf(out, "%sPhong\n", sIndent(indent)) ind := indent + step DumpColorOrTexture("Emission", ph.Emission, out, ind) DumpColorOrTexture("Ambient", ph.Ambient, out, ind) DumpColorOrTexture("Diffuse", ph.Diffuse, out, ind) DumpColorOrTexture("Specular", ph.Specular, out, ind) DumpFloatOrParam("Shininess", ph.Shininess, out, ind) DumpColorOrTexture("Reflective", ph.Reflective, out, ind) DumpFloatOrParam("Reflectivity", ph.Reflectivity, out, ind) DumpColorOrTexture("Transparent", ph.Transparent, out, ind) DumpFloatOrParam("Transparency", ph.Transparency, out, ind) DumpFloatOrParam("IndexOfRefraction", ph.IndexOfRefraction, out, ind) } func DumpColorOrTexture(name string, v interface{}, out io.Writer, indent int) { if v == nil { return } fmt.Fprintf(out, "%s%s\n", sIndent(indent), name) ind := indent + step switch vt := v.(type) { case *Color: vt.Dump(out, ind) case *Texture: vt.Dump(out, ind) } } func DumpFloatOrParam(name string, v interface{}, out io.Writer, indent int) { if v == nil { return } fmt.Fprintf(out, "%s%s\n", sIndent(indent), name) ind := indent + step switch vt := v.(type) { case *Float: vt.Dump(out, ind) break } } // // Color // type Color struct { Sid string Data [4]float32 } func (c *Color) Dump(out io.Writer, indent int) { fmt.Fprintf(out, "%sColor sid:%s data:%v\n", sIndent(indent), c.Sid, c.Data) } // // Float // type Float struct { Sid string Data float32 } func (f *Float) Dump(out io.Writer, indent int) { fmt.Fprintf(out, "%sFloat sid:%s data:%v\n", sIndent(indent), f.Sid, f.Data) } // // Texture // type Texture struct { Texture string Texcoord string } func (t *Texture) Dump(out io.Writer, indent int) { fmt.Fprintf(out, "%sTexture texture:%s texcoord:%v\n", sIndent(indent), t.Texture, t.Texcoord) } func (d *Decoder) decLibraryEffects(start xml.StartElement, dom *Collada) error { le := new(LibraryEffects) dom.LibraryEffects = le le.Id = findAttrib(start, "id").Value le.Name = findAttrib(start, "name").Value for { // Get next child element child, _, err := d.decNextChild(start) if err != nil || child.Name.Local == "" { return err } // Decodes if child.Name.Local == "effect" { err := d.decEffect(child, le) if err != nil { return err } continue } } return nil } func (d *Decoder) decEffect(start xml.StartElement, le *LibraryEffects) error { e := new(Effect) e.Id = findAttrib(start, "id").Value e.Name = findAttrib(start, "name").Value le.Effect = append(le.Effect, e) for { // Get next child element child, _, err := d.decNextChild(start) if err != nil || child.Name.Local == "" { return err } if child.Name.Local == "profile_COMMON" { err := d.decEffectProfileCommon(child, e) if err != nil { return err } continue } } return nil } func (d *Decoder) decEffectProfileCommon(start xml.StartElement, e *Effect) error { pc := new(ProfileCOMMON) pc.Id = findAttrib(start, "id").Value e.Profile = append(e.Profile, pc) for { // Get next child element child, _, err := d.decNextChild(start) if err != nil || child.Name.Local == "" { return err } if child.Name.Local == "newparam" { err := d.decProfileCommonNewparam(child, pc) if err != nil { return err } continue } if child.Name.Local == "technique" { err := d.decProfileCommonTechnique(child, pc) if err != nil { return err } continue } } return nil } func (d *Decoder) decProfileCommonNewparam(start xml.StartElement, pc *ProfileCOMMON) error { np := new(Newparam) np.Sid = findAttrib(start, "sid").Value pc.Newparam = append(pc.Newparam, np) for { child, _, err := d.decNextChild(start) if err != nil || child.Name.Local == "" { return err } if child.Name.Local == "surface" { err := d.decSurface(child, np) if err != nil { return err } continue } if child.Name.Local == "sampler2D" { err := d.decSampler2D(child, np) if err != nil { return err } continue } } return nil } func (d *Decoder) decSurface(start xml.StartElement, np *Newparam) error { sf := new(Surface) sf.Type = findAttrib(start, "type").Value np.ParameterType = sf for { child, data, err := d.decNextChild(start) if err != nil || child.Name.Local == "" { return err } if child.Name.Local == "init_from" { sf.Init = InitFrom{string(data)} continue } } return nil } func (d *Decoder) decSampler2D(start xml.StartElement, np *Newparam) error { sp := new(Sampler2D) np.ParameterType = sp for { child, data, err := d.decNextChild(start) if err != nil || child.Name.Local == "" { return err } if child.Name.Local == "source" { sp.Source = string(data) continue } } return nil } func (d *Decoder) decProfileCommonTechnique(start xml.StartElement, pc *ProfileCOMMON) error { pc.Technique.Id = findAttrib(start, "id").Value pc.Technique.Sid = findAttrib(start, "sid").Value for { child, _, err := d.decNextChild(start) if err != nil || child.Name.Local == "" { return err } if child.Name.Local == "blinn" { err := d.decBlinn(child, pc) if err != nil { return err } continue } if child.Name.Local == "constant" { log.Warn("CONSTANT not implemented yet") continue } if child.Name.Local == "lambert" { log.Warn("LAMBERT not implemented yet") continue } if child.Name.Local == "phong" { err := d.decPhong(child, pc) if err != nil { return err } continue } } return nil } func (d *Decoder) decBlinn(start xml.StartElement, pc *ProfileCOMMON) error { bl := new(Blinn) pc.Technique.ShaderElement = bl for { child, _, err := d.decNextChild(start) if err != nil || child.Name.Local == "" { return err } if child.Name.Local == "emission" { err := d.decColorOrTexture(child, &bl.Emission) if err != nil { return err } continue } if child.Name.Local == "ambient" { err := d.decColorOrTexture(child, &bl.Ambient) if err != nil { return err } continue } if child.Name.Local == "diffuse" { err := d.decColorOrTexture(child, &bl.Diffuse) if err != nil { return err } continue } if child.Name.Local == "specular" { err := d.decColorOrTexture(child, &bl.Specular) if err != nil { return err } continue } if child.Name.Local == "shininess" { err := d.decFloatOrParam(child, &bl.Shininess) if err != nil { return err } continue } if child.Name.Local == "reflective" { err := d.decFloatOrParam(child, &bl.Reflective) if err != nil { return err } continue } if child.Name.Local == "reflectivity" { err := d.decFloatOrParam(child, &bl.Reflectivity) if err != nil { return err } continue } if child.Name.Local == "transparent" { // not supported continue } if child.Name.Local == "transparency" { err := d.decFloatOrParam(child, &bl.Transparency) if err != nil { return err } continue } if child.Name.Local == "index_of_refraction" { err := d.decFloatOrParam(child, &bl.IndexOfRefraction) if err != nil { return err } continue } } return nil } func (d *Decoder) decPhong(start xml.StartElement, pc *ProfileCOMMON) error { ph := new(Phong) pc.Technique.ShaderElement = ph for { child, _, err := d.decNextChild(start) if err != nil || child.Name.Local == "" { return err } if child.Name.Local == "emission" { err := d.decColorOrTexture(child, &ph.Emission) if err != nil { return err } continue } if child.Name.Local == "ambient" { err := d.decColorOrTexture(child, &ph.Ambient) if err != nil { return err } continue } if child.Name.Local == "diffuse" { err := d.decColorOrTexture(child, &ph.Diffuse) if err != nil { return err } continue } if child.Name.Local == "specular" { err := d.decColorOrTexture(child, &ph.Specular) if err != nil { return err } continue } if child.Name.Local == "shininess" { err := d.decFloatOrParam(child, &ph.Shininess) if err != nil { return err } continue } if child.Name.Local == "reflective" { err := d.decFloatOrParam(child, &ph.Reflective) if err != nil { return err } continue } if child.Name.Local == "reflectivity" { err := d.decFloatOrParam(child, &ph.Reflectivity) if err != nil { return err } continue } if child.Name.Local == "transparent" { // not supported continue } if child.Name.Local == "transparency" { err := d.decFloatOrParam(child, &ph.Transparency) if err != nil { return err } continue } if child.Name.Local == "index_of_refraction" { err := d.decFloatOrParam(child, &ph.IndexOfRefraction) if err != nil { return err } continue } } return nil } func (d *Decoder) decColorOrTexture(start xml.StartElement, dest *interface{}) error { child, cdata, err := d.decNextChild(start) if err != nil || child.Name.Local == "" { return err } if child.Name.Local == "color" { c := &Color{} c.Sid = findAttrib(child, "sid").Value *dest = c var br bytesReader br.Init(cdata) idx := 0 for { tok := br.TokenNext() if tok == nil || len(tok) == 0 { break } v, err := strconv.ParseFloat(string(tok), 32) if err != nil { return err } c.Data[idx] = float32(v) idx++ } return nil } if child.Name.Local == "texture" { t := &Texture{} t.Texture = findAttrib(child, "texture").Value t.Texcoord = findAttrib(child, "texcoord").Value *dest = t return nil } if child.Name.Local == "param" { return fmt.Errorf("not supported") } return nil } func (d *Decoder) decFloatOrParam(start xml.StartElement, dest *interface{}) error { child, cdata, err := d.decNextChild(start) if err != nil || child.Name.Local == "" { return err } if child.Name.Local == "float" { f := &Float{} f.Sid = findAttrib(child, "sid").Value *dest = f v, err := strconv.ParseFloat(string(cdata), 32) if err != nil { return err } f.Data = float32(v) return nil } return nil }