Example #1
0
        //逐点插入法2
        public Edge[] PointByPointInsertion()
        {
            EdgeSet      sEdgeSet     = new EdgeSet();
            TriangleSet  sTriangleSet = new TriangleSet();
            MinBoundRect sMBR         = this.mPointSet.MBR;
            double       width        = sMBR.MaxX - sMBR.MinX;
            double       height       = sMBR.MaxY - sMBR.MinY;
            double       middlePointX = (sMBR.MaxX + sMBR.MinX) / 2;
            double       middlePointY = sMBR.MinY;
            DataPoint    P0           = new DataPoint(-1, "P0", middlePointX - width, middlePointY, 0);
            DataPoint    P1           = new DataPoint(-2, "P1", middlePointX + width, middlePointY, 0);
            DataPoint    P2           = new DataPoint(-3, "P2", middlePointX, middlePointY + 2 * height, 0);
            Triangle     T0           = new Triangle(P0, P1, P2, -1);

            sTriangleSet.AddTriangle(T0);
            sEdgeSet.AddEdge(new Edge(P0, P1));
            sEdgeSet.AddEdge(new Edge(P1, P2));
            sEdgeSet.AddEdge(new Edge(P1, P0));
            foreach (var point in mPointSet.PointList)
            {
                Triangle CurTri = sTriangleSet.GetPointInsidesTri(point);
                if (CurTri != null)
                {
                }
            }
            return(sEdgeSet.EdgeList.ToArray());
        }
Example #2
0
 private void 逐点插入法ToolStripMenuItem_Click(object sender, EventArgs e)
 {
     //交互-格网与TIN
     if (逐点插入法ToolStripMenuItem.Checked == true)
     {
         //修改显示
         this.UserOperation = UserOperationType.DisplayInTIN;
         this.ShowTin       = true;
         this.显示隐藏TINToolStripMenuItem.Checked = true;
         CreateTIN createTin = new CreateTIN(this.mPointSet);
         Edge[]    tinEdges  = createTin.PointByPointInsertion2();
         Edge[]    tinEdges2 = createTin.GeneTIN().ToArray();
         TinEdges = tinEdges;
         TriangleSet triSet  = EdgeSet.TopologyGenerateTriangleSet(tinEdges, mPointSet);
         Triangle[]  triList = triSet.TriangleList.ToArray();
         TinContourLinePen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dash;
         agisControl.Refresh();
     }
     else
     {
         //修改显示
         this.UserOperation = UserOperationType.None;
         this.ShowTin       = false;
         this.显示隐藏TINToolStripMenuItem.Checked = false;
     }
 }
Example #3
0
    // FUNCTIONS
    /// <summary>
    /// Generate triangle array for a standard mesh consisting of rectangular cross sections.
    /// </summary>
    /// <param name="numCrossSections">Number of rectangular cross sections "framing" the mesh.</param>
    /// <returns>Array of integers, each set of 3 representing a triangle in the mesh.</returns>
    public static int[] getStandardMeshTriangles(int numCrossSections)
    {
        int         numVertices = numCrossSections * 4;
        TriangleSet triangleSet = new TriangleSet((numCrossSections - 1) * 8 + 4);

        // Form appropriate triangles for each set of two cross sections
        for (int i = 0; i < numCrossSections - 1; i++)
        {
            int vOffset = i * 4;

            // Top triangles
            triangleSet.pushTriangles(vOffset, vOffset + 4, vOffset + 5, vOffset + 1);

            // Bottom triangles
            triangleSet.pushTriangles(vOffset + 2, vOffset + 3, vOffset + 7, vOffset + 6);

            // Left triangles
            triangleSet.pushTriangles(vOffset, vOffset + 2, vOffset + 6, vOffset + 4);

            // Right triangles
            triangleSet.pushTriangles(vOffset + 1, vOffset + 5, vOffset + 7, vOffset + 3);
        }

        // Special case: front triangles on first cross section
        triangleSet.pushTriangles(0, 1, 3, 2);

        // Special case: rear triangles on last cross section
        triangleSet.pushTriangles(numVertices - 4, numVertices - 2, numVertices - 1, numVertices - 3);

        return(triangleSet.getTrianglePoints());
    }
