Exemple #1
1
        public void Export(string filePath)
        {
            PalletProperties palletProperties = _palletSolution.Analysis.PalletProperties;

            COLLADA model = new COLLADA();
            // asset
            model.asset = new asset()
            {
                created = DateTime.Now,
                modified = DateTime.Now
            };
            model.asset.keywords = "StackBuilder Pallet Case";
            model.asset.title = _palletSolution.Title;
            model.asset.unit = new assetUnit() { name = "millimeters", meter = 0.001 };
            model.asset.up_axis = UpAxisType.Z_UP;

            library_images images = new library_images();
            library_materials materials = new library_materials();
            library_effects effects = new library_effects();
            library_geometries geometries = new library_geometries();
            library_nodes nodes = new library_nodes();
            library_cameras cameras = new library_cameras();
            library_animations animations = new library_animations();
            library_visual_scenes scenes = new library_visual_scenes();

            COLLADAScene colladaScene = new COLLADAScene();

            model.Items = new Object[] { images, materials, effects, geometries, nodes, cameras, animations, scenes };
            model.scene = colladaScene;

            // colors and materials
            List<effect> listEffects = new List<effect>();
            List<material> listMaterials = new List<material>();
            List<image> listImages = new List<image>();

            // effects
            effect effectPallet;
            material materialPallet;
            CreateMaterial(palletProperties.Color, null, null, "Pallet", out effectPallet, out materialPallet);
            listEffects.Add(effectPallet);
            listMaterials.Add(materialPallet);

            Box box = new Box(0, _palletSolution.Analysis.BProperties);

            // build list of effects / materials / images
            uint faceIndex = 0;
            foreach (Face face in box.Faces)
            {
                // build texture image if any
                string textureName = null;
                if (face.HasBitmap)
                {
                    textureName = string.Format("textureFace_{0}", faceIndex);
                    string texturePath = System.IO.Path.Combine(
                        System.IO.Path.GetDirectoryName(filePath)
                        , textureName + ".jpg");

                    double dimX = 0.0, dimY = 0.0;

                    switch (faceIndex)
                    {
                        case 0: dimX = box.Width; dimY = box.Height; break;
                        case 1: dimX = box.Width; dimY = box.Height; break;
                        case 2: dimX = box.Length; dimY = box.Height; break;
                        case 3: dimX = box.Length; dimY = box.Height; break;
                        case 4: dimX = box.Length; dimY = box.Width; break;
                        case 5: dimX = box.Length; dimY = box.Width; break;
                        default: break;
                    }
                    face.ExtractFaceBitmap(dimX, dimY, _bmpWidth, texturePath);
                    // create image
                    listImages.Add(
                        new image()
                        {
                            id = textureName + ".jpg",
                            name = textureName + ".jpg",
                            Item = @".\" + textureName + @".jpg"
                        }
                    );
                }
                material materialCase;
                effect effectCase;
                CreateMaterial(face.ColorFill, textureName, "0", string.Format("Case{0}", faceIndex), out effectCase, out materialCase);
                listEffects.Add(effectCase);
                listMaterials.Add(materialCase);

                ++faceIndex;
            }

            // add to image list
            images.image = listImages.ToArray();

            // case lines material
            effect effectCaseLines;
            material materialCaseLines;
            CreateMaterial(Color.Black, null, null, "CaseLines", out effectCaseLines, out materialCaseLines);
            listEffects.Add(effectCaseLines);
            listMaterials.Add(materialCaseLines);
            effects.effect = listEffects.ToArray();
            materials.material = listMaterials.ToArray();

            // geometries
            geometry geomPallet = new geometry() { id = "palletGeometry", name = "palletGeometry" };
            geometry geomCase = new geometry() { id = "caseGeometry", name = "caseGeometry" };
            geometries.geometry = new geometry[] { geomPallet, geomCase };
            // pallet
            mesh meshPallet = CreatePalletMesh(palletProperties);
            geomPallet.Item = meshPallet;
            // case
            mesh meshCase = CreateCaseMesh(_palletSolution.Analysis.BProperties as BoxProperties);
            geomCase.Item = meshCase;
            // library_animations
            animation animationMain = new animation() { id = "animationMain_ID", name = "animationMain" };
            animations.animation = new animation[] { animationMain };

            List<object> listAnimationSource = new List<object>();

            // library_visual_scenes
            visual_scene mainScene = new visual_scene() { id = "MainScene", name = "MainScene" };
            scenes.visual_scene = new visual_scene[] { mainScene };

            List<node> sceneNodes = new List<node>();
            sceneNodes.Add(new node()
            {
                id = "PalletNode",
                name = "PalletNode",
                instance_geometry = new instance_geometry[]
                {
                    new instance_geometry()
                    {
                        url = "#palletGeometry",
                        bind_material = new bind_material()
                        {
                            technique_common = new instance_material[]
                            {
                                new instance_material()
                                {
                                    symbol="materialPallet",
                                    target=string.Format("#{0}", materialPallet.id)
                                }
                            }
                        }
                    }
                }
            });
            uint caseIndex = 0;
            foreach (ILayer layer in _palletSolution)
            {
                BoxLayer bLayer = layer as BoxLayer;
                if (null == bLayer) continue;

                foreach (BoxPosition bp in bLayer)
                {
                    Vector3D translation = bp.Position;
                    Vector3D rotations = bp.Transformation.Rotations;

                    node caseNode = new node()
                    {
                        id = string.Format("CaseNode_{0}_ID", caseIndex),
                        name = string.Format("CaseNode_{0}", caseIndex),
                        ItemsElementName = new ItemsChoiceType2[]
                        {
                            ItemsChoiceType2.translate,
                            ItemsChoiceType2.rotate,
                            ItemsChoiceType2.rotate,
                            ItemsChoiceType2.rotate
                        },
                        Items = new object[]
                        {
                            new TargetableFloat3()
                            {
                                Values = new double[] { translation.X, translation.Y, translation.Z },
                                sid = "t",
                            },
                            new rotate()
                            {
                                Values = new double[] { 1.0, 0.0, 0.0, rotations.X },
                                sid = "rx"
                            },
                            new rotate()
                            {
                                Values = new double[] { 0.0, 1.0, 0.0, rotations.Y },
                                sid = "ry"
                            },
                            new rotate()
                            {
                                Values = new double[] { 0.0, 0.0, 1.0, rotations.Z },
                                sid = "rz"
                            } 
                        },

                        instance_geometry = new instance_geometry[]
                        {
                            new instance_geometry()
                            {
                                url="#caseGeometry",
                                bind_material = new bind_material()
                                {
                                    technique_common = new instance_material[]
                                    {
                                        new instance_material() { symbol="materialCase0", target="#material_Case0_ID" },
                                        new instance_material() { symbol="materialCase1", target="#material_Case1_ID" },
                                        new instance_material() { symbol="materialCase2", target="#material_Case2_ID" },
                                        new instance_material() { symbol="materialCase3", target="#material_Case3_ID" },
                                        new instance_material() { symbol="materialCase4", target="#material_Case4_ID" },
                                        new instance_material() { symbol="materialCase5", target="#material_Case5_ID" },
                                        new instance_material() { symbol="materialCaseLines", target="#material_CaseLines_ID"}
                                    }
                                }
                            }
                        }
                    };
                    sceneNodes.Add(caseNode);

                    // animations
                    CreateAnimation(caseIndex, (uint)_palletSolution.CaseCount, listAnimationSource, bp);

                    // increment case index
                    ++caseIndex;
                }
            }

            // add nodes
            mainScene.node = sceneNodes.ToArray();

            animationMain.Items = listAnimationSource.ToArray();

            // library_cameras
            camera cameraCamera = new camera() { id = "Camera-Camera", name = "Camera-Camera" };
            cameraOpticsTechnique_commonPerspective cameraPerspective = new cameraOpticsTechnique_commonPerspective()
            {
                znear = new TargetableFloat() { sid = "znear", Value = 1.0 },
                zfar = new TargetableFloat() { sid = "zfar", Value = 10000.0 }
            };
            cameraCamera.optics = new cameraOptics() { technique_common = new cameraOpticsTechnique_common() { Item = cameraPerspective } };
            cameras.camera = new camera[] { cameraCamera };

            // colladaScene
            colladaScene.instance_visual_scene = new InstanceWithExtra() { url = "#MainScene" };

            model.Save(filePath);
            model.Save(System.IO.Path.ChangeExtension(filePath, "xml"));
        }
        static ColladaSpline GetSpline(CL.UpAxisType up, CL.geometry geo)
        {
            var spline = geo.Item as CL.spline;

            if (spline == null)
            {
                return(null);
            }
            var conv = new ColladaSpline();
            Dictionary <string, float[]>        arrays  = new Dictionary <string, float[]>();
            Dictionary <string, GeometrySource> sources = new Dictionary <string, GeometrySource>();

            //Get arrays
            foreach (var acc in spline.source)
            {
                var arr = acc.Item as CL.float_array;
                arrays.Add(arr.id, FloatArray(arr.Text));
            }
            //Accessors
            foreach (var acc in spline.source)
            {
                sources.Add(acc.id, new GeometrySource(acc, arrays));
            }
            //Process spline

            /*foreach(var input in spline.control_vertices.input) {
             *  switch(input.semantic) {
             *
             *  }
             * }
             * spline.*/
            return(conv);
        }
