예제 #1
0
        public static double Angle(XwVector v1, XwVector v0)
        {
            double lengthProduct = v0.Length() * v1.Length();

            double angle;

            if (lengthProduct == 0.0)
            {
                angle = 0.0;
            }
            else
            {
                double cos = XwVector.DotProduct(v1, v0) / lengthProduct;

                if (cos > 1.0)
                {
                    cos = 1.0;
                }
                else if (cos < -1.0)
                {
                    cos = -1.0;
                }

                angle = XwVector.AcosWithAtan2(cos);
            }

            return(angle);
        }
예제 #2
0
        public static double SubstractAndLength(XwVector v1, XwVector v0)
        {
            XwVector v;

            v = XwVector.Substract(v1, v0);
            return(v.Length());
        }
예제 #3
0
        public static XwVector Mean(XwVector v1, XwVector v0)
        {
            XwVector v;

            v = XwVector.Add(v1, v0);
            v = XwVector.Multiply(v, 0.5);
            return(v);
        }
예제 #4
0
        public static XwVector Add(XwVector v1, XwVector v0)
        {
            double x = v1.x + v0.x;
            double y = v1.y + v0.y;
            double z = v1.z + v0.z;

            return(new XwVector(x, y, z));
        }
예제 #5
0
        public static XwVector Substract(XwVector v1, XwVector v0)
        {
            double x = v1.x - v0.x;
            double y = v1.y - v0.y;
            double z = v1.z - v0.z;

            return(new XwVector(x, y, z));
        }
예제 #6
0
        public static XwVector Multiply(XwVector v0, double value)
        {
            double x = v0.x * value;
            double y = v0.y * value;
            double z = v0.z * value;

            return(new XwVector(x, y, z));
        }
예제 #7
0
        public static XwVector CrossProduct(XwVector v0, XwVector v1)
        {
            double x = v0.y * v1.z - v0.z * v1.y;
            double y = v0.z * v1.x - v0.x * v1.z;
            double z = v0.x * v1.y - v0.y * v1.x;

            return(new XwVector(x, y, z));
        }
예제 #8
0
        public static XwVector NormalizeAndMultiply(XwVector v0, double value)
        {
            double length = v0.Length();

            if (length <= 0.0)
            {
                return(new XwVector(0.0, 0.0, 0.0));
            }
            else
            {
                return(XwVector.Multiply(v0, value / length));
            }
        }
예제 #9
0
        static int XwVectorsFindOrAdd(XwVector vector, IList <Vector> list)
        {
            Vector v = vector.ToOptVector();

            int index = 0;

            for (; index < list.Count; index++)
            {
                if (XwVector.NearEqual(vector, new XwVector(list[index])))
                {
                    break;
                }
            }

            if (index >= list.Count)
            {
                list.Add(v);
            }

            return(index);
        }
예제 #10
0
        static int XwVectorsFindOrAdd(Vector vector, IList <XwVector> list)
        {
            XwVector v = new XwVector(vector);

            int index = 0;

            for (; index < list.Count; index++)
            {
                if (XwVector.NearEqual(v, list[index]))
                {
                    break;
                }
            }

            if (index >= list.Count)
            {
                list.Add(v);
            }

            return(index);
        }
예제 #11
0
 public static bool NearEqual(XwVector v1, XwVector v0)
 {
     return(XwVector.SubstractAndLength(v1, v0) < 0.0001);
 }
예제 #12
0
 public static double DotProduct(XwVector v1, XwVector v0)
 {
     return(v0.x * v1.x + v0.y * v1.y + v0.z * v1.z);
 }