Example #4
0
        /// <summary>
        /// Given a Triangle set, write the data to a file.
        /// </summary>
        /// <param name="output">The stream to write data to. Will be closed when method completed</param>
        /// <param name="data">The <TriangleSet> to output </param>
        public void WriteOutput(Stream output, TriangleSet data)
        {
            using (var sw = new StreamWriter(output))
            {
                sw.WriteLine($"{data.EarliestOriginYear},{data.NumberOfDevelopmentYears}");

                foreach (var t in data.Triangles)
                {
                    var stringBuilder = new StringBuilder(t.ProductName);

                    foreach (var year in t.Matrix.Keys)
                    {
                        stringBuilder.Append(",").Append(string.Join(",", t.Matrix[year].Select(x => x.ToString("###0.##"))));
                    }

                    sw.WriteLine(stringBuilder.ToString());
                }
            }
        }
Example #5
0
        public void Test_WhenCalculateCalled_ShouldOrWithMembership()
        {
            // Arrange
            FuzzySet antecedentSet = new TriangleSet(.5, .3, .3);

            antecedentSet.DegreeOfMembership = .7;
            Term antecedent = new SetProxy(antecedentSet);

            FuzzySet consequenceSet = new TriangleSet(.5, .3, .3);

            consequenceSet.DegreeOfMembership = 0;
            Term consequence = new SetProxy(consequenceSet);

            Rule rule = new Rule(antecedent, consequence);

            // Act
            rule.Calculate();

            // Assert
            Assert.AreEqual(.7, antecedent.Membership, .00001);
            Assert.AreEqual(.7, consequence.Membership, .00001);
        }
Example #6
0
        private void GetTriangleSet_LV3(Vector2 targetPosW, List <PosWeightPair> pairList, PosWeightPair pair1, PosWeightPair pair2, int startIndex, List <TriangleSet> resultTriList)
        {
            if (startIndex >= pairList.Count)
            {
                return;
            }

            PosWeightPair pair3 = null;

            for (int i = startIndex; i < pairList.Count; i++)
            {
                pair3 = pairList[i];

                //3개의 포인트가 다 모였다.
                //targetPosW를 기준으로 삼각형이 되는지 확인하자.
                bool isTriCondition = false;

                float angle12 = Vector2.Angle(pair1._posWorld - targetPosW, pair2._posWorld - targetPosW);
                float angle23 = Vector2.Angle(pair2._posWorld - targetPosW, pair3._posWorld - targetPosW);
                float angle31 = Vector2.Angle(pair3._posWorld - targetPosW, pair1._posWorld - targetPosW);

                float angleSum = angle12 + angle23 + angle31;
                if (Mathf.Abs(angleSum - 360.0f) < 2.0f)
                {
                    //대략 삼각형 안에 포인트가 있는 듯 하다.
                    isTriCondition = true;
                }

                if (!isTriCondition)
                {
                    continue;
                }

                //삼각형 메시를 구했다.
                TriangleSet newTriSet = new TriangleSet(pair1, pair2, pair3, targetPosW, angle12, angle23, angle31);
                resultTriList.Add(newTriSet);
            }
        }
Example #7
0
        /// <summary>
        /// Builds kdtree for specific patch.
        /// Kdtree is built according to specified positions type and hierarchy level.
        /// </summary>
        private static KdIntersectionTree BuildKdTreeForPatch(
            string patchName, int level, PatchFileInfo info, OpcPaths paths,
            PositionsType posType, bool saveTriangles = false, bool saveKdTree = true,
            float maxTriangleSize = float.PositiveInfinity)
        {
            var path = Path.Combine(paths.PatchesSubDir, patchName);

            var patchGeometry = new TriangleSet();

            //var patchGeometryTest = new TriangleSet();
            if ((maxTriangleSize < float.PositiveInfinity) && (maxTriangleSize > 0.000001f))
            {
                patchGeometry = PatchLoadingStrategy.LoadPatchTriangleSetWithoutOversizedTriangles(info, path, posType, maxTriangleSize);
                //patchGeometryTest = PatchLoadingStrategy.LoadPatchTriangleSet(info, path, posType);
            }
            else
            {
                patchGeometry = PatchLoadingStrategy.LoadPatchTriangleSet(info, path, posType);
            }

            KdIntersectionTree kdIntTree =
                new KdIntersectionTree(patchGeometry,
                                       KdIntersectionTree.BuildFlags.MediumIntersection |
                                       KdIntersectionTree.BuildFlags.Hierarchical);

            if (!saveTriangles)
            {
                kdIntTree.ObjectSet = null;
            }

            if (saveKdTree)
            {
                var kdTreePath = paths.GetKdTreePath(patchName, level, posType);
                kdIntTree.Save(kdTreePath);
            }

            return(kdIntTree);
        }