Exemple #3
0
            CL.instance_material[] GetMaterials(CL.geometry g)
            {
                var materials = new List <CL.instance_material>();

                foreach (var item in ((CL.mesh)g.Item).Items)
                {
                    string matref = ((CL.triangles)item).material;
                    if (!materials.Any((m) => m.symbol == matref))
                    {
                        materials.Add(new CL.instance_material()
                        {
                            symbol = matref,
                            target = "#" + matref
                        });
                    }
                }
                return(materials.ToArray());
            }
        static ColladaGeometry GetGeometry(CL.UpAxisType up, CL.geometry geo, CL.library_materials matlib, CL.library_effects fxlib)
        {
            var conv = new ColladaGeometry()
            {
                FVF = D3DFVF.XYZ
            };

            conv.Name = string.IsNullOrEmpty(geo.name) ? geo.id : geo.name;
            var msh = geo.Item as CL.mesh;

            if (msh == null)
            {
                return(null);
            }
            List <VertexPositionNormalDiffuseTextureTwo> vertices = new List <VertexPositionNormalDiffuseTextureTwo>();
            List <int>             hashes                    = new List <int>();
            List <ushort>          indices                   = new List <ushort>();
            List <ColladaDrawcall> drawcalls                 = new List <ColladaDrawcall>();
            Dictionary <string, GeometrySource> sources      = new Dictionary <string, GeometrySource>();
            Dictionary <string, float[]>        arrays       = new Dictionary <string, float[]>();
            Dictionary <string, GeometrySource> verticesRefs = new Dictionary <string, GeometrySource>();
            int placeHolderIdx = 0;

            //Get arrays
            foreach (var acc in msh.source)
            {
                var arr = acc.Item as CL.float_array;
                arrays.Add(arr.id, FloatArray(arr.Text));
            }
            //Accessors
            foreach (var acc in msh.source)
            {
                sources.Add(acc.id, new GeometrySource(acc, arrays));
            }
            //Process geometry
            foreach (var item in msh.Items)
            {
                if (!(item is CL.triangles || item is CL.polylist || item is CL.polygons))
                {
                    FLLog.Warning("Collada", "Ignoring " + item.GetType().Name + " element.");
                }
            }
            int totalTriangles = 0;

            foreach (var item in msh.Items.Where(x => x is CL.triangles || x is CL.polylist || x is CL.polygons))
            {
                if (item is CL.triangles)
                {
                    totalTriangles += (int)((CL.triangles)item).count;
                }
                else if (item is CL.polylist plist)
                {
                    totalTriangles += (int)plist.count;
                }
                else
                {
                    totalTriangles += (int)((CL.polygons)item).count;
                }
            }
            if (totalTriangles > 21845)
            {
                throw new Exception(string.Format(
                                        "Overflow!\nCollada geometry {0} has {1} triangles\nVMeshData has limit of 21845",
                                        string.IsNullOrEmpty(geo.name) ? geo.id : geo.name,
                                        totalTriangles));
            }
            foreach (var item in msh.Items.Where(x => x is CL.triangles || x is CL.polylist || x is CL.polygons))
            {
                CL.InputLocalOffset[] inputs;
                int[]           pRefs;
                int             indexCount;
                string          materialRef;
                ColladaMaterial material;
                if (item is CL.triangles)
                {
                    var triangles = (CL.triangles)item;
                    indexCount  = (int)(triangles.count * 3);
                    pRefs       = IntArray(triangles.p);
                    inputs      = triangles.input;
                    materialRef = triangles.material;
                }
                else if (item is CL.polygons polygons)
                {
                    indexCount = (int)(polygons.count * 3);
                    int j = 0;
                    pRefs = new int[indexCount];
                    foreach (var arr in polygons.Items)
                    {
                        if (!(arr is string))
                        {
                            throw new Exception("Polygons: ph element unsupported");
                        }
                        var ints = IntArray((string)arr);
                        if (ints.Length != 3)
                        {
                            throw new Exception("Polygons: non-triangle geometry not supported");
                        }
                        pRefs[j]     = ints[0];
                        pRefs[j + 1] = ints[1];
                        pRefs[j + 2] = ints[2];
                        j           += 3;
                    }
                    inputs      = polygons.input;
                    materialRef = polygons.material;
                }
                else
                {
                    var plist = (CL.polylist)item;
                    pRefs = IntArray(plist.p);
                    foreach (var c in IntArray(plist.vcount))
                    {
                        if (c != 3)
                        {
                            throw new Exception("Polylist: non-triangle geometry");
                        }
                    }
                    materialRef = plist.material;
                    inputs      = plist.input;
                    indexCount  = (int)(plist.count * 3);
                }
                if (indexCount == 0)
                {
                    continue;                  //Skip empty
                }
                material = ParseMaterial(materialRef, matlib, fxlib);
                int pStride = 0;
                foreach (var input in inputs)
                {
                    pStride = Math.Max((int)input.offset, pStride);
                }
                pStride++;
                GeometrySource sourceXYZ = null; int offXYZ = int.MinValue;
                GeometrySource sourceNORMAL = null; int offNORMAL = int.MinValue;
                GeometrySource sourceCOLOR = null; int offCOLOR = int.MinValue;
                GeometrySource sourceUV1 = null; int offUV1 = int.MinValue;
                GeometrySource sourceUV2 = null; int offUV2 = int.MinValue;
                int            texCount = 0;
                int            startIdx = indices.Count;
                foreach (var input in inputs)
                {
                    switch (input.semantic)
                    {
                    case SEM_VERTEX:
                        if (CheckURI(input.source) != msh.vertices.id)
                        {
                            throw new Exception("VERTEX doesn't match mesh vertices");
                        }
                        foreach (var ip2 in msh.vertices.input)
                        {
                            switch (ip2.semantic)
                            {
                            case SEM_POSITION:
                                offXYZ    = (int)input.offset;
                                sourceXYZ = sources[CheckURI(ip2.source)];
                                break;

                            case SEM_NORMAL:
                                offNORMAL    = (int)input.offset;
                                sourceNORMAL = sources[CheckURI(ip2.source)];
                                conv.FVF    |= D3DFVF.NORMAL;
                                break;

                            case SEM_COLOR:
                                offCOLOR    = (int)input.offset;
                                sourceCOLOR = sources[CheckURI(ip2.source)];
                                conv.FVF   |= D3DFVF.DIFFUSE;
                                break;

                            case SEM_TEXCOORD:
                                if (texCount == 2)
                                {
                                    throw new Exception("Too many texcoords!");
                                }
                                if (texCount == 1)
                                {
                                    offUV2    = (int)input.offset;
                                    sourceUV2 = sources[CheckURI(ip2.source)];
                                    conv.FVF &= ~D3DFVF.TEX1;
                                    conv.FVF |= D3DFVF.TEX2;
                                }
                                else
                                {
                                    offUV1    = (int)input.offset;
                                    sourceUV1 = sources[CheckURI(ip2.source)];
                                    if ((conv.FVF & D3DFVF.TEX2) != D3DFVF.TEX2)
                                    {
                                        conv.FVF |= D3DFVF.TEX1;
                                    }
                                }
                                texCount++;
                                break;
                            }
                        }
                        break;

                    case SEM_POSITION:
                        offXYZ    = (int)input.offset;
                        sourceXYZ = sources[CheckURI(input.source)];
                        break;

                    case SEM_NORMAL:
                        offNORMAL    = (int)input.offset;
                        sourceNORMAL = sources[CheckURI(input.source)];
                        conv.FVF    |= D3DFVF.NORMAL;
                        break;

                    case SEM_COLOR:
                        offCOLOR    = (int)input.offset;
                        sourceCOLOR = sources[CheckURI(input.source)];
                        conv.FVF   |= D3DFVF.DIFFUSE;
                        break;

                    case SEM_TEXCOORD:
                        if (texCount == 2)
                        {
                            throw new Exception("Too many texcoords!");
                        }
                        if (texCount == 1)
                        {
                            offUV2    = (int)input.offset;
                            sourceUV2 = sources[CheckURI(input.source)];
                            conv.FVF &= ~D3DFVF.TEX1;
                            conv.FVF |= D3DFVF.TEX2;
                        }
                        else
                        {
                            offUV1    = (int)input.offset;
                            sourceUV1 = sources[CheckURI(input.source)];
                            if ((conv.FVF & D3DFVF.TEX2) != D3DFVF.TEX2)
                            {
                                conv.FVF |= D3DFVF.TEX1;
                            }
                        }
                        texCount++;
                        break;
                    }
                }
                int vertexOffset = vertices.Count;
                for (int i = 0; i < indexCount; i++)
                {
                    int idx  = i * pStride;
                    var vert = new VertexPositionNormalDiffuseTextureTwo(
                        VecAxis(up, sourceXYZ.GetXYZ(pRefs[idx + offXYZ])),
                        offNORMAL == int.MinValue ? Vector3.Zero : VecAxis(up, sourceNORMAL.GetXYZ(pRefs[idx + offNORMAL])),
                        offCOLOR == int.MinValue ? (uint)Color4.White.ToRgba() : (uint)sourceCOLOR.GetColor(pRefs[idx + offCOLOR]).ToRgba(),
                        offUV1 == int.MinValue ? Vector2.Zero : sourceUV1.GetUV(pRefs[idx + offUV1]),
                        offUV2 == int.MinValue ? Vector2.Zero : sourceUV2.GetUV(pRefs[idx + offUV2])
                        );
                    var hash    = HashVert(ref vert);
                    var vertIdx = FindDuplicate(hashes, vertices, vertexOffset, ref vert, hash);
                    if (indices.Count >= ushort.MaxValue)
                    {
                        throw new Exception("Too many indices");
                    }
                    if (vertIdx == -1)
                    {
                        if (vertices.Count + 1 >= ushort.MaxValue)
                        {
                            throw new Exception("Too many vertices");
                        }
                        indices.Add((ushort)(vertices.Count - vertexOffset));
                        vertices.Add(vert);
                        hashes.Add(hash);
                    }
                    else
                    {
                        indices.Add((ushort)(vertIdx - vertexOffset));
                    }
                }
                drawcalls.Add(new ColladaDrawcall()
                {
                    StartIndex  = startIdx,
                    StartVertex = vertexOffset,
                    EndVertex   = vertices.Count - 1,
                    TriCount    = (indices.Count - startIdx) / 3,
                    Material    = material
                });
            }
            conv.Indices   = indices.ToArray();
            conv.Vertices  = vertices.ToArray();
            conv.Drawcalls = drawcalls.ToArray();
            conv.CalculateDimensions();
            return(conv);
        }
        public static geometry MeshToGeometry(CPUMesh inputMesh, string id)
        {
            geometry outputGeometry = new geometry();
            mesh     outputMesh     = new mesh();

            outputGeometry.id   = id + "-lib";
            outputGeometry.name = inputMesh.name + "-mesh";
            outputGeometry.Item = outputMesh;


            //vertex Positions
            List <source> sourceList    = new List <source>();
            var           inputVertices = inputMesh.vertices;

            if (inputVertices.Length == 0)
            {
                return(null);
            }
            sourceList.Add(ArrayToSource(inputMesh.vertices, id + "-POSITION"));

            vertices vertexList = new vertices();

            vertexList.id                = id + "-VERTEX";
            vertexList.input             = new InputLocal[1];
            vertexList.input[0]          = new InputLocal();
            vertexList.input[0].semantic = "POSITION";
            vertexList.input[0].source   = "#" + sourceList[0].id;
            outputMesh.vertices          = vertexList;

            List <InputLocalOffset> offsetList = new List <InputLocalOffset>();

            {
                InputLocalOffset offset = new InputLocalOffset();
                offset.semantic = "VERTEX";
                offset.offset   = 0;
                offset.source   = "#" + vertexList.id;
                offsetList.Add(offset);
            }

            var inputNormals = inputMesh.normals;

            if (inputNormals.Length > 0)
            {
                var array = ArrayToSource(inputNormals, id + "-Normal0");
                InputLocalOffset offset = new InputLocalOffset();
                offset.semantic = "NORMAL";
                offset.offset   = (ulong)sourceList.Count;
                offset.source   = "#" + array.id;
                sourceList.Add(array);
                offsetList.Add(offset);
            }
            var inputUV1s = inputMesh.uv;

            if (inputUV1s.Length > 0)
            {
                var array = ArrayToSource(inputUV1s, id + "-UV0");
                InputLocalOffset offset = new InputLocalOffset();
                offset.semantic     = "TEXCOORD";
                offset.offset       = (ulong)sourceList.Count;
                offset.source       = "#" + array.id;
                offset.set          = 0;
                offset.setSpecified = true;
                sourceList.Add(array);
                offsetList.Add(offset);
            }
            var inputUV2s = inputMesh.uv2;

            if (inputUV2s.Length > 0)
            {
                var array = ArrayToSource(inputUV2s, id + "-UV1");
                InputLocalOffset offset = new InputLocalOffset();
                offset.semantic     = "TEXCOORD";
                offset.offset       = (ulong)sourceList.Count;
                offset.source       = "#" + array.id;
                offset.set          = 1;
                offset.setSpecified = true;
                sourceList.Add(array);
                offsetList.Add(offset);
            }
            var inputColors = inputMesh.colors;

            if (inputColors.Length > 0)
            {
                var array = ArrayToSource(inputColors, id + "-VERTEX_COLOR0");
                InputLocalOffset offset = new InputLocalOffset();
                offset.semantic     = "COLOR";
                offset.offset       = (ulong)sourceList.Count;
                offset.source       = "#" + array.id;
                offset.set          = 0;
                offset.setSpecified = true;
                sourceList.Add(array);
                offsetList.Add(offset);
            }

            outputMesh.source = sourceList.ToArray();


            triangles triangleList = new triangles();

            triangleList.input = offsetList.ToArray();

            var inputTriangles = inputMesh.triangles;

            triangleList.count = (ulong)inputTriangles.Length / 3;

            if (triangleList.count == 0)
            {
                return(null);
            }

            StringBuilder pString = new StringBuilder();

            for (int i = 0; i < inputTriangles.Length; i++)
            {
                for (int j = 0; j < triangleList.input.Length; j++)
                {
                    pString.Append(inputTriangles[i]).Append(" ");
                }
                if (i % 3 == 2)
                {
                    pString.AppendLine();
                }
                else
                {
                    pString.Append("   ");
                }
            }

            triangleList.p = pString.ToString();

            outputMesh.Items    = new object[1];
            outputMesh.Items[0] = triangleList;

            return(outputGeometry);
        }
        public static geometry MeshToGeometry(Mesh inputMesh)
        {
            string meshName = "Mesh-" + inputMesh.GetInstanceID();

            geometry outputGeometry = new geometry();
            mesh outputMesh = new mesh();

            outputGeometry.id = meshName + "-lib";
            outputGeometry.name = inputMesh.name + "-mesh";
            outputGeometry.Item = outputMesh;


            //vertex Positions
            List<source> sourceList = new List<source>();
            var inputVertices = inputMesh.vertices;
            if (inputVertices.Length == 0)
                return null;
            sourceList.Add(ArrayToSource(inputMesh.vertices, meshName + "-POSITION"));

            vertices vertexList = new vertices();
            vertexList.id = meshName + "-VERTEX";
            vertexList.input = new InputLocal[1];
            vertexList.input[0] = new InputLocal();
            vertexList.input[0].semantic = "POSITION";
            vertexList.input[0].source = "#" + sourceList[0].id;
            outputMesh.vertices = vertexList;

            List<InputLocalOffset> offsetList = new List<InputLocalOffset>();

            {
                InputLocalOffset offset = new InputLocalOffset();
                offset.semantic = "VERTEX";
                offset.offset = 0;
                offset.source = "#" + vertexList.id;
                offsetList.Add(offset);
            }

            var inputNormals = inputMesh.normals;
            if(inputNormals.Length > 0)
            {
                var array = ArrayToSource(inputNormals, meshName + "-Normal0");
                InputLocalOffset offset = new InputLocalOffset();
                offset.semantic = "NORMAL";
                offset.offset = (ulong)sourceList.Count;
                offset.source = "#" + array.id;
                sourceList.Add(array);
                offsetList.Add(offset);
            }
            var inputUV1s = inputMesh.uv;
            if (inputUV1s.Length > 0)
            {
                var array = ArrayToSource(inputUV1s, meshName + "-UV0");
                InputLocalOffset offset = new InputLocalOffset();
                offset.semantic = "TEXCOORD";
                offset.offset = (ulong)sourceList.Count;
                offset.source = "#" + array.id;
                offset.set = 0;
                offset.setSpecified = true;
                sourceList.Add(array);
                offsetList.Add(offset);
            }
            var inputUV2s = inputMesh.uv2;
            if (inputUV2s.Length > 0)
            {
                var array = ArrayToSource(inputUV2s, meshName + "-UV1");
                InputLocalOffset offset = new InputLocalOffset();
                offset.semantic = "TEXCOORD";
                offset.offset = (ulong)sourceList.Count;
                offset.source = "#" + array.id;
                offset.set = 1;
                offset.setSpecified = true;
                sourceList.Add(array);
                offsetList.Add(offset);
            }
            var inputColors = inputMesh.colors;
            if (inputColors.Length > 0)
            {
                var array = ArrayToSource(inputColors, meshName + "-VERTEX_COLOR0");
                InputLocalOffset offset = new InputLocalOffset();
                offset.semantic = "COLOR";
                offset.offset = (ulong)sourceList.Count;
                offset.source = "#" + array.id;
                offset.set = 0;
                offset.setSpecified = true;
                sourceList.Add(array);
                offsetList.Add(offset);
            }

            outputMesh.source = sourceList.ToArray();


            triangles triangleList = new triangles();
            triangleList.input = offsetList.ToArray();

            var inputTriangles = inputMesh.triangles;

            triangleList.count = (ulong)inputTriangles.Length / 3;

            if (triangleList.count == 0)
                return null;

            StringBuilder pString = new StringBuilder();

            for(int i = 0; i < inputTriangles.Length; i++)
            {
                for(int j = 0; j < triangleList.input.Length; j++)
                {
                    pString.Append(inputTriangles[i]).Append(" ");
                }
                if (i % 3 == 2)
                    pString.AppendLine();
                else
                    pString.Append("   ");
            }

            triangleList.p = pString.ToString();

            outputMesh.Items = new object[1];
            outputMesh.Items[0] = triangleList;

            return outputGeometry;
        }
        static ColladaGeometry GetGeometry(CL.UpAxisType up, CL.geometry geo)
        {
            var conv = new ColladaGeometry()
            {
                FVF = D3DFVF.XYZ
            };
            var msh = geo.Item as CL.mesh;

            if (msh == null)
            {
                return(null);
            }
            List <VertexPositionNormalDiffuseTextureTwo> vertices = new List <VertexPositionNormalDiffuseTextureTwo>();
            List <ushort>          indices                   = new List <ushort>();
            List <ColladaDrawcall> drawcalls                 = new List <ColladaDrawcall>();
            Dictionary <string, GeometrySource> sources      = new Dictionary <string, GeometrySource>();
            Dictionary <string, float[]>        arrays       = new Dictionary <string, float[]>();
            Dictionary <string, GeometrySource> verticesRefs = new Dictionary <string, GeometrySource>();

            //Get arrays
            foreach (var acc in msh.source)
            {
                var arr = acc.Item as CL.float_array;
                arrays.Add(arr.id, FloatArray(arr.Text));
            }
            //Accessors
            foreach (var acc in msh.source)
            {
                sources.Add(acc.id, new GeometrySource(acc, arrays));
            }
            //Process geometry
            if (msh.Items.Where(x => x is CL.triangles || x is CL.polylist).Count() != msh.Items.Length)
            {
                throw new Exception("Non-triangle geometry");
            }
            foreach (var item in msh.Items.Where(x => x is CL.triangles || x is CL.polylist))
            {
                CL.InputLocalOffset[] inputs;
                int[]  pRefs;
                int    triangleCount;
                string material;
                if (item is CL.triangles)
                {
                    var triangles = (CL.triangles)item;
                    pRefs         = IntArray(triangles.p);
                    inputs        = triangles.input;
                    triangleCount = (int)(triangles.count * 3);
                    material      = triangles.material;
                }
                else
                {
                    var plist = (CL.polylist)item;
                    pRefs = IntArray(plist.p);
                    foreach (var c in IntArray(plist.vcount))
                    {
                        if (c != 3)
                        {
                            throw new Exception("Polylist: non-triangle geometry");
                        }
                    }
                    material      = plist.material;
                    inputs        = plist.input;
                    triangleCount = (int)(plist.count * 3);
                }
                int pStride = 0;
                foreach (var input in inputs)
                {
                    pStride = Math.Max((int)input.offset, pStride);
                }
                pStride++;
                GeometrySource sourceXYZ = null; int offXYZ = int.MinValue;
                GeometrySource sourceNORMAL = null; int offNORMAL = int.MinValue;
                GeometrySource sourceCOLOR = null; int offCOLOR = int.MinValue;
                GeometrySource sourceUV1 = null; int offUV1 = int.MinValue;
                GeometrySource sourceUV2 = null; int offUV2 = int.MinValue;
                int            texCount = 0;
                int            startIdx = indices.Count;
                foreach (var input in inputs)
                {
                    switch (input.semantic)
                    {
                    case SEM_VERTEX:
                        if (CheckURI(input.source) != msh.vertices.id)
                        {
                            throw new Exception("VERTEX doesn't match mesh vertices");
                        }
                        foreach (var ip2 in msh.vertices.input)
                        {
                            switch (ip2.semantic)
                            {
                            case SEM_POSITION:
                                offXYZ    = (int)input.offset;
                                sourceXYZ = sources[CheckURI(ip2.source)];
                                break;

                            case SEM_NORMAL:
                                offNORMAL    = (int)input.offset;
                                sourceNORMAL = sources[CheckURI(ip2.source)];
                                conv.FVF    |= D3DFVF.NORMAL;
                                break;

                            case SEM_COLOR:
                                offCOLOR    = (int)input.offset;
                                sourceCOLOR = sources[CheckURI(ip2.source)];
                                conv.FVF   |= D3DFVF.DIFFUSE;
                                break;

                            case SEM_TEXCOORD:
                                if (texCount == 2)
                                {
                                    throw new Exception("Too many texcoords!");
                                }
                                if (texCount == 1)
                                {
                                    offUV2    = (int)input.offset;
                                    sourceUV2 = sources[CheckURI(ip2.source)];
                                    conv.FVF &= ~D3DFVF.TEX1;
                                    conv.FVF |= D3DFVF.TEX2;
                                }
                                else
                                {
                                    offUV1    = (int)input.offset;
                                    sourceUV1 = sources[CheckURI(ip2.source)];
                                    if ((conv.FVF & D3DFVF.TEX2) != D3DFVF.TEX2)
                                    {
                                        conv.FVF |= D3DFVF.TEX1;
                                    }
                                }
                                texCount++;
                                break;
                            }
                        }
                        break;

                    case SEM_POSITION:
                        offXYZ    = (int)input.offset;
                        sourceXYZ = sources[CheckURI(input.source)];
                        break;

                    case SEM_NORMAL:
                        offNORMAL    = (int)input.offset;
                        sourceNORMAL = sources[CheckURI(input.source)];
                        conv.FVF    |= D3DFVF.NORMAL;
                        break;

                    case SEM_COLOR:
                        offCOLOR    = (int)input.offset;
                        sourceCOLOR = sources[CheckURI(input.source)];
                        conv.FVF   |= D3DFVF.DIFFUSE;
                        break;

                    case SEM_TEXCOORD:
                        if (texCount == 2)
                        {
                            throw new Exception("Too many texcoords!");
                        }
                        if (texCount == 1)
                        {
                            offUV2    = (int)input.offset;
                            sourceUV2 = sources[CheckURI(input.source)];
                            conv.FVF &= ~D3DFVF.TEX1;
                            conv.FVF |= D3DFVF.TEX2;
                        }
                        else
                        {
                            offUV1    = (int)input.offset;
                            sourceUV1 = sources[CheckURI(input.source)];
                            if ((conv.FVF & D3DFVF.TEX2) != D3DFVF.TEX2)
                            {
                                conv.FVF |= D3DFVF.TEX1;
                            }
                        }
                        texCount++;
                        break;
                    }
                }
                for (int i = 0; i < triangleCount; i++)
                {
                    int idx  = i * pStride;
                    var vert = new VertexPositionNormalDiffuseTextureTwo(
                        VecAxis(up, sourceXYZ.GetXYZ(pRefs[idx + offXYZ])),
                        offNORMAL == int.MinValue ? Vector3.Zero : VecAxis(up, sourceNORMAL.GetXYZ(pRefs[idx + offNORMAL])),
                        offCOLOR == int.MinValue ? Color4.White : sourceCOLOR.GetColor(pRefs[idx + offCOLOR]),
                        offUV1 == int.MinValue ? Vector2.Zero : sourceUV1.GetUV(pRefs[idx + offUV1]),
                        offUV2 == int.MinValue ? Vector2.Zero : sourceUV2.GetUV(pRefs[idx + offUV2])
                        );
                    var vertIdx = vertices.IndexOf(vert);
                    if (indices.Count >= ushort.MaxValue)
                    {
                        throw new Exception("Too many indices");
                    }
                    if (vertIdx == -1)
                    {
                        if (vertices.Count + 1 >= ushort.MaxValue)
                        {
                            throw new Exception("Overflow");
                        }
                        indices.Add((ushort)vertices.Count);
                        vertices.Add(vert);
                    }
                    else
                    {
                        indices.Add((ushort)vertIdx);
                    }
                }
                drawcalls.Add(new ColladaDrawcall()
                {
                    Start    = startIdx,
                    TriCount = (indices.Count - startIdx) / 3,
                    Material = string.IsNullOrEmpty(material) ? "NullMaterial" : material
                });
            }
            conv.Indices   = indices.ToArray();
            conv.Vertices  = vertices.ToArray();
            conv.Drawcalls = drawcalls.ToArray();
            conv.CalculateDimensions();
            return(conv);
        }
