utensil/lol-model-format

View on GitHub
lib/lol_model_format/dae/dae_model.rb

Summary

Maintainability
A
2 hrs
Test Coverage
module LolModelFormat
    module Dae
        class DaeModel

            def initialize(lol_model)
                @lol_model = lol_model
            end

            #COLLADA 
            def to_dae(model_name = nil)
                @model = {}

                positions = []
                normals = []
                tex_coords = []
                triangles = []
                weights = []
                vcount_array = []
                v_array = []

                @lol_model.skin_file.vertices.each_with_index do |v, i|
                    positions << v.position.x.to_f.round(4)
                    positions << v.position.y.to_f.round(4)
                    positions << v.position.z.to_f.round(4)

                    normals << v.normal.x.to_f.round(6)
                    normals << v.normal.y.to_f.round(6)
                    normals << v.normal.z.to_f.round(6)

                    tex_coords << v.tex_coords.x.to_f.round(6)
                    tex_coords << -v.tex_coords.y.to_f.round(6)

                    v.weights.to_a.each do |weight|
                       weights << weight.to_f.round(6)
                    end

                    vcount_array << 4

                    v_array << 4 * i
                    v_array << 4 * i + 1
                    v_array << 4 * i + 2
                    v_array << 4 * i + 3
                end
                
                @model["positions-array"] = positions.join " "
                @model["positions-array-size"] = positions.size

                @model["normals-array"] = normals.join " "
                @model["normals-array-size"] = normals.size

                @model["map-array"] = tex_coords.join " "
                @model["map-array-size"] = tex_coords.size

                @lol_model.skin_file.indices.each do |i|
                    1.upto 3 do
                        triangles << i
                    end                
                end

                @model["triangles-array"] = triangles.to_a.join " "

                #computedLen = ((triangleData.length) / cl_inputmap.length) / 3;
                # cl_inputmap: [VERTEX NORMAL TEXCOORD].size == 3
                @model["triangles-array-size"] = triangles.size / 9
                @model["texture-file-name"] = "#{model_name || 'texture'}.jpg" 

                @model["weights-array-size"] = weights.size
                @model["weights-array"] = weights.join ' '

                @model["vcount-array"] = vcount_array.join " "
                @model["v-array"] = v_array.join " "

                @model["vertex-weights-count"] = @lol_model.skin_file.vertices.size

                bone_trees, name_arrays = @lol_model.gen_bone_tree_from_skl

                puts JSON.pretty_generate(bone_trees)
                puts JSON.pretty_generate(name_arrays)

                @model["bone-tree"] = bone_trees
                @model["skeleton-names"] = name_arrays["root"]            
                @model["joints-name-array"] = @model["skeleton-names"].join ' '
                @model["joints-name-array-size"] = @model["skeleton-names"].size 

                bind_poses_array = []

                @model["skeleton-names"].each do |joint_name|
                    bind_poses_array += @lol_model.skeleton_file.bones[
                            # bone id remapping
                            @lol_model.remap_bone_index(
                                # bone name to bone original id
                                @lol_model.bone_name_to_index_map[joint_name]
                            )                            
                        ].transform.getInverse.getTransposed.to_a
                end

                #bone_name_to_index_map

                @model["bind-poses-array"] = bind_poses_array.join " "
                @model["bind-poses-array-size"] = bind_poses_array.size

                @model["bind-shape-matrix"] = "1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1"


                #@model["animations"] = []

                #["anm_bones"] = []

                @lol_model.static_skeleton

                @enable_animation = true



                #builder = Nokogiri::XML::Builder.new do |xml|
                #  xml.root {
                #    xml.products {
                #      xml.widget {
                #        xml.id_ "10"
                #        xml.name "Awesome widget"
                #      }
                #    }
                #  }
                #end
                #puts builder.to_xml

                haml_engine = Haml::Engine.new(File.read(File.expand_path('../model.dae.haml', __FILE__)), 
                    :attr_wrapper => '"', :format => :xhtml)

                haml_engine.render binding

                #· Bind Pose: visual_scenes node[type="JOINT"] matrix 
                #· Inverse Bind Pose: library_controllers controller skin source
                #· Bind Shape matrix: library_controllers controller skin bind_shape_matrix 
                #· Bone Weights: library_controllers controller skin vertex_weights 
                #· Time and Matrix for each key frame for a specific joint:
                #  library_animations animation#"joint’s name and “matrix”"

                # mesh: not visual_scenes instance_geometry
                # visual_scenes instance_controller 
                #doc = Nokogiri::XML(open(''))
                #doc.css("visual_scene > node:not([type='JOINT']) > instance_geometry")
                #instance_controller = doc.css("visual_scene > node:not([type='JOINT']) > instance_controller")
                #controller = doc.css("controller#{instance_controller.attr('url')}")
                #"geometry#{controller.css(' > skin').attr('source')}"
                #root_joint_node = nil
                #instance_controller.css('> skeleton').each do |skeleton|
                #    if node = doc.css("visual_scenes > node#{skeleton.text}")
                #        root_joint_node = node
                #    end
                #end
    #
                #controller.css(' > skin bind_shape_matrix')
                #joint_name_source = controller.css(' > skin > joints > input[semantic="JOINT"]').attr('source')
                #inv_bind_matrix_source_id = controller.css(' > skin > joints > input[semantic="INV_BIND_MATRIX"]').attr('source')
                #inv_bind_matrix_source = controller.css(" > skin > source#{inv_bind_matrix_source_id}" # float array
                #controller.css(' > skin > vertex_weights > input[semantic="WEIGHT"]').attr('source')
                #controller.css(' > skin > vertex_weights > vcount')
                #controller.css(' > skin > vertex_weights > v')
    #


                #Position = VertexPosition x (Bind Shape x Σ(MatrixPallette[n] x Weight[n]))
                #where 0<=n<4
                #MatrixPallette[n] = inverseBindPose[n] x worldTransforms[n]
                #worldTransforms[n] = BindPose[n] x worldTransforms[parent]

                #One major difference in the reading of a skinned mesh in comparison to a static
                #mesh in COLLADA is that when you find the mesh’s node representation in the
                #<visual_scenes> it will not have an <instance_geometry> child, it will instead
                #have an <instance_controller> child and finding the geometry for it requires a
                #bit of extra work. But it’s an important note because it’s an easy mistake to make.
                #Another note that I think deserves a mention, you may be thinking that if you
                #have the bind pose for a joint, then you can get the inverse bind pose by just
                #inversing it using a D3DXMatrixInverse() function etc, I have found that this is not
                #the case unfortunately, though I haven’t tested this too thoroughly. You shouldn’t
                #ever really need to make your own inverse bind pose anyway but I thought it was
                #still an important note.
            end
        end
    end
end