예제 #13
0
        static void XwParseOpt(OptFile opt, int meshIndex, Face face, out XwVector outNormal, out double outAngle, out double outAngleSum)
        {
            var verticesVertex = new List <XwVector>(face.VerticesCount);
            var verticesLength = new List <double>(face.VerticesCount);
            var verticesAngle  = new List <double>(face.VerticesCount);

            for (int index = 0; index < face.VerticesCount; index++)
            {
                int      index2 = XwOptGetVertexIndex(index + 1, face.VerticesCount);
                XwVector v1     = new XwVector(opt.Meshes[meshIndex].Vertices[face.VerticesIndex.AtIndex(index)]);
                XwVector v0     = new XwVector(opt.Meshes[meshIndex].Vertices[face.VerticesIndex.AtIndex(index2)]);

                XwVector v = XwVector.Substract(v1, v0);

                verticesVertex.Add(v);
                verticesLength.Add(v.Length());
            }

            outAngleSum = 0.0;

            for (int index = 0; index < face.VerticesCount; index++)
            {
                int    index2 = XwOptGetVertexIndex(index - 1, face.VerticesCount);
                double angle  = XwVector.AngleRadianToDegree(XwVector.Angle(verticesVertex[index2], verticesVertex[index]));

                verticesAngle.Add(angle);
                outAngleSum += angle;
            }

            int maxLengthVertexIndex = 0;

            for (int index = 1; index < face.VerticesCount; index++)
            {
                if (verticesLength[maxLengthVertexIndex] < verticesLength[index])
                {
                    maxLengthVertexIndex = index;
                }
            }

            if (verticesLength[XwOptGetVertexIndex(maxLengthVertexIndex - 1, face.VerticesCount)] < verticesLength[XwOptGetVertexIndex(maxLengthVertexIndex + 1, face.VerticesCount)])
            {
                maxLengthVertexIndex = XwOptGetVertexIndex(maxLengthVertexIndex + 1, face.VerticesCount);
            }

            XwVector crossV0 = XwVector.Multiply(verticesVertex[XwOptGetVertexIndex(maxLengthVertexIndex - 1, face.VerticesCount)], -1.0);
            XwVector crossV1 = verticesVertex[maxLengthVertexIndex];
            XwVector normal  = XwVector.NormalizeAndMultiply(XwVector.CrossProduct(crossV0, crossV1), 1.0);

            XwVector ebpC8 = new XwVector(0.0, 0.0, 0.0);
            XwVector ebpD4 = new XwVector(0.0, 0.0, 0.0);
            XwVector ebpE0 = new XwVector(0.0, 0.0, 0.0);
            XwVector ebpEC = new XwVector(0.0, 0.0, 0.0);

            if (face.VerticesCount == 4)
            {
                maxLengthVertexIndex = XwOptGetVertexIndex(maxLengthVertexIndex + 2, face.VerticesCount);
                int index2 = XwOptGetVertexIndex(maxLengthVertexIndex - 1, face.VerticesCount);

                ebpC8 = XwVector.Multiply(verticesVertex[index2], -1.0);
                ebpD4 = verticesVertex[maxLengthVertexIndex];
                ebpE0 = XwVector.NormalizeAndMultiply(XwVector.CrossProduct(ebpC8, ebpD4), 1.0);
                ebpEC = XwVector.NormalizeAndMultiply(XwVector.Add(normal, ebpE0), 1.0);
            }

            outAngle  = XwVector.AngleRadianToDegree(XwVector.Angle(normal, new XwVector(face.Normal)));
            outNormal = normal;
        }