Example #8
0
        private void 生成等值线ToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            this.ShowContourLine = (this.生成等值线ToolStripMenuItem1.Checked == true);
            if (this.ShowContourLine == false)
            {
                this.agisControl.Refresh(); return;
            }
            ContourLineSettingForm settingForm = new ContourLineSettingForm();

            if (settingForm.ShowDialog(this) == DialogResult.OK)
            {
                //生成Tin
                CreateTIN createTin = new CreateTIN(this.mPointSet);
                Edge[]    tinEdges  = createTin.PointByPointInsertion2();
                TinEdges = tinEdges;
                TriangleSet triSet           = EdgeSet.TopologyGenerateTriangleSet(tinEdges, mPointSet);
                Triangle[]  triList          = triSet.TriangleList.ToArray();
                List <Edge> contourLinesList = new List <Edge>();
                //计算等值线条数
                int lineCount = (int)((settingForm.MaxValue - settingForm.MinValue) / settingForm.IntervalValue);
                for (int i = 0; i <= lineCount; i++)
                {
                    for (int j = 0; j < triList.Length; j++)
                    {
                        Edge contourLine = triList[j].GetContourLine(settingForm.MaxValue - i * settingForm.IntervalValue);
                        if (contourLine != null)
                        {
                            contourLinesList.Add(contourLine);
                        }
                    }
                    this.TinContourLineList = contourLinesList.ToArray();
                }
            }
            TinContourLinePen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dash;
            agisControl.Refresh();
        }