Exemple #8
0
        static ExportModel ProcessModel(ModelFile mdl, ResourceManager resources)
        {
            mdl.Path = mdl.Path.Replace(' ', '_');
            var ex = new ExportModel();

            for (int midx = 0; midx < mdl.Levels.Length; midx++)
            {
                var lvl       = mdl.Levels[midx];
                var processed = ProcessRef(lvl, resources);
                var geo       = new CL.geometry();
                geo.name = geo.id = mdl.Path + "-level" + midx;
                var mesh = new CL.mesh();
                geo.Item = mesh;
                CL.source positions;
                CL.source normals = null;
                CL.source colors  = null;
                CL.source tex1    = null;
                CL.source tex2    = null;
                int       idxC    = 1;
                positions = CreateSource(
                    geo.name + "-positions",
                    (k) => new Vector4(processed.Vertices[k].Position, 0),
                    3, processed.Vertices.Length);
                mesh.vertices = new CL.vertices()
                {
                    id    = geo.name + "-vertices",
                    input = new CL.InputLocal[] { new CL.InputLocal()
                                                  {
                                                      semantic = "POSITION", source = "#" + positions.id
                                                  } }
                };
                var sources = new List <CL.source>()
                {
                    positions
                };
                if ((processed.FVF & D3DFVF.NORMAL) == D3DFVF.NORMAL)
                {
                    normals = CreateSource(
                        geo.name + "-normals",
                        (k) => new Vector4(processed.Vertices[k].Normal, 0),
                        3, processed.Vertices.Length);
                    sources.Add(normals);
                    idxC++;
                }
                if ((processed.FVF & D3DFVF.DIFFUSE) == D3DFVF.DIFFUSE)
                {
                    colors = CreateSource(
                        geo.name + "-color",
                        (k) =>
                    {
                        var c = Color4.FromRgba(processed.Vertices[k].Diffuse);
                        return(new Vector4(c.R, c.G, c.B, c.A));
                    }, 4, processed.Vertices.Length);
                    sources.Add(colors);
                    idxC++;
                }
                bool doTex1, doTex2 = false;
                if ((processed.FVF & D3DFVF.TEX2) == D3DFVF.TEX2)
                {
                    doTex1 = doTex2 = true;
                }
                else if ((processed.FVF & D3DFVF.TEX1) == D3DFVF.TEX1)
                {
                    doTex1 = true;
                }
                else
                {
                    doTex1 = doTex2 = false;
                }
                if (doTex1)
                {
                    tex1 = CreateSource(
                        geo.name + "-tex1",
                        (k) => new Vector4(processed.Vertices[k].TextureCoordinate, 0, 0),
                        2, processed.Vertices.Length);
                    sources.Add(tex1);
                    idxC++;
                }
                if (doTex2)
                {
                    tex2 = CreateSource(
                        geo.name + "-tex2",
                        (k) => new Vector4(processed.Vertices[k].TextureCoordinateTwo, 0, 0),
                        2, processed.Vertices.Length);
                    sources.Add(tex2);
                    idxC++;
                }
                mesh.source = sources.ToArray();
                var items = new List <object>();
                foreach (var dc in processed.Drawcalls)
                {
                    if (!ex.Materials.Any((x) => x.Name == dc.Material.Name))
                    {
                        ex.Materials.Add(dc.Material);
                    }
                    var trs = new CL.triangles();
                    trs.count    = (ulong)(dc.Indices.Length / 3);
                    trs.material = dc.Material.Name + "-material";
                    List <int> pRefs = new List <int>(dc.Indices.Length * idxC);
                    List <CL.InputLocalOffset> inputs = new List <CL.InputLocalOffset>()
                    {
                        new CL.InputLocalOffset()
                        {
                            semantic = "VERTEX", source = "#" + geo.id + "-vertices", offset = 0
                        }
                    };
                    ulong off = 1;
                    if (normals != null)
                    {
                        inputs.Add(new CL.InputLocalOffset()
                        {
                            semantic = "NORMAL",
                            source   = "#" + normals.id,
                            offset   = off++
                        });
                    }
                    if (colors != null)
                    {
                        inputs.Add(new CL.InputLocalOffset()
                        {
                            semantic = "COLOR",
                            source   = "#" + colors.id,
                            offset   = off++
                        });
                    }
                    if (tex1 != null)
                    {
                        inputs.Add(new CL.InputLocalOffset()
                        {
                            semantic = "TEXCOORD",
                            source   = "#" + tex1.id,
                            offset   = off++
                        });
                    }
                    if (tex2 != null)
                    {
                        inputs.Add(new CL.InputLocalOffset()
                        {
                            semantic = "TEXCOORD",
                            source   = "#" + tex2.id,
                            offset   = off++
                        });
                    }
                    trs.input = inputs.ToArray();
                    for (int i = 0; i < dc.Indices.Length; i++)
                    {
                        for (int j = 0; j < idxC; j++)
                        {
                            pRefs.Add(dc.Indices[i]);
                        }
                    }
                    trs.p = string.Join(" ", pRefs.ToArray());
                    items.Add(trs);
                }
                mesh.Items = items.ToArray();
                ex.Geometries.Add(geo);
            }
            return(ex);
        }