예제 #14
0
        static void XwOptComputing(OptFile opt, int selectedMeshIndex, double threshold)
        {
            int meshStart;
            int meshEnd;

            if (selectedMeshIndex < 0)
            {
                meshStart = 0;
                meshEnd   = opt.Meshes.Count;
            }
            else
            {
                meshStart = selectedMeshIndex;
                meshEnd   = meshStart + 1;

                if (meshStart >= opt.Meshes.Count)
                {
                    return;
                }
            }

            var ebp94             = new List <XwVector>();
            var ebp98_vertexIndex = new List <int>();
            var ebp9C_edgesIndex  = new List <Tuple <int, int> >();

            var ebpC8 = new List <List <Tuple <Face, Index, int> > >(); // face, vertexIndex, meshIndex

            int maxLodsCount = opt.Meshes
                               .Skip(meshStart)
                               .Take(meshEnd - meshStart)
                               .Max(t => t.Lods.Count);

            for (int i = 0; i < maxLodsCount; i++)
            {
                ebpC8.Add(new List <Tuple <Face, Index, int> >());
            }

            for (int meshIndex = meshStart; meshIndex < meshEnd; meshIndex++)
            {
                var mesh = opt.Meshes[meshIndex];

                ebp94.Clear();
                ebp98_vertexIndex.Clear();

                for (int i = 0; i < mesh.Vertices.Count; i++)
                {
                    ebp98_vertexIndex.Add(-1);
                }

                for (int lodIndex = 0; lodIndex < mesh.Lods.Count; lodIndex++)
                {
                    var lod = mesh.Lods[lodIndex];

                    for (int faceGroupIndex = 0; faceGroupIndex < lod.FaceGroups.Count; faceGroupIndex++)
                    {
                        ebp9C_edgesIndex.Clear();

                        var faceGroup = lod.FaceGroups[faceGroupIndex];

                        ebp9C_edgesIndex.Clear();

                        for (int faceIndex = 0; faceIndex < faceGroup.Faces.Count; faceIndex++)
                        {
                            var face = faceGroup.Faces[faceIndex];

                            var faceTuple = Tuple.Create(face, Index.Empty, meshIndex);
                            ebpC8[lodIndex].Add(faceTuple);

                            XwVector normal;
                            double   angle;
                            double   angleSum;
                            XwParseOpt(opt, meshIndex, face, out normal, out angle, out angleSum);

                            // TODO
                            face.Normal = normal.ToOptVector();

                            Index item2 = Index.Empty;
                            Index vertexNormalsIndex = Index.Empty;

                            for (int vertexIndex = 0; vertexIndex < faceTuple.Item1.VerticesCount; vertexIndex++)
                            {
                                int ebp18 = faceTuple.Item1.VerticesIndex.AtIndex(vertexIndex);

                                if (ebp98_vertexIndex[ebp18] == -1)
                                {
                                    ebp98_vertexIndex[ebp18] = XwVectorsFindOrAdd(mesh.Vertices[ebp18], ebp94);
                                }

                                item2 = item2.SetAtIndex(vertexIndex, ebp98_vertexIndex[ebp18]);
                                vertexNormalsIndex = vertexNormalsIndex.SetAtIndex(vertexIndex, -1);
                            }

                            faceTuple = Tuple.Create(faceTuple.Item1, item2, faceTuple.Item3);
                            ebpC8[lodIndex][ebpC8[lodIndex].Count - 1] = faceTuple;

                            faceTuple.Item1.VertexNormalsIndex = vertexNormalsIndex;

                            Index edgesIndex = Index.Empty;

                            for (int vertexIndex = 0; vertexIndex < faceTuple.Item1.VerticesCount; vertexIndex++)
                            {
                                int ebp18;

                                if (faceTuple.Item1.VerticesCount - 1 == vertexIndex)
                                {
                                    ebp18 = 0;
                                }
                                else
                                {
                                    ebp18 = vertexIndex + 1;
                                }

                                Tuple <int, int> ebpDC = Tuple.Create(
                                    faceTuple.Item1.VerticesIndex.AtIndex(vertexIndex),
                                    faceTuple.Item1.VerticesIndex.AtIndex(ebp18));

                                edgesIndex = edgesIndex.SetAtIndex(vertexIndex, XwSetsFindOrAdd(ebpDC, ebp9C_edgesIndex));
                            }

                            faceTuple.Item1.EdgesIndex = edgesIndex;
                        }
                    }
                }

                mesh.VertexNormals.Clear();
            }

            for (int lodIndex = 0; lodIndex < maxLodsCount; lodIndex++)
            {
                for (int faceIndex = 0; faceIndex < ebpC8[lodIndex].Count; faceIndex++)
                {
                    var faceTuple = ebpC8[lodIndex][faceIndex];

                    Index vertexNormalsIndex = Index.Empty;

                    for (int vertexIndex = 0; vertexIndex < faceTuple.Item1.VerticesCount; vertexIndex++)
                    {
                        int index = faceTuple.Item2.AtIndex(vertexIndex);

                        XwVector normalSum = new XwVector(faceTuple.Item1.Normal);

                        for (int faceIndex2 = 0; faceIndex2 < ebpC8[lodIndex].Count; faceIndex2++)
                        {
                            if (faceIndex2 == faceIndex)
                            {
                                continue;
                            }

                            var faceTuple2 = ebpC8[lodIndex][faceIndex2];

                            for (int vertexIndex2 = 0; vertexIndex2 < faceTuple2.Item1.VerticesCount; vertexIndex2++)
                            {
                                if (faceTuple2.Item2.AtIndex(vertexIndex2) == index)
                                {
                                    double angle = XwVector.Angle(new XwVector(faceTuple.Item1.Normal), new XwVector(faceTuple2.Item1.Normal));

                                    if (XwVector.AngleRadianToDegree(angle) <= threshold)
                                    {
                                        normalSum = XwVector.Add(normalSum, new XwVector(faceTuple2.Item1.Normal));
                                    }
                                }
                            }
                        }

                        XwVector normal = XwVector.NormalizeAndMultiply(normalSum, 1.0);
                        vertexNormalsIndex = vertexNormalsIndex.SetAtIndex(vertexIndex, XwVectorsFindOrAdd(normal, opt.Meshes[faceTuple.Item3].VertexNormals));
                    }

                    faceTuple.Item1.VertexNormalsIndex = vertexNormalsIndex;
                }
            }
        }
