示例#1
0
        //TODO needs to be changed to account for single points
        /// <summary>
        /// Turns a bunch of random numbers into valid barycentric coordinates
        /// </summary>
        /// <param name="one"></param>
        /// <param name="two"></param>
        /// <param name="three"></param>
        /// <returns></returns>
        static string[] toBary(Bary b)
        {
            double[] bary =
            {
                1, 1, 1,
                1, 1, 1,
                1, 1, 1
            };
            //Points

            /*if (baryArr[index, 0] > 0 && baryArr[index, 4] <= 0 && baryArr[index, 5] <= 0)
             * {
             *
             *      bary[1] = 0;
             *      bary[4] = baryArr[index, 0];
             *      bary[7] = baryArr[index, 0];
             *
             * }
             *
             * if (baryArr[index, 1] > 0 && baryArr[index, 3] <= 0 && baryArr[index, 5] <= 0)
             * {
             *      bary[2] = baryArr[index, 1];
             *      bary[5] = 0;
             *      bary[8] = baryArr[index, 1];
             * }
             *
             * if (baryArr[index, 2] > 0 && baryArr[index, 3] <= 0 && baryArr[index, 4] <= 0)
             * {
             *      bary[0] = baryArr[index, 2];
             *      bary[3] = baryArr[index, 2];
             *      bary[6] = 0;
             * }*/
            //Lines
            if (b.l0 > 0)
            {
                bary[0] = b.l0;
                bary[3] = 0;
                bary[6] = 0;
            }

            if (b.l1 > 0)
            {
                bary[1] = 0;
                bary[4] = b.l1;
                bary[7] = 0;
            }

            if (b.l2 > 0)
            {
                bary[2] = 0;
                bary[5] = 0;
                bary[8] = b.l2;
            }
            string[] baryString = new string[3];
            for (int i = 0, c = 0; i < 9; i += 3, c++)
            {
                baryString[c] = bary[i] + "," + bary[i + 1] + "," + bary[i + 2] + ",";
            }
            return(baryString);
        }