Example #9
0
        public bool Paste(apMeshGroup meshGroup, List <apModifiedVertexRig> targetModVertRigs)
        {
            if (meshGroup == null ||
                targetModVertRigs == null ||
                targetModVertRigs.Count == 0)
            {
                return(false);
            }
            if (_keyMeshGroup == null || _keyMeshGroup != meshGroup || _posWeightPairs.Count == 0)
            {
                return(false);
            }

            //Debug.LogError("Paste Start----");

            apModifiedVertexRig targetModVertRig = null;
            Vector2             targetPosW       = Vector2.zero;

            PosWeightPair src     = null;
            Vector2       srcPosW = Vector2.zero;

            PosWeightPair near_mX   = null;
            PosWeightPair near_pX   = null;
            PosWeightPair near_mY   = null;
            PosWeightPair near_pY   = null;
            float         minDst_mX = 0.0f;
            float         minDst_pX = 0.0f;
            float         minDst_mY = 0.0f;
            float         minDst_pY = 0.0f;
            float         dst       = 0.0f;

            //알고리즘 변경
            //1. 일단 -X, +X, -Y, +Y 방향으로 가장 가까운 포인트를 찾는다. (축값이 아닌 실제 Dst임)
            //2. 최대 4개의 포인트에 대하여 "최대 거리"를 구한다
            //3. 4개의 포인트를 포함하여 최대 거리 안에 포함된 포인트들을 리스트에 넣는다.
            //4. 포인트를 3개씩 묶어서 "삼각형"이 되어 이 점을 포함하는지 확인
            //5. "삼각형"이 되는 경우, 전체 Dist의 합이 가장 작은 삼각형을 선택한다.
            //6. 최적화된 삼각형을 찾은 상태에서 Barycentric 방식으로 보간한다.


            for (int iTarget = 0; iTarget < targetModVertRigs.Count; iTarget++)
            {
                targetModVertRig = targetModVertRigs[iTarget];
                targetPosW       = targetModVertRig._renderVertex._pos_World_NoMod;

                near_mX   = null;
                near_pX   = null;
                near_mY   = null;
                near_pY   = null;
                minDst_mX = 0.0f;
                minDst_pX = 0.0f;
                minDst_mY = 0.0f;
                minDst_pY = 0.0f;

                for (int iSrc = 0; iSrc < _posWeightPairs.Count; iSrc++)
                {
                    src     = _posWeightPairs[iSrc];
                    srcPosW = src._posWorld;

                    dst = Vector2.Distance(srcPosW, targetPosW);

                    if (srcPosW.x < targetPosW.x)
                    {
                        //-X에 대해서
                        if (dst < minDst_mX || near_mX == null)
                        {
                            near_mX   = src;
                            minDst_mX = dst;
                        }
                    }
                    else
                    {
                        //+X에 대해서
                        if (dst < minDst_pX || near_pX == null)
                        {
                            near_pX   = src;
                            minDst_pX = dst;
                        }
                    }

                    if (srcPosW.y < targetPosW.y)
                    {
                        //-Y에 대해서
                        if (dst < minDst_mY || near_mY == null)
                        {
                            near_mY   = src;
                            minDst_mY = dst;
                        }
                    }
                    else
                    {
                        //+Y에 대해서
                        if (dst < minDst_pY || near_pY == null)
                        {
                            near_pY   = src;
                            minDst_pY = dst;
                        }
                    }
                }

                //아주 가까운 점이 있다면 그 점을 그대로 대입한다.
                if (near_mX != null && near_mX.IsApproxPos(targetPosW))
                {
                    near_mX.PasteToModVertRig(meshGroup, targetModVertRig);
                    //Debug.Log(">> Case0 : 1개의 겹치는 점 대입");
                    continue;
                }
                if (near_pX != null && near_pX.IsApproxPos(targetPosW))
                {
                    near_pX.PasteToModVertRig(meshGroup, targetModVertRig);
                    //Debug.Log(">> Case0 : 1개의 겹치는 점 대입");
                    continue;
                }
                if (near_mY != null && near_mY.IsApproxPos(targetPosW))
                {
                    near_mY.PasteToModVertRig(meshGroup, targetModVertRig);
                    //Debug.Log(">> Case0 : 1개의 겹치는 점 대입");
                    continue;
                }
                if (near_pY != null && near_pY.IsApproxPos(targetPosW))
                {
                    near_pY.PasteToModVertRig(meshGroup, targetModVertRig);
                    //Debug.Log(">> Case0 : 1개의 겹치는 점 대입");
                    continue;
                }

                //2. 최대 4개의 포인트에 대하여 "최대 거리"를 구한다
                //3. 4개의 포인트를 포함하여 최대 거리 안에 포함된 포인트들을 리스트에 넣는다.


                List <PosWeightPair> pairList = new List <PosWeightPair>();
                float maxDist = 0.0f;

                if (near_mX != null)
                {
                    pairList.Add(near_mX); maxDist = Mathf.Max(minDst_mX, maxDist);
                }
                if (near_pX != null && !pairList.Contains(near_pX))
                {
                    pairList.Add(near_pX); maxDist = Mathf.Max(minDst_pX, maxDist);
                }
                if (near_mY != null && !pairList.Contains(near_mY))
                {
                    pairList.Add(near_mY); maxDist = Mathf.Max(minDst_mY, maxDist);
                }
                if (near_pY != null && !pairList.Contains(near_pY))
                {
                    pairList.Add(near_pY); maxDist = Mathf.Max(minDst_pY, maxDist);
                }

                if (pairList.Count < 3)
                {
                    maxDist *= 2;
                }
                //이제 다시 돌면서 maxDist 거리 안에 있는 모든 포인트를 리스트에 넣는다.
                for (int iSrc = 0; iSrc < _posWeightPairs.Count; iSrc++)
                {
                    src = _posWeightPairs[iSrc];

                    if (pairList.Contains(src))
                    {
                        //이미 추가되었다.
                        continue;
                    }
                    srcPosW = src._posWorld;

                    dst = Vector2.Distance(srcPosW, targetPosW);
                    if (dst < maxDist)
                    {
                        pairList.Add(src);
                    }
                }

                if (pairList.Count == 0)
                {
                    //1개도 없다면
                    continue;
                }

                if (pairList.Count == 1)
                {
                    //가까운 점이 1개라면
                    //그대로 대입
                    pairList[0].PasteToModVertRig(meshGroup, targetModVertRig);

                    //Debug.Log(">> Case1 : 1개의 점 대입");
                    continue;
                }

                PosWeightPair pairResult = new PosWeightPair();

                if (pairList.Count == 2)
                {
                    //4-1. 가까운 점이 2개라면
                    //두개의 거리 비로 계산한다.
                    PosWeightPair pairA = pairList[0];
                    PosWeightPair pairB = pairList[0];
                    float         dstA  = Vector2.Distance(pairA._posWorld, targetPosW);
                    float         dstB  = Vector2.Distance(pairB._posWorld, targetPosW);

                    if (dstA + dstB > 0.0f)
                    {
                        pairResult.Lerp(pairA, pairB, dstA / (dstA + dstB));
                    }
                    else
                    {
                        pairResult.Lerp(pairA, pairB, 0.5f);
                    }
                    pairResult.PasteToModVertRig(meshGroup, targetModVertRig);

                    //Debug.Log(">> Case2 : 2개의 점 대입");
                    continue;
                }
                //4-2. 포인트를 3개씩 묶어서 "삼각형"이 되어 이 점을 포함하는지 확인

                //Recursive 함수를 이용하자
                List <TriangleSet> triSet = GetTriangleSet_LV1(targetPosW, pairList, 0);

                if (triSet.Count == 0)
                {
                    //삼각형 메시에 포함되지 않았다면,
                    //가장 가까운 3개의 점을 보간하자
                    pairList.Sort(delegate(PosWeightPair a, PosWeightPair b)
                    {
                        float dstA = Vector2.Distance(a._posWorld, targetPosW);
                        float dstB = Vector2.Distance(b._posWorld, targetPosW);

                        return((int)((dstA - dstB) * 1000.0f));
                    });

                    pairResult.Interpolation3_NotTri(pairList[0], pairList[1], pairList[2], targetPosW);
                    pairResult.PasteToModVertRig(meshGroup, targetModVertRig);

                    //Debug.Log(">> Case3 : 삼각형이 안되는 3개의 점 대입");
                    continue;
                }

                //5. "삼각형"이 되는 경우, 전체 Dist의 합이 가장 작은 삼각형을 선택한다.
                TriangleSet minTriSet  = null;
                float       minTriSize = 0.0f;

                TriangleSet curTriSet = null;
                for (int iTri = 0; iTri < triSet.Count; iTri++)
                {
                    curTriSet = triSet[iTri];
                    if (minTriSet == null || curTriSet._totalDist < minTriSize)
                    {
                        minTriSet  = curTriSet;
                        minTriSize = curTriSet._totalDist;
                    }
                }

                //6. 최적화된 삼각형을 찾은 상태에서 Barycentric 방식으로 보간한다.
                minTriSet.CalculateBaryCentricWeights(targetPosW);
                pairResult.AddPosWeightPair(minTriSet._pair_A, minTriSet._baryCentricWeightA);
                pairResult.AddPosWeightPair(minTriSet._pair_B, minTriSet._baryCentricWeightB);
                pairResult.AddPosWeightPair(minTriSet._pair_C, minTriSet._baryCentricWeightC);
                pairResult.Normalize();

                pairResult.PasteToModVertRig(meshGroup, targetModVertRig);

                //Debug.Log(">> Case4 : 삼각형 보간 대입");
            }

            return(true);
        }