예제 #15
0
        static int XwOptChecking(OptFile opt, int selectedMeshIndex)
        {
            int meshStart;
            int meshEnd;

            if (selectedMeshIndex < 0)
            {
                meshStart = 0;
                meshEnd   = opt.Meshes.Count;
            }
            else
            {
                meshStart = selectedMeshIndex;
                meshEnd   = meshStart + 1;

                if (meshStart >= opt.Meshes.Count)
                {
                    return(0);
                }
            }

            int facesCount = 0;

            for (int meshIndex = meshStart; meshIndex < meshEnd; meshIndex++)
            {
                var mesh = opt.Meshes[meshIndex];

                for (int lodIndex = 0; lodIndex < mesh.Lods.Count; lodIndex++)
                {
                    var lod = mesh.Lods[lodIndex];

                    for (int faceGroupIndex = 0; faceGroupIndex < lod.FaceGroups.Count; faceGroupIndex++)
                    {
                        var faceGroup = lod.FaceGroups[faceGroupIndex];

                        for (int faceIndex = 0; faceIndex < faceGroup.Faces.Count; faceIndex++)
                        {
                            var face = faceGroup.Faces[faceIndex];
                            facesCount++;

                            XwVector normal;
                            double   angle;
                            double   angleSum;
                            XwParseOpt(opt, meshIndex, face, out normal, out angle, out angleSum);

                            var sb = new StringBuilder();
                            sb.AppendFormat(CultureInfo.InvariantCulture, "M:{0} L:{1} B:{2} F:{3} [ ", meshIndex, lodIndex, faceGroupIndex, faceIndex);

                            for (int i = 0; i < face.VerticesCount; i++)
                            {
                                sb.AppendFormat(CultureInfo.InvariantCulture, "{0} ", face.VerticesIndex.AtIndex(i));
                            }

                            sb.Append("]");

                            if (Math.Abs(angleSum - 360.0) >= 2.0)
                            {
                                sb.AppendFormat(CultureInfo.InvariantCulture, " invalid {0}V face", face.VerticesCount);
                                Console.WriteLine(sb);

                                if (face.VerticesCount >= 4)
                                {
                                    double ebp50 = XwVector.SubstractAndLength(
                                        new XwVector(mesh.Vertices[face.VerticesIndex.AtIndex(0)]),
                                        new XwVector(mesh.Vertices[face.VerticesIndex.AtIndex(2)]));

                                    double ebp60 = XwVector.SubstractAndLength(
                                        new XwVector(mesh.Vertices[face.VerticesIndex.AtIndex(1)]),
                                        new XwVector(mesh.Vertices[face.VerticesIndex.AtIndex(3)]));

                                    int[] ebp134 = new int[3];
                                    int[] ebp1AC = new int[3];

                                    if (ebp60 >= ebp50)
                                    {
                                        for (int i = 0; i < 3; i++)
                                        {
                                            ebp134[i] = face.VerticesIndex.AtIndex(i);
                                            ebp1AC[i] = face.VerticesIndex.AtIndex(XwOptGetVertexIndex(i + 2, 4));
                                        }
                                    }
                                    else
                                    {
                                        for (int i = 0; i < 3; i++)
                                        {
                                            if (i < 2)
                                            {
                                                ebp134[i] = face.VerticesIndex.AtIndex(i);
                                            }
                                            else
                                            {
                                                ebp134[i] = face.VerticesIndex.AtIndex(3);
                                            }

                                            ebp1AC[i] = face.VerticesIndex.AtIndex(i + 1);
                                        }
                                    }
                                }
                            }
                            else if (Math.Abs(angle) > 80.0)
                            {
                                sb.AppendFormat(CultureInfo.InvariantCulture, " CW/CCW problem ? ({0:F1}°)", angle);
                                Console.WriteLine(sb);
                            }
                            else if (Math.Abs(angle) >= 2.0)
                            {
                                sb.AppendFormat(CultureInfo.InvariantCulture, " normal recomputed ! ({0:F1}°)", angle);
                                Console.WriteLine(sb);
                            }
                        }
                    }
                }
            }

            return(facesCount);
        }