示例#2
0
        static int nullBonesC = 0;         //TODO remove this counter

        public static void Main(string[] args)
        {
            //Dir
            if (Directory.Exists("./obj"))
            {
                Console.WriteLine("Directory Found");
            }
            else
            {
                printError("Creating Dir");
                Directory.CreateDirectory("./obj");
            }

            //File Input
            string fileName = "./obj/" + getUserInput("File name");

            if (fileName == "./obj/")
            {
                string[] possibleFiles = Directory.GetFiles("./obj");
                foreach (string currFileName in possibleFiles)
                {
                    if (!currFileName.EndsWith(".txt") && !currFileName.EndsWith(".js"))
                    {
                        fileName = currFileName;
                        break;
                    }
                }
            }
            else
            {
                string[] possibleFiles = Directory.GetFiles("./obj");
                foreach (string currFileName in possibleFiles)
                {
                    if (!currFileName.Contains("fileName"))
                    {
                        fileName = currFileName;
                        break;
                    }
                }
            }

            Console.WriteLine("Files found, starting to read them");

            try { File.Delete("./obj/output.txt"); }
            catch (Exception e)
            {
                printError("No file to delete, ignore this error" + e);
            }
            //Create a new importer
            AssimpContext importer = new AssimpContext();

            importer.SetConfig(new IFCUseCustomTriangulationConfig(true));

            importer.SetConfig(new SortByPrimitiveTypeConfig(PrimitiveType.Line | PrimitiveType.Point));
            importer.SetConfig(new VertexBoneWeightLimitConfig(4));
            //This is how we add a configuration (each config is its own class)
            //NormalSmoothingAngleConfig config = new NormalSmoothingAngleConfig(66.0f);
            //importer.SetConfig(config);

            //This is how we add a logging callback
            LogStream logstream = new LogStream(delegate(String msg, String userData)
            {
                Console.WriteLine(msg);
            });

            logstream.Attach();

            //Import the model. All configs are set. The model
            //is imported, loaded into managed memory. Then the unmanaged memory is released, and everything is reset.
            //Triangulating is already being done
            //TODO aiProcess_JoinIdenticalVertices (Index buffer objects)
            scene = importer.ImportFile(fileName, PostProcessPreset.TargetRealTimeMaximumQuality | PostProcessSteps.FlipUVs | PostProcessSteps.OptimizeMeshes | PostProcessSteps.OptimizeGraph | PostProcessSteps.SortByPrimitiveType | PostProcessSteps.LimitBoneWeights);

            extractBones(scene.RootNode);
            createBoneTree(scene.RootNode, -1, Matrix4x4.Identity);

            parseNode(scene.RootNode);
            //End of example
            importer.Dispose();
            adjVert = (Lookup <Vector3D, triAndVertIndex>)toLookup.ToLookup((item) => item.Key, (item) => item.Value);

            //First 3 => Point, Second 3 => Line
            //TODO Make this a bit better
            //For each triangle, store some bary coords
            Bary[] bary = new Bary[normals.Count];             //Filled with: default( int )
            //Edit

            #region Bary coords and bones
            //Lines:
            for (int j = 0; j < toLookup.Count; j += 3)
            {
                Vector3D v0   = toLookup[j + 2].Key - toLookup[j + 1].Key;
                Vector3D v1   = toLookup[j + 2].Key - toLookup[j].Key;
                Vector3D v2   = toLookup[j + 1].Key - toLookup[j].Key;
                double   area = Math.Abs(Vector3D.Cross(v1, v2).Length()) / 2;               //Determinant of a 2D matrix, used to calculate the area of a parallelogram


                IEnumerable <triAndVertIndex> matchingVertices0 = adjVert[toLookup[j].Key];
                IEnumerable <triAndVertIndex> matchingVertices1 = adjVert[toLookup[j + 1].Key];
                IEnumerable <triAndVertIndex> matchingVertices2 = adjVert[toLookup[j + 2].Key];
                //2 Matching points
                //TriIndex = triangle index of the adjacent triangle
                foreach (triAndVertIndex index in matchingVertices0)
                {
                    //Oh, yeah! It's working! (Magic!)
                    //TODO turn this into a function as well
                    foreach (triAndVertIndex otherIndex in matchingVertices1)
                    {
                        //If it is part of the same line
                        if (otherIndex.triIndex == index.triIndex)
                        {
                            double angleBetweenTriangles = (Vector3D.Dot(faceNormals[j / 3], faceNormals[otherIndex.triIndex]));
                            if (angleBetweenTriangles < THRESHOLD)
                            {
                                //area = 1/2*base*height
                                //2*area / base = height

                                /*
                                 * dist = vec3(area / v0.Length(), 0, 0);
                                 * gl_Position = gl_PositionIn[0];
                                 * EmitVertex();
                                 * dist = vec3(0, area / v1.Length(), 0);
                                 * gl_Position = gl_PositionIn[1];
                                 * EmitVertex();
                                 * dist = vec3(0, 0, area / v2.Length());
                                 * gl_Position = gl_PositionIn[2];
                                 * EmitVertex();*/
                                bary[j / 3].l2 = area / v2.Length();                                 // 1;// angleBetweenTriangles + addTo;
                            }
                            //If we found the adjacent triangle, we can go to the next one
                            break;
                        }
                    }
                }
                foreach (triAndVertIndex index in matchingVertices1)
                {
                    foreach (triAndVertIndex otherIndex in matchingVertices2)
                    {
                        if (otherIndex.triIndex == index.triIndex)
                        {
                            double angleBetweenTriangles = (Vector3D.Dot(faceNormals[j / 3], faceNormals[otherIndex.triIndex]));
                            if (angleBetweenTriangles < THRESHOLD)
                            {
                                bary[j / 3].l0 = area / v0.Length();                                // TODO angleBetweenTriangles + addTo;
                            }
                            break;
                        }
                    }
                }
                foreach (triAndVertIndex index in matchingVertices2)
                {
                    foreach (triAndVertIndex otherIndex in matchingVertices0)
                    {
                        if (otherIndex.triIndex == index.triIndex)
                        {
                            double angleBetweenTriangles = (Vector3D.Dot(faceNormals[j / 3], faceNormals[otherIndex.triIndex]));
                            if (angleBetweenTriangles < THRESHOLD)
                            {
                                bary[j / 3].l1 = area / v1.Length();                                // TODO angleBetweenTriangles + addTo;
                            }
                            break;
                        }
                    }
                }
            }

            //Draw the points as well
            for (int j = 0; j < toLookup.Count; j += 3)
            {
                Vector3D v0   = toLookup[j + 2].Key - toLookup[j + 1].Key;
                Vector3D v1   = toLookup[j + 2].Key - toLookup[j].Key;
                Vector3D v2   = toLookup[j + 1].Key - toLookup[j].Key;
                double   area = Math.Abs(Vector3D.Cross(v1, v2).Length()) / 2;               //Determinant of a 2D matrix, used to calculate the area of a parallelogram


                IEnumerable <triAndVertIndex> matchingVertices0 = adjVert[toLookup[j].Key];
                IEnumerable <triAndVertIndex> matchingVertices1 = adjVert[toLookup[j + 1].Key];
                IEnumerable <triAndVertIndex> matchingVertices2 = adjVert[toLookup[j + 2].Key];

                /*int numberOfAdjBary = 0;
                 *
                 * //Index of the adjacent triangle
                 * foreach (triAndVertIndex index in matchingVertices0)
                 * {
                 *      //TODO turn this into a function as well
                 *      if ((bary[index.triIndex], ((index.vertIndex + 1) % 3) + 3] > 0 || bary[index.triIndex, ((index.vertIndex + 2) % 3) + 3] > 0)
                 *              && index.triIndex != j / 3)
                 *      {
                 *              numberOfAdjBary++;
                 *      }
                 * }
                 * //Every line is actually 2 lines
                 * if (numberOfAdjBary >= 4)
                 * {
                 *      //Now, we need to do the point calculations
                 *      double dist0 = area / v0.Length();
                 *      //bary[j / 3, 0] = ;
                 * }
                 * numberOfAdjBary = 0;
                 * foreach (triAndVertIndex index in matchingVertices1)
                 * {
                 *      if ((bary[index.triIndex, ((index.vertIndex + 1) % 3) + 3] > 0 || bary[index.triIndex, ((index.vertIndex + 2) % 3) + 3] > 0)
                 *              && index.triIndex != j / 3)
                 *      {
                 *              numberOfAdjBary++;
                 *      }
                 * }
                 * if (numberOfAdjBary >= 4)
                 * {
                 *      bary[j / 3, 1] = area / v1.Length();
                 * }
                 * numberOfAdjBary = 0;
                 * foreach (triAndVertIndex index in matchingVertices2)
                 * {
                 *      if ((bary[index.triIndex, ((index.vertIndex + 1) % 3) + 3] > 0 || bary[index.triIndex, ((index.vertIndex + 2) % 3) + 3] > 0)
                 *              && index.triIndex != j / 3)
                 *      {
                 *              numberOfAdjBary++;
                 *      }
                 * }
                 * if (numberOfAdjBary >= 4)
                 * {
                 *      bary[j / 3, 2] = area / v2.Length();
                 * }***/
            }
            #endregion
#if true
            //Create the output file
            StreamWriter JSONFile = File.CreateText("./obj/output.txt");
            //Write to file
            JSONFile.Write("model = [");
            bool firstTime = true;
            for (int j = 0, texCount = 0; j < vertices.Count; j++)
            {
                var        index    = j - texCount;
                Vector3D[] currVert = Program.vertices[j];
                if (currVert.Length == 1)
                {
                    if (firstTime)
                    {
                        JSONFile.Write("{");
                        firstTime = false;
                    }
                    else
                    {
                        JSONFile.Write("]},\n{");
                    }
                    JSONFile.Write("name:\"" + texNames[(int)currVert[0].X] + "\",model:[");
                    Console.Write(texNames[(int)currVert[0].X] + "---");
                    texCount++;
                }
                else
                {
                    //Edit
                    string[] baryCoordsOfTri = toBary(bary[index]);
                    //Triangle
                    for (int i = 0; i < 3; i++)
                    {
                        JSONFile.Write(Vec3DToString(currVert[i]));
                        JSONFile.Write(UVToString(uvs[index][i]));
                        JSONFile.Write(Vec3DToString(normals[index][i]));

                        JSONFile.Write(baryCoordsOfTri[i]);
                        bones[index][i].Weights[1] = 0;
                        if (bones[index][i].BoneIDs[1] == -1)
                        {
                            bones[index][i].Weights[0] = 1;
                        }
                        if (bones[index][i].Weights[0] == 0.5)
                        {
                            bones[index][i].Weights[0] = 0.49f;
                        }
                        JSONFile.Write((bones[index][i].BoneIDs[0] + 0.5) + "," + (bones[index][i].BoneIDs[1] + 0.5)
                                       + "," + bones[index][i].Weights[0] + ",");

                        if (bones[index][i].Weights[0] > 0.45 && bones[index][i].Weights[0] < 0.55)
                        {
                            //printError("W1: " + string.Join(",.,", bones[index][i].Weights));
                        }

                        if (bones[index][i].Weights[0] > 0.9)
                        {
                            //printError("W1: " + string.Join(",.,", bones[index][i].Weights));
                        }
                    }
                }
            }


            JSONFile.Write("]}];");
            JSONFile.Close();
#endif

            StreamWriter bonesFile = File.CreateText("./obj/outputBones.txt");
            //You are going to have to reorder the parts manually
            bonesFile.Write("bones = [");

            foreach (BoneInfo boneNode in boneNodesList)
            {
                //TODO Number of bones (To nearest power of 2)
                //TODO Max number of influencing bones per vertex
                Quaternion rot, offsetRot;
                Vector3D   translation, offsetTranslation;
                Vector3D   scale, offsetScale;
                boneNode.localMat.Decompose(out scale, out rot, out translation);

                boneNode.BoneOffsetMatrix.Decompose(out offsetScale, out offsetRot, out offsetTranslation);
                //Console.WriteLine(QuaternionToString(rot) + "->\n" + MatToString1(rot.GetMatrix()));
                //Console.WriteLine(QuaternionToString(rot) + "->\n" + Matrix4x4.FromTranslation(translation));

                //Don't use .ToString(), use a custom function!
                bonesFile.WriteLine(
                    "{name:\"" + boneNode.Name + "\",parent:" + boneNode.Parent +
                    ",pos:[" + Vec3DToString(translation, false) + "],qRot:[" + QuaternionToString(rot) + "],offsetPos:["
                    + Vec3DToString(offsetTranslation, false) + "],offsetRot:[" + QuaternionToString(offsetRot) + "]},");
            }

            bonesFile.Write("];");
            bonesFile.WriteLine("\nvar animations = [];");
            bonesFile.Close();

            try { File.Delete("./obj/output.js"); } catch (Exception) { };
            try { File.Delete("./obj/outputBones.js"); } catch (Exception) { };
            try { File.Move("./obj/output.txt", Path.ChangeExtension("./obj/output.txt", ".js")); } catch (Exception) { };
            try { File.Move("./obj/outputBones.txt", Path.ChangeExtension("./obj/outputBones.txt", ".js")); } catch (Exception) { };

            Console.WriteLine("Info: {0} Bones    {1} vertices without bones", boneNodesList.Count, nullBonesC);
            Console.WriteLine("DONE!");
            Console.Read();
        }