Example #10
0
    public static GameObject LoadModel(string fileName)
    {
        // If we get here, we're loading a custom model. If it's in the cache, return what's there.
        if (_cachedModels.ContainsKey(fileName))
        {
            return (GameObject)GameObject.Instantiate(_cachedModels[fileName]);
        }

        // If we get here, this is our first request for this filename. Load the mesh.
        // (We currently only support the Collada format)
        string meshFileName = CustomContentDirector.GetApplicationDataPath() + fileName;
        GameObject o = new GameObject(); // This will be the return value
        Debug.Log("Loading custom model " + meshFileName + "...");

        try
        {
            // Open a stream to the file
            using (FileStream fileStream = new FileStream(meshFileName, FileMode.Open))
            {
                // Load the stream into an Xml document parser
                XmlDocument doc = new XmlDocument();
                doc.Load(fileStream);

                // Now deserialize the document into a XmlCollada.XmlColladaSchema object. While
                // the naming could be better, this object allows easy access to all the components
                // in the Collada mesh.
                XmlCollada.XmlColladaSchema collada = new XmlCollada.XmlColladaSchema(doc);
                XmlCollada.Scene scene = collada.Scene;
                XmlCollada.Instance_Visual_Scene instanceVisualScene = scene.InstanceVisualScene;
                XmlCollada.Visual_Scene visualScene = collada.LibraryVisualScenes.GetVisualScene(instanceVisualScene.URL.Trim('#'));
                XmlCollada.XmlColladaList geometryNodeList = visualScene.GetInstanceGeometryNodes();
                // We don't support these; but when we decide to, these are here for us
                //XmlCollada.XmlColladaList materialNodeList = collada.LibraryMaterials.Materials;
                //XmlCollada.XmlColladaList imageNodeList = collada.LibraryImages.Images;

                // Navigate through the schema to build all geometries
                for (int i = 0; i < geometryNodeList.Count; i++)
                {
                    XmlCollada.Node node = (XmlCollada.Node)geometryNodeList.GetAt(i);
                    XmlCollada.XmlColladaList transforms = node.Transforms;
                    XmlCollada.Instance_Geometry instanceGeometry = node.InstanceGeometry;
                    XmlCollada.Geometry geometry = collada.LibraryGeometries.GetGeometry(instanceGeometry.URL.Trim('#'));
                    XmlCollada.Mesh colladaMesh = geometry.Mesh;
                    XmlCollada.XmlColladaList xmlGeometries = colladaMesh.GetXmlGeometries();

                    // Build a matrix based on all geometry transforms
                    for (int j = 0; j < transforms.Count; j++)
                    {
                        // TODO: Build a matrix based on the transforms
                    }

                    // Now load all the polygon lists
                    for (int j = 0; j < xmlGeometries.Count; j++)
                    {
                        XmlCollada.XmlGeometry xmlGeometry = (XmlCollada.XmlGeometry)xmlGeometries.GetAt(j);
                        XmlCollada.XmlColladaList inputs = xmlGeometry.GetInputs();
                        TriangleSet triangleSet = new TriangleSet();

                        // Create one Unity game object per polygon list
                        GameObject unityNode = new GameObject();
                        Mesh unityMesh = new Mesh();
                        unityNode.AddComponent<MeshFilter>().mesh = unityMesh;
                        unityNode.AddComponent<MeshRenderer>();
                        unityNode.transform.parent = o.transform;
                        unityNode.name = node.Name;

                        // Get the material (Currently unsuppoorted)
                        //string instanceMaterialTarget = node.InstanceGeometry.GetBoundMaterialTarget(xmlGeometry.Material);
                        //XmlCollada.Material material = collada.LibraryMaterials.GetMaterial(instanceMaterialTarget.Trim('#'));
                        //XmlCollada.Effect effect = collada.LibraryEffects.GetEffect(material._instanceEffect.URL.Trim('#'));
                        //XmlCollada.XmlShaderElement shader = effect.ProfileCommon.Technique.Shader;

                        // Now load recognized input components for this polygon list
                        Vector3[] vertices = null;
                        Vector3[] normals = null;
                        Vector2[] texcoords = null;
                        int verticesPOffset = -1;
                        int normalsPOffset = -1;
                        int texcoordsPOffset = -1;
                        int maxInputOffset = 0;
                        for (int k = 0; k < inputs.Count; k++)
                        {
                            XmlCollada.Input input = (XmlCollada.Input)inputs.GetAt(k);
                            if (input.Offset > maxInputOffset)
                            {
                                maxInputOffset = input.Offset;
                            }

                            XmlCollada.Source source;
                            if (input.Semantic == "VERTEX")
                            {
                                source = (XmlCollada.Source)colladaMesh.GetSource(colladaMesh.Vertices.Input.Source.Trim('#'));
                            }
                            else
                            {
                                source = (XmlCollada.Source)colladaMesh.GetSource(input.Source.Trim('#'));
                            }
                            XmlCollada.Float_Array floatArray = source.Float_Array;
                            XmlCollada.Technique_Common techniqueCommon = (XmlCollada.Technique_Common)source.Technique_Common;
                            XmlCollada.Accessor accessor = techniqueCommon.Accessor;
                            XmlCollada.XmlColladaList paramsList = accessor.GetParamsList();

                            // Calculate the number of named parameters
                            int namedParamCount = 0;
                            for (int l = 0; l < paramsList.Count; l++)
                            {
                                XmlCollada.Param param = (XmlCollada.Param)paramsList.GetAt(l);
                                if (param.Name.Length > 0)
                                {
                                    namedParamCount++;
                                }
                            }

                            // Build the coordinate list from all the accessor elements
                            float[] floatValues = new float[accessor.Count * namedParamCount];
                            int curFloatValue = 0;
                            for (int l = 0; l < accessor.Count; l++)
                            {
                                // Do for all parameters
                                int m0 = accessor.Offset + l * accessor.Stride;
                                for (int m = 0; m < paramsList.Count; m++)
                                {
                                    XmlCollada.Param param = (XmlCollada.Param)paramsList.GetAt(m);
                                    if (param.Name.Length > 0)
                                    {
                                        floatValues[curFloatValue++] = floatArray.Values[m0 + m];
                                    }
                                }
                            }

                            if (null == vertices && "VERTEX" == input.Semantic.ToUpper())
                            {
                                vertices = new Vector3[accessor.Count];
                                for (int l = 0; l < accessor.Count; l++)
                                {
                                    vertices[l] = new Vector3();
                                    vertices[l].x = floatValues[l * namedParamCount];
                                    if (namedParamCount > 1) { vertices[l].y = floatValues[l * namedParamCount + 1]; }
                                    if (namedParamCount > 2) { vertices[l].z = floatValues[l * namedParamCount + 2]; }
                                }
                                verticesPOffset = input.Offset;
                            }
                            else if (null == normals && "NORMAL" == input.Semantic.ToUpper())
                            {
                                normals = new Vector3[accessor.Count];
                                for (int l = 0; l < accessor.Count; l++)
                                {
                                    normals[l] = new Vector3();
                                    normals[l].x = floatValues[l * namedParamCount];
                                    if (namedParamCount > 1) { normals[l].y = floatValues[l * namedParamCount + 1]; }
                                    if (namedParamCount > 2) { normals[l].z = floatValues[l * namedParamCount + 2]; }
                                }
                                normalsPOffset = input.Offset;
                            }
                            else if (null == texcoords && "TEXCOORD" == input.Semantic.ToUpper())
                            {
                                texcoords = new Vector2[accessor.Count];
                                for (int l = 0; l < accessor.Count; l++)
                                {
                                    texcoords[l] = new Vector2();
                                    texcoords[l].x = floatValues[l * namedParamCount];
                                    if (namedParamCount > 1) { texcoords[l].y = floatValues[l * namedParamCount + 1]; }
                                }
                                texcoordsPOffset = input.Offset;
                            }
                        } // for (int k = 0; k < inputs.Count; k++)

                        // Now that all the input components (vertex lists) have been loaded, we load the actual face
                        // and index information. Loading is different for polygons and triangles.
                        if (xmlGeometry.root == "polylist" || xmlGeometry.root == "triangles")
                        {
                            // Make a first pass at reading in the polygons. Because there can be a different
                            // number of vertex indices than normal indices than UV indices, we have to create
                            // our own index group based on the unique pairs of those elements.
                            //
                            // Note: The stride of <p> is equal to one more than the highest input offset.
                            //
                            IndexGroupList indexGroupList = new IndexGroupList();
                            int[] vcounts = xmlGeometry.GetVCount();
                            int[] p = xmlGeometry.GetP();
                            int pIndex = 0;

                            // A triangle list is no different than a polygon list where the vcount is undefined. We'll make
                            // it up here and assign three vertices per triangle.
                            if (xmlGeometry.root == "triangles")
                            {
                                vcounts = new int[xmlGeometry.Count];
                                for (int k=0; k < xmlGeometry.Count; k++) {
                                    vcounts[k] = 3;
                                }
                            }

                            // Do for all elements in vcount (one element is one polygon)
                            for (int k = 0; k < vcounts.Length; k++)
                            {
                                int vertexCount = vcounts[k];
                                int[] polyVertIndices = new int[vertexCount];
                                int[] polyNormIndices = (normalsPOffset >= 0) ? new int[vertexCount] : null;
                                int[] polyTexIndices = (texcoordsPOffset >= 0) ? new int[vertexCount] : null;

                                // Do for all vertices for this polygon
                                for (int l = 0; l < vertexCount; l++)
                                {
                                    polyVertIndices[l] = p[pIndex + verticesPOffset];
                                    if (normalsPOffset >= 0) { polyNormIndices[l] = p[pIndex + normalsPOffset]; }
                                    if (texcoordsPOffset >= 0) { polyTexIndices[l] = p[pIndex + texcoordsPOffset]; }
                                    pIndex += maxInputOffset + 1;
                                }

                                // At this point we have all our indices; however we still have to deal with the disjointed
                                // nature of the indices (e.g. 8 vertex indices, 24 normal vertices). This is where our index
                                // group list comes in. Add every unique combination of vertex, normal, and uv indices into
                                // a single array, and build our triangle list while we're at it.
                                int[] triangleIndices = new int[(vertexCount - 2) * 3];
                                for (int l = 0; l < vertexCount - 2; l++)
                                {
                                    triangleIndices[l * 3] = indexGroupList.GetGroup(polyVertIndices[0], ((polyNormIndices != null) ? polyNormIndices[0] : -1), ((polyTexIndices != null) ? polyTexIndices[0] : -1));
                                    triangleIndices[l * 3 + 1] = indexGroupList.GetGroup(polyVertIndices[l + 1], ((polyNormIndices != null) ? polyNormIndices[l + 1] : -1), ((polyTexIndices != null) ? polyTexIndices[l + 1] : -1));
                                    triangleIndices[l * 3 + 2] = indexGroupList.GetGroup(polyVertIndices[l + 2], ((polyNormIndices != null) ? polyNormIndices[l + 2] : -1), ((polyTexIndices != null) ? polyTexIndices[l + 2] : -1));
                                }

                                // Add the triangles to the generic mesh
                                triangleSet.AddIndices(triangleIndices);
                            }

                            // Now we need to assign all the accumulated vertices, normals, and texcoords to the generic mesh
                            Vector3[] v = new Vector3[indexGroupList.Count];
                            Vector3[] n = (null != normals) ? new Vector3[indexGroupList.Count] : null;
                            Vector2[] uv = (null != texcoords) ? new Vector2[indexGroupList.Count] : null;
                            for (int k = 0; k < indexGroupList.Count; k++)
                            {
                                IndexGroup group = indexGroupList.GetGroup(k);
                                v[k] = vertices[group.vertIndex];
                                if (null != normals && group.normIndex >= 0) { n[k] = normals[group.normIndex]; }
                                if (null != texcoords && group.texcoordIndex >= 0) { uv[k] = texcoords[group.texcoordIndex]; }
                            }

                            unityMesh.vertices = v;
                            unityMesh.normals = n;
                            unityMesh.uv = uv;
                            unityMesh.triangles = triangleSet.indices;

                            // Assign a default material
                            unityNode.renderer.material = new Material(Shader.Find ("Diffuse"));
                            unityNode.renderer.material.color = new Color(0.3f,0.3f,0.3f,1);

                            // Now add the triangle set to the geometry
                            //genericMeshGeometry.AddTriangleSet(triangleSet);

                        } // if (xmlGeometry.root == "polylist" || xmlGeometry.root == "triangles")

                        //genericMesh.AddGeometry(genericMeshGeometry);
                    }

                } // for (int i = 0; i < geometryNodeList.Count; i++)

            }

            // Now add the mesh to our cache and return it
            o.name = "prefab_" + fileName;
            o.SetActiveRecursively(false);
            DontDestroyOnLoad(o);
            _cachedModels.Add(fileName, o);
        }
        catch (Exception e)
        {
            Debug.LogError(e.ToString());
        }
        return (GameObject)GameObject.Instantiate(o);
    }