Ejemplo n.º 1
0
        public void Push_Tri(FaceVertex A, FaceVertex B, FaceVertex C, Model_Prefab_Transform[] transforms)
        {
            if (transforms != null)
            {
                foreach (var trans in transforms)
                {
                    switch (trans)
                    {
                    case Model_Prefab_Transform.Flip_X:
                    case Model_Prefab_Transform.Flip_Y:
                    case Model_Prefab_Transform.Flip_Z:
                        FaceVertex vA = A, vB = B, vC = C;
                        A = vA;
                        B = vC;
                        C = vB;
                        break;

                    default:
                        throw new NotImplementedException($"Model_Prefab_Transform: {Enum.GetName(typeof(Model_Prefab_Transform), trans)} is not yet implemented!");
                        break;
                    }
                }
            }

            this.Push(A, transforms);
            this.Push(B, transforms);
            this.Push(C, transforms);
        }
Ejemplo n.º 2
0
        private Vector3 ComputeNormal(FaceVertex v1, FaceVertex v2, FaceVertex v3)
        {
            Vector3 pos1 = Positions[v1.PositionIndex - 1];
            Vector3 pos2 = Positions[v2.PositionIndex - 1];
            Vector3 pos3 = Positions[v3.PositionIndex - 1];

            return(Vector3.Normalize(Vector3.Cross(pos1 - pos2, pos1 - pos3)));
        }
Ejemplo n.º 3
0
        private vec3 ComputeNormal(FaceVertex v1, FaceVertex v2, FaceVertex v3)
        {
            vec3 pos1 = Positions[v1.PositionIndex - 1];
            vec3 pos2 = Positions[v2.PositionIndex - 1];
            vec3 pos3 = Positions[v3.PositionIndex - 1];

            return(glm.normalize(vec3.Cross(pos1 - pos2, pos1 - pos3)));
        }
Ejemplo n.º 4
0
            public Face(FaceVertex v0, FaceVertex v1, FaceVertex v2, int smoothingGroup = -1)
            {
                Vertex0 = v0;
                Vertex1 = v1;
                Vertex2 = v2;

                SmoothingGroup = smoothingGroup;
            }
Ejemplo n.º 5
0
        /// <summary>
        /// Computes face adjacency for the whole mesh and stores it in the appropriate dictionaries.
        /// </summary>
        public void ComputeFaceAdjacency()
        {
            foreach (MeshFace face in mesh.Faces)
            {
                foreach (MeshVertex adjacent in face.AdjacentVertices())
                {
                    if (!FaceVertex.ContainsKey(face.Index))
                    {
                        FaceVertex.Add(face.Index, new List <int>()
                        {
                            adjacent.Index
                        });
                    }
                    else
                    {
                        FaceVertex[face.Index].Add(adjacent.Index);
                    }
                }

                foreach (MeshFace adjacent in face.AdjacentFaces())
                {
                    if (!FaceFace.ContainsKey(face.Index))
                    {
                        FaceFace.Add(face.Index, new List <int>()
                        {
                            adjacent.Index
                        });
                    }
                    else
                    {
                        FaceFace[face.Index].Add(adjacent.Index);
                    }
                }

                foreach (MeshEdge adjacent in face.AdjacentEdges())
                {
                    if (!FaceEdge.ContainsKey(face.Index))
                    {
                        FaceEdge.Add(face.Index, new List <int>()
                        {
                            adjacent.Index
                        });
                    }
                    else
                    {
                        FaceEdge[face.Index].Add(adjacent.Index);
                    }
                }
            }
        }
Ejemplo n.º 6
0
        public uint GetOrCreate(
            Dictionary <FaceVertex, uint> vertexMap,
            FastList <VertexPosTexNorm> vertices,
            FaceVertex key,
            FaceVertex adjacent1,
            FaceVertex adjacent2)
        {
            uint index;

            if (!vertexMap.TryGetValue(key, out index))
            {
                VertexPosTexNorm vertex = ConstructVertex(key, adjacent1, adjacent2);
                vertices.Add(vertex);
                index = checked ((uint)(vertices.Count - 1));
                vertexMap.Add(key, index);
            }

            return(index);
        }
Ejemplo n.º 7
0
        private VertexPositionNormalTexture ConstructVertex(FaceVertex key, FaceVertex adjacent1, FaceVertex adjacent2)
        {
            Vector3 position = Positions[key.PositionIndex - 1];
            Vector3 normal;

            if (key.NormalIndex == -1)
            {
                normal = ComputeNormal(key, adjacent1, adjacent2);
            }
            else
            {
                normal = Normals[key.NormalIndex - 1];
            }


            Vector2 texCoord = key.TexCoordIndex == -1 ? Vector2.Zero : TexCoords[key.TexCoordIndex - 1];

            return(new VertexPositionNormalTexture(position, normal, texCoord));
        }
Ejemplo n.º 8
0
        private VertexPosTexNorm ConstructVertex(FaceVertex key, FaceVertex adjacent1, FaceVertex adjacent2)
        {
            vec3 position = Positions[key.PositionIndex - 1];
            vec3 normal;

            if (key.NormalIndex == -1)
            {
                normal = ComputeNormal(key, adjacent1, adjacent2);
            }
            else
            {
                normal = Normals[key.NormalIndex - 1];
            }


            vec2 texCoord = key.TexCoordIndex == -1 ? vec2.Zero : TexCoords[key.TexCoordIndex - 1];

            return(new VertexPosTexNorm(position, texCoord, normal));
        }
Ejemplo n.º 9
0
        private ushort GetOrCreate(
            Dictionary <FaceVertex, ushort> vertexMap,
            List <VertexPositionNormalTexture> vertices,
            FaceVertex key,
            FaceVertex adjacent1,
            FaceVertex adjacent2)
        {
            ushort index;

            if (!vertexMap.TryGetValue(key, out index))
            {
                VertexPositionNormalTexture vertex = ConstructVertex(key, adjacent1, adjacent2);
                vertices.Add(vertex);
                index = checked ((ushort)(vertices.Count - 1));
                vertexMap.Add(key, index);
            }

            return(index);
        }
Ejemplo n.º 10
0
        private FaceVertex ParseFaceVertex(string vertexString)
        {
            var fields = vertexString.Split(new[] { '/' }, StringSplitOptions.None);

            var vertexIndex = fields[0].ParseInvariantInt();
            var faceVertex  = new FaceVertex(vertexIndex, 0, 0);

            if (fields.Length > 1)
            {
                var textureIndex = fields[1].Length == 0 ? 0 : fields[1].ParseInvariantInt();
                faceVertex.TextureIndex = textureIndex;
            }

            if (fields.Length > 2)
            {
                var normalIndex = fields.Length > 2 && fields[2].Length == 0 ? 0 : fields[2].ParseInvariantInt();
                faceVertex.NormalIndex = normalIndex;
            }

            return(faceVertex);
        }
            // Returns true on success, false if it was a degenerate triangle
            public bool AddTriangle(FaceVertex v0, FaceVertex v1, FaceVertex v2)
            {
                AddVertexResult vb_id_0 = m_addVertex(v0);
                AddVertexResult vb_id_1 = m_addVertex(v1);
                AddVertexResult vb_id_2 = m_addVertex(v2);

                // Degenerate check
                if (vb_id_0.CombinedVertexIndex == vb_id_1.CombinedVertexIndex ||
                    vb_id_0.CombinedVertexIndex == vb_id_2.CombinedVertexIndex ||
                    vb_id_1.CombinedVertexIndex == vb_id_2.CombinedVertexIndex)
                {
                    return(false);
                }

                m_combined_vertlist.Add(vb_id_0.CombinedVertexIndex);
                m_combined_vertlist.Add(vb_id_1.CombinedVertexIndex);
                m_combined_vertlist.Add(vb_id_2.CombinedVertexIndex);

                m_submesh_vertlist.Add(vb_id_0.SubmeshVertexIndex);
                m_submesh_vertlist.Add(vb_id_1.SubmeshVertexIndex);
                m_submesh_vertlist.Add(vb_id_2.SubmeshVertexIndex);

                return(true);
            }
Ejemplo n.º 12
0
        private void ProcessLine(string line)
        {
            var parts = line.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);

            if (parts.Length <= 0)
            {
                return;
            }

            switch (parts[0])
            {
            case "v":
                var vertex = new GeometricVertex();
                vertex.ProcessData(parts, _maxValue);
                GeometricVertices.Add(vertex);
                break;

            case "f":
                var face = new FaceVertex();
                face.ProcessData(parts);
                FaceVertices.Add(face);
                break;

            case "vt":
                var textureVertex = new TextureVertex();
                textureVertex.ProcessData(parts);
                TextureVertices.Add(textureVertex);
                break;

            case "vn":
                var normalVertex = new NormalVertex();
                normalVertex.ProcessData(parts);
                NormalVertices.Add(normalVertex);
                break;
            }
        }
Ejemplo n.º 13
0
        public static void GenerateSegmentedPlane(int axis, Vector2 size, Vector2I segments, Vector2 uvTilesPerUnit, Vector2 uvTilesInTotal, out Vector3[] positions, out Vector3[] normals, out Vector4[] tangents, out Vector2[] texCoords, out int[] indices, out Face[] faces)
        {
            int resX = Math.Max(2, segments.X + 1);               // 2 minimum
            int resY = Math.Max(2, segments.Y + 1);

            positions = new Vector3[resX * resY];
            texCoords = new Vector2[positions.Length];

            Vector2 vt = uvTilesPerUnit * size;

            for (int y = 0; y < resY; y++)
            {
                // [ -height / 2, height / 2 ]
                double yPos = ((double)y / (resY - 1) - .5) * size.Y;
                double ty   = yPos + size.Y / 2; // [0, height]
                ty /= size.Y;                    // [0, 1]

                for (int x = 0; x < resX; x++)
                {
                    // [ -width / 2, width / 2 ]
                    double xPos = ((double)x / (resX - 1) - .5) * size.X;

                    double tx = xPos + size.X / 2;   // [0, width]
                    tx /= size.X;                    // [0, 1]

                    int index = x + y * resX;

                    if (axis == 0)
                    {
                        positions[index] = new Vector3(0, xPos, yPos);
                    }
                    else if (axis == 1)
                    {
                        positions[index] = new Vector3(-xPos, 0, yPos);
                    }
                    else
                    {
                        positions[index] = new Vector3(xPos, yPos, 0);
                    }
                    //texCoords[ index ] = new Vector2( tx, 1.0f - ty );

                    if (uvTilesInTotal != Vector2.Zero)
                    {
                        texCoords[index] = new Vector2(tx * uvTilesInTotal.X, 1.0f - ty * uvTilesInTotal.Y);
                    }
                    else if (uvTilesPerUnit != Vector2.Zero)
                    {
                        texCoords[index] = new Vector2(tx * vt.X, 1.0f - ty * vt.Y);
                    }
                    else
                    {
                        texCoords[index] = new Vector2(tx, 1.0f - ty);
                    }
                }
            }

            normals = new Vector3[positions.Length];
            for (int n = 0; n < normals.Length; n++)
            {
                if (axis == 0)
                {
                    normals[n] = Vector3F.XAxis;
                }
                else if (axis == 1)
                {
                    normals[n] = Vector3F.YAxis;
                }
                else
                {
                    normals[n] = Vector3F.ZAxis;
                }
            }

            tangents = new Vector4[positions.Length];
            for (int n = 0; n < tangents.Length; n++)
            {
                if (axis == 0)
                {
                    tangents[n] = new Vector4F(0, 1, 0, -1);
                }
                else if (axis == 1)
                {
                    tangents[n] = new Vector4F(-1, 0, 0, -1);
                }
                else
                {
                    tangents[n] = new Vector4F(1, 0, 0, -1);
                }
            }

            int nbFaces = (resX - 1) * (resY - 1);

            indices = new int[nbFaces * 6];
            int tIdx = 0;

            for (int fy = 0; fy < (resY - 1); fy++)
            {
                for (int fx = 0; fx < (resX - 1); fx++)
                {
                    indices[tIdx++] = fy * resX + fx;
                    indices[tIdx++] = fy * resX + 1 + fx;
                    indices[tIdx++] = fy * resX + resX + fx;

                    indices[tIdx++] = fy * resX + resX + fx;
                    indices[tIdx++] = fy * resX + 1 + fx;
                    indices[tIdx++] = fy * resX + resX + 1 + fx;
                }
            }

            var faceTriangles = new FaceVertex[indices.Length];

            for (int i = 0; i < indices.Length; i++)
            {
                faceTriangles[i] = new FaceVertex(indices[i], indices[i]);
            }
            faces = new Face[] { new Face(faceTriangles) };
        }
Ejemplo n.º 14
0
        public static void GeneratePlane(Vector2 size, Vector2 uvTilesPerUnit, Vector2 uvTilesInTotal, out Vector3[] positions, out Vector3[] normals, out Vector4[] tangents, out Vector2[] texCoords, out int[] indices, out Face[] faces)
        {
            var half = size * 0.5;

            positions    = new Vector3[4];
            positions[0] = new Vector3(-half.X, -half.Y, 0);
            positions[1] = new Vector3(half.X, -half.Y, 0);
            positions[2] = new Vector3(half.X, half.Y, 0);
            positions[3] = new Vector3(-half.X, half.Y, 0);

            normals    = new Vector3[4];
            normals[0] = Vector3.ZAxis;
            normals[1] = Vector3.ZAxis;
            normals[2] = Vector3.ZAxis;
            normals[3] = Vector3.ZAxis;

            tangents    = new Vector4[4];
            tangents[0] = new Vector4(1, 0, 0, -1);
            tangents[1] = new Vector4(1, 0, 0, -1);
            tangents[2] = new Vector4(1, 0, 0, -1);
            tangents[3] = new Vector4(1, 0, 0, -1);
            //tangents[ 0 ] = new Vector4( 1, 0, 0, 1 );
            //tangents[ 1 ] = new Vector4( 1, 0, 0, 1 );
            //tangents[ 2 ] = new Vector4( 1, 0, 0, 1 );
            //tangents[ 3 ] = new Vector4( 1, 0, 0, 1 );

            texCoords = new Vector2[4];
            if (uvTilesInTotal != Vector2.Zero)
            {
                texCoords[0] = new Vector2(0, uvTilesInTotal.Y);
                texCoords[1] = new Vector2(uvTilesInTotal.X, uvTilesInTotal.Y);
                texCoords[2] = new Vector2(uvTilesInTotal.X, 0);
                texCoords[3] = new Vector2(0, 0);

                //var half = uvTilesInTotal * 0.5;
                //texCoords[ 0 ] = new Vec2( -half.X, -half.Y );
                //texCoords[ 1 ] = new Vec2( half.X, -half.Y );
                //texCoords[ 2 ] = new Vec2( half.X, half.Y );
                //texCoords[ 3 ] = new Vec2( -half.X, half.Y );
            }
            else if (uvTilesPerUnit != Vector2.Zero)
            {
                Vector2 v = uvTilesPerUnit * size;
                texCoords[0] = new Vector2(0, v.Y);
                texCoords[1] = new Vector2(v.X, v.Y);
                texCoords[2] = new Vector2(v.X, 0);
                texCoords[3] = new Vector2(0, 0);

                //Vec2 half = uvTilesPerUnit * size * 0.5;
                //texCoords[ 0 ] = new Vec2( -half.X, -half.Y );
                //texCoords[ 1 ] = new Vec2( half.X, -half.Y );
                //texCoords[ 2 ] = new Vec2( half.X, half.Y );
                //texCoords[ 3 ] = new Vec2( -half.X, half.Y );
            }

            indices = new int[] { 0, 1, 2, 2, 3, 0 };

            var faceTriangles = new FaceVertex[indices.Length];

            for (int i = 0; i < indices.Length; i++)
            {
                faceTriangles[i] = new FaceVertex(indices[i], indices[i]);
            }
            faces = new Face[] { new Face(faceTriangles) };
        }
Ejemplo n.º 15
0
        //Is used in Sphere, Capsule
        public static Face[] BuildFacesForGeoSphere(int hSegments, int vSegments, int rawVerticesInFace, int rawVerticesInFaceForMiddle, int[] indices)
        {
            Debug.Assert(rawVerticesInFace == 3 && (rawVerticesInFaceForMiddle == 3 || rawVerticesInFaceForMiddle == 6));

            int faceCount = hSegments * (vSegments - 2) * 6 / rawVerticesInFace +
                            hSegments * 6 / rawVerticesInFaceForMiddle;
            var faces = new Face[faceCount];

            int middleSegmentStart = (vSegments / 2) * hSegments * 6;
            int middleSegmentEnd   = middleSegmentStart + hSegments * 6;
            int curTriangle        = 0;
            int curFace            = 0;

            FaceVertex[] faceTriangles = null;
            for (int i = 0; i < indices.Length; i++)
            {
                int index  = indices[i];
                int vIndex = index / (hSegments + 1);
                int hIndex = index % (hSegments + 1);
                hIndex %= hSegments;

                //Each vSegment has hSegments of vertices, exept the first and last vSegment, they have 1 vertex.
                //Verext count == hSegments * (vSegments-1) + 2;
                int vertexIndex;
                if (vIndex == 0)
                {
                    vertexIndex = hSegments * (vSegments - 1);
                }
                else if (vIndex == vSegments)
                {
                    vertexIndex = hSegments * (vSegments - 1) + 1;
                }
                else
                {
                    vertexIndex = (vIndex - 1) * hSegments + hIndex;
                }
                if (faceTriangles == null)
                {
                    faceTriangles = new FaceVertex[middleSegmentStart <= i && i < middleSegmentEnd ? rawVerticesInFaceForMiddle : rawVerticesInFace];
                    curTriangle   = 0;
                }

                faceTriangles[curTriangle++] = new FaceVertex(vertexIndex, index);
                if (curTriangle == faceTriangles.Length)
                {
                    bool isFirstDegenerate = IsDegenerate(faceTriangles[0].Vertex, faceTriangles[1].Vertex, faceTriangles[2].Vertex);
                    Debug.Assert(!(faceTriangles.Length == 6 && (
                                       isFirstDegenerate || IsDegenerate(faceTriangles[3].Vertex, faceTriangles[4].Vertex, faceTriangles[5].Vertex))
                                   ));

                    //??? Сейчас отбрасываются вырожденные. Можно ли сделать чтобы вырожденные не перебирались совсем?
                    if (!isFirstDegenerate)
                    {
                        faces[curFace++] = new Face(faceTriangles);
                    }

                    faceTriangles = null;
                }
            }

            Debug.Assert(faces.Length == curFace);
            return(faces.ToArray());

            bool IsDegenerate(int i0, int i1, int i2) => i0 == i1 || i0 == i2 || i1 == i2;
        }
Ejemplo n.º 16
0
        public static void ExportXModel(string FilePath, XModelType FileType, bool Siege = false, string Cosmetic = "")
        {
            // Configure scene
            using (var MayaCfg = new MayaSceneConfigure())
            {
                // First, get the current selection
                var ExportObjectList = new MSelectionList();
                MGlobal.getActiveSelectionList(ExportObjectList);

                // If empty, select all joints and meshes
                if (ExportObjectList.length == 0)
                {
                    // Select all joints and meshes
                    MGlobal.executeCommand("string $selected[] = `ls -type joint`; select -r $selected;");
                    MGlobal.executeCommand("string $transforms[] = `ls -tr`;string $polyMeshes[] = `filterExpand -sm 12 $transforms`;select -add $polyMeshes;");

                    // Get it again
                    MGlobal.getActiveSelectionList(ExportObjectList);
                }

                // If still empty, error blank scene
                if (ExportObjectList.length == 0)
                {
                    MGlobal.displayError("[CODTools] The current scene is empty...");
                    return;
                }

                // Progress
                MayaCfg.StartProgress("Exporting XModel...", (int)ExportObjectList.length);

                // Create new model
                var Result = new XModel(System.IO.Path.GetFileNameWithoutExtension(FilePath));
                // Assign siege model flag (Default: false)
                Result.SiegeModel = Siege;

                // Metadata
                var SceneName = string.Empty;
                MGlobal.executeCommand("file -q -sceneName", out SceneName);

                Result.Comments.Add(string.Format("Export filename: '{0}'", FilePath));
                Result.Comments.Add(string.Format("Source filename: '{0}'", SceneName));
                Result.Comments.Add(string.Format("Export time: {0}", DateTime.Now.ToString()));

                // Iterate and add joints
                var ParentStack = new List <string>();
                var UniqueBones = new HashSet <string>();

                foreach (var Joint in ExportObjectList.DependNodes(MFn.Type.kJoint))
                {
                    // Step
                    MayaCfg.StepProgress();

                    // Grab the controller
                    var Path       = GetObjectDagPath(Joint);
                    var Controller = new MFnIkJoint(Path);

                    // Create a new bone
                    var TagName = CleanNodeName(Controller.name);

                    if (UniqueBones.Contains(TagName))
                    {
                        continue;
                    }
                    UniqueBones.Add(TagName);

                    var NewBone = new Bone(TagName);
                    // Add parent
                    ParentStack.Add(GetParentName(Controller));

                    // Fetch the world-space position and rotation
                    var WorldPosition = Controller.getTranslation(MSpace.Space.kWorld);

                    var WorldRotation = new MQuaternion(MQuaternion.identity);
                    Controller.getRotation(WorldRotation, MSpace.Space.kWorld);

                    var WorldScale = new double[3] {
                        1, 1, 1
                    };
                    Controller.getScale(WorldScale);

                    // Create the matrix
                    NewBone.Translation    = WorldPosition * (1 / 2.54);
                    NewBone.Scale          = new MVector(WorldScale[0], WorldScale[1], WorldScale[2]);
                    NewBone.RotationMatrix = WorldRotation.asMatrix;

                    // Add it
                    Result.Bones.Add(NewBone);
                }
                // Sort joints
                SortJoints(ref Result, ParentStack, Cosmetic);

                // Pre-fetch skins
                var SkinClusters = GetSkinClusters();
                var BoneMapping  = Result.GetBoneMapping();

                // A list of used materials
                int MaterialIndex = 0;
                var UsedMaterials = new Dictionary <string, int>();
                var UsedMeshes    = new HashSet <string>();

                // Iterate and add meshes
                foreach (var Mesh in ExportObjectList.DependNodes(MFn.Type.kMesh))
                {
                    // Step
                    MayaCfg.StepProgress();

                    // Grab the controller
                    var Path = GetObjectDagPath(Mesh);
                    Path.extendToShape();
                    var Controller = new MFnMesh(Path);

                    // Ignore duplicates
                    if (UsedMeshes.Contains(Path.partialPathName))
                    {
                        continue;
                    }
                    UsedMeshes.Add(Path.partialPathName);

                    // Pre-fetch materials
                    var MeshMaterials = GetMaterialsMesh(ref Controller, ref Path);
                    foreach (var Mat in MeshMaterials)
                    {
                        if (!UsedMaterials.ContainsKey(Mat.Name))
                        {
                            UsedMaterials.Add(Mat.Name, MaterialIndex++);
                            Result.Materials.Add(Mat);
                        }
                    }

                    // New mesh
                    var NewMesh = new Mesh();

                    // Grab iterators
                    var VertexIterator = new MItMeshVertex(Path);
                    var FaceIterator   = new MItMeshPolygon(Path);

                    // Get the cluster for this
                    var SkinCluster = FindSkinCluster(ref SkinClusters, Controller);
                    var SkinJoints  = new MDagPathArray();

                    if (SkinCluster != null)
                    {
                        SkinCluster.influenceObjects(SkinJoints);
                    }

                    // Build vertex array
                    for (; !VertexIterator.isDone; VertexIterator.next())
                    {
                        // Prepare
                        var NewVert = new Vertex();

                        // Grab data
                        NewVert.Position = VertexIterator.position(MSpace.Space.kWorld) * (1 / 2.54);

                        // Weights if valid
                        if (SkinCluster != null)
                        {
                            var WeightValues = new MDoubleArray();

                            uint Influence = 0;
                            SkinCluster.getWeights(Path, VertexIterator.currentItem(), WeightValues, ref Influence);

                            for (int i = 0; i < (int)WeightValues.length; i++)
                            {
                                if (WeightValues[i] < 0.000001)
                                {
                                    continue;
                                }
                                var WeightTagName = CleanNodeName(SkinJoints[i].partialPathName);
                                var WeightID      = (BoneMapping.ContainsKey(WeightTagName)) ? BoneMapping[WeightTagName] : 0;

                                NewVert.Weights.Add(new Tuple <int, float>(WeightID, (float)WeightValues[i]));
                            }
                        }
                        if (NewVert.Weights.Count == 0)
                        {
                            NewVert.Weights.Add(new Tuple <int, float>(0, 1.0f));
                        }

                        // Add it
                        NewMesh.Vertices.Add(NewVert);
                    }

                    // Build face array
                    for (; !FaceIterator.isDone; FaceIterator.next())
                    {
                        var Indices = new MIntArray();
                        var Normals = new MVectorArray();
                        var UVUs    = new MFloatArray();
                        var UVVs    = new MFloatArray();

                        FaceIterator.getVertices(Indices);
                        FaceIterator.getNormals(Normals, MSpace.Space.kWorld);
                        FaceIterator.getUVs(UVUs, UVVs);

                        // Only support TRIS/QUAD
                        if (Indices.Count < 3)
                        {
                            continue;
                        }

                        if (Indices.Count == 3)
                        {
                            // Create new face
                            var NewFace = new FaceVertex();
                            // Setup
                            NewFace.Indices[0] = Indices[0];
                            NewFace.Indices[2] = Indices[1];
                            NewFace.Indices[1] = Indices[2];

                            // Normals
                            NewFace.Normals[0] = new MVector(Normals[0][0], Normals[0][1], Normals[0][2]);
                            NewFace.Normals[2] = new MVector(Normals[1][0], Normals[1][1], Normals[1][2]);
                            NewFace.Normals[1] = new MVector(Normals[2][0], Normals[2][1], Normals[2][2]);

                            // Colors
                            FaceIterator.getColor(NewFace.Colors[0], 0);
                            FaceIterator.getColor(NewFace.Colors[2], 1);
                            FaceIterator.getColor(NewFace.Colors[1], 2);

                            // Append UV Layers
                            NewFace.UVs[0] = new Tuple <float, float>(UVUs[0], 1 - UVVs[0]);
                            NewFace.UVs[2] = new Tuple <float, float>(UVUs[1], 1 - UVVs[1]);
                            NewFace.UVs[1] = new Tuple <float, float>(UVUs[2], 1 - UVVs[2]);

                            // Set material index
                            if (MeshMaterials.Count > 0)
                            {
                                NewFace.MaterialIndex = UsedMaterials[MeshMaterials[0].Name];
                            }

                            // Add it
                            NewMesh.Faces.Add(NewFace);
                        }
                        else
                        {
                            // Create new faces
                            FaceVertex NewFace = new FaceVertex(), NewFace2 = new FaceVertex();
                            // Setup
                            NewFace.Indices[0]  = Indices[0];
                            NewFace.Indices[2]  = Indices[1];
                            NewFace.Indices[1]  = Indices[2];
                            NewFace2.Indices[0] = Indices[0];
                            NewFace2.Indices[2] = Indices[2];
                            NewFace2.Indices[1] = Indices[3];

                            // Normals
                            NewFace.Normals[0]  = new MVector(Normals[0][0], Normals[0][1], Normals[0][2]);
                            NewFace.Normals[2]  = new MVector(Normals[1][0], Normals[1][1], Normals[1][2]);
                            NewFace.Normals[1]  = new MVector(Normals[2][0], Normals[2][1], Normals[2][2]);
                            NewFace2.Normals[0] = new MVector(Normals[0][0], Normals[0][1], Normals[0][2]);
                            NewFace2.Normals[2] = new MVector(Normals[2][0], Normals[2][1], Normals[2][2]);
                            NewFace2.Normals[1] = new MVector(Normals[3][0], Normals[3][1], Normals[3][2]);

                            // Colors
                            FaceIterator.getColor(NewFace.Colors[0], 0);
                            FaceIterator.getColor(NewFace.Colors[2], 1);
                            FaceIterator.getColor(NewFace.Colors[1], 2);
                            FaceIterator.getColor(NewFace2.Colors[0], 0);
                            FaceIterator.getColor(NewFace2.Colors[2], 2);
                            FaceIterator.getColor(NewFace2.Colors[1], 3);

                            // Append UV Layers
                            NewFace.UVs[0]  = new Tuple <float, float>(UVUs[0], 1 - UVVs[0]);
                            NewFace.UVs[2]  = new Tuple <float, float>(UVUs[1], 1 - UVVs[1]);
                            NewFace.UVs[1]  = new Tuple <float, float>(UVUs[2], 1 - UVVs[2]);
                            NewFace2.UVs[0] = new Tuple <float, float>(UVUs[0], 1 - UVVs[0]);
                            NewFace2.UVs[2] = new Tuple <float, float>(UVUs[2], 1 - UVVs[2]);
                            NewFace2.UVs[1] = new Tuple <float, float>(UVUs[3], 1 - UVVs[3]);

                            // Set material index
                            if (MeshMaterials.Count > 0)
                            {
                                NewFace.MaterialIndex  = UsedMaterials[MeshMaterials[0].Name];
                                NewFace2.MaterialIndex = UsedMaterials[MeshMaterials[0].Name];
                            }

                            // Add it
                            NewMesh.Faces.Add(NewFace);
                            NewMesh.Faces.Add(NewFace2);
                        }
                    }

                    // Add it
                    Result.Meshes.Add(NewMesh);
                }

                // Write
                switch (FileType)
                {
                case XModelType.Export:
                    Result.WriteExport(FilePath);
                    break;

                case XModelType.Bin:
                    Result.WriteBin(FilePath);
                    break;
                }
            }

            // Log complete
            MGlobal.displayInfo(string.Format("[CODTools] Exported {0}", System.IO.Path.GetFileName(FilePath)));
        }
Ejemplo n.º 17
0
 public void AddVertex(FaceVertex vertex)
 {
     _vertices.Add(vertex);
 }
Ejemplo n.º 18
0
        public static void GenerateCone(int axis, ConeOrigin origin, double radius, double height, int segments, bool needSide, bool needBottom, out Vector3[] positions, out Vector3[] normals, out Vector4[] tangents, out Vector2[] texCoords, out int[] indices, out Face[] faces)
        {
            if (!needSide && !needBottom)
            {
                positions = new Vector3[0];
                indices   = new int[0];
                normals   = new Vector3[0];
                tangents  = new Vector4[0];
                texCoords = new Vector2[0];
                faces     = null;
                return;
            }

            if (axis < 0 || axis > 2)
            {
                Log.Fatal("SimpleMeshGenerator: GenerateCone: axis < 0 || axis > 2.");
            }
            //if( radius < 0 )
            //	Log.Fatal( "SimpleMeshGenerator: GenerateCone: radius < 0." );
            //if( height < 0 )
            //	Log.Fatal( "SimpleMeshGenerator: GenerateCone: height < 0." );
            if (segments < 3)
            {
                Log.Fatal("SimpleMeshGenerator: GenerateCone: segments < 3.");
            }

            int bottomStartIndex = 0;

            //positions
            {
                int vertexCount = 0;
                if (needSide)
                {
                    vertexCount += (segments + 1) * 2;
                }
                if (needBottom)
                {
                    vertexCount += segments + 2;
                }

                positions = new Vector3[vertexCount];
                normals   = new Vector3[vertexCount];
                tangents  = new Vector4[vertexCount];
                texCoords = new Vector2[vertexCount];

                double[] cosTable = new double[segments + 1];
                double[] sinTable = new double[segments + 1];
                {
                    double angleStep = Math.PI * 2 / segments;
                    for (int n = 0; n < segments + 1; n++)
                    {
                        double angle = angleStep * n;
                        cosTable[n] = Math.Cos(angle);
                        sinTable[n] = Math.Sin(angle);
                    }
                }

                int currentPosition = 0;

                if (needSide)
                {
                    for (int n = 0; n < segments + 1; n++)
                    {
                        var fromVector = new Vector3(0, cosTable[n], sinTable[n]);

                        var from = fromVector * radius;
                        var to   = new Vector3(Math.Abs(height), 0, 0);

                        positions[currentPosition] = from;

                        //normals
                        Vector3 normal;
                        if (radius == 0)
                        {
                            normal = fromVector;
                        }
                        else if (height == 0)
                        {
                            normal = Vector3.XAxis;
                        }
                        else
                        {
                            var v = new Vector3(0, from.Y, from.Z).GetNormalize();
                            normal = new Vector3(radius / height, v.Y * (height / radius), v.Z * (height / radius)).GetNormalize();
                        }
                        if (radius < 0 || height < 0)
                        {
                            normal = -normal;
                        }
                        normals[currentPosition] = normal;

                        tangents[currentPosition]  = new Vector4((to - from).GetNormalize(), -1);
                        texCoords[currentPosition] = new Vector2(0, (double)n / (double)segments * 2);

                        currentPosition++;
                    }

                    for (int n = 0; n < segments + 1; n++)
                    {
                        double angle      = ((double)n + 0.5) / (double)segments * Math.PI * 2;
                        var    fromVector = new Vector3(0, Math.Cos(angle), Math.Sin(angle));
                        //var fromVector = new Vec3( 0, cosTable[ n ], sinTable[ n ] );

                        var from = fromVector * radius;
                        var to   = new Vector3(Math.Abs(height), 0, 0);

                        positions[currentPosition] = to;

                        //normals
                        Vector3 normal;
                        if (radius == 0)
                        {
                            normal = fromVector;
                        }
                        else if (height == 0)
                        {
                            normal = Vector3.XAxis;
                        }
                        else
                        {
                            var v = new Vector3(0, from.Y, from.Z).GetNormalize();
                            normal = new Vector3(radius / height, v.Y * (height / radius), v.Z * (height / radius)).GetNormalize();
                        }
                        if (radius < 0 || height < 0)
                        {
                            normal = -normal;
                        }
                        normals[currentPosition] = normal;

                        tangents[currentPosition]  = new Vector4((to - from).GetNormalize(), -1);
                        texCoords[currentPosition] = new Vector2(1, ((double)n + 0.5) / (double)segments * 2);

                        currentPosition++;
                    }
                }

                if (needBottom)
                {
                    bottomStartIndex = currentPosition;
                    for (int n = 0; n < segments + 1; n++)
                    {
                        positions[currentPosition] = new Vector3(0, cosTable[n] * radius, sinTable[n] * radius);
                        normals[currentPosition]   = new Vector3(-1, 0, 0);
                        if (radius < 0 || height < 0)
                        {
                            normals[currentPosition] = -normals[currentPosition];
                        }
                        tangents[currentPosition] = new Vector4(0, 0, -1, -1);

                        if (radius < 0 || height < 0)
                        {
                            texCoords[currentPosition] = new Vector2(sinTable[n], cosTable[n]) * 0.5 + new Vector2(0.5, 0.5);
                        }
                        else
                        {
                            texCoords[currentPosition] = new Vector2(-sinTable[n], cosTable[n]) * 0.5 + new Vector2(0.5, 0.5);
                        }
                        currentPosition++;
                    }

                    positions[currentPosition] = new Vector3(0, 0, 0);
                    normals[currentPosition]   = new Vector3(-1, 0, 0);
                    if (radius < 0 || height < 0)
                    {
                        normals[currentPosition] = -normals[currentPosition];
                    }
                    tangents[currentPosition]  = new Vector4(0, 0, -1, -1);
                    texCoords[currentPosition] = new Vector2(0.5, 0.5);
                    currentPosition++;
                }

                if (positions.Length != currentPosition)
                {
                    Log.Fatal("SimpleMeshGenerator: GenerateCone: positions.Length != currentPosition.");
                }
            }



            //indices and faces
            {
                int faceCount = 0;
                if (needSide)
                {
                    faceCount += segments;
                }
                if (needBottom)
                {
                    faceCount += 1;
                }

                //side faces - faces[0..segments) ; bottom - faces[segments]
                faces = new Face[faceCount];

                //Vertex indices will be: on bottom [0..segments); top[segments] ; bottom center[segments+1]
                const int bottomVertexStart  = 0;
                int       topVertex          = segments;
                int       bottomCenterVertex = segments + 1;

                int indexCount = 0;
                if (needSide)
                {
                    indexCount += segments * 3;
                }
                if (needBottom)
                {
                    indexCount += segments * 3;
                }

                indices = new int[indexCount];

                int currentIndex = 0;

                if (needSide)
                {
                    for (int n = 0; n < segments; n++)
                    {
                        //int index = n * 2;
                        indices[currentIndex++] = n;
                        int nextClipped = (n + 1) % segments;
                        if (radius < 0 || height < 0)
                        {
                            indices[currentIndex++] = n + segments + 1;                               //top
                            indices[currentIndex++] = n + 1;

                            faces[n] = new Face
                            {
                                Triangles = new[] {
                                    new FaceVertex(bottomVertexStart + n, n),
                                    new FaceVertex(topVertex, n + segments + 1),
                                    new FaceVertex(bottomVertexStart + nextClipped, n + 1)
                                }
                            };
                        }
                        else
                        {
                            indices[currentIndex++] = n + 1;
                            indices[currentIndex++] = n + segments + 1;

                            faces[n] = new Face
                            {
                                Triangles = new[] {
                                    new FaceVertex(bottomVertexStart + n, n),
                                    new FaceVertex(bottomVertexStart + nextClipped, n + 1),
                                    new FaceVertex(topVertex, n + segments + 1)
                                }
                            };
                        }
                    }
                }
                if (needBottom)
                {
                    var faceTriangles = new FaceVertex[segments * 3];

                    for (int n = 0; n < segments; n++)
                    {
                        int index = bottomStartIndex + n;
                        int n3    = n * 3;

                        faceTriangles[n3]       = new FaceVertex(bottomVertexStart + (n + 1) % segments, index + 1);
                        indices[currentIndex++] = index + 1;

                        if (radius < 0 || height < 0)
                        {
                            faceTriangles[n3 + 1]   = new FaceVertex(bottomCenterVertex, bottomStartIndex + segments + 1);
                            indices[currentIndex++] = bottomStartIndex + segments + 1;                               //center

                            faceTriangles[n3 + 2]   = new FaceVertex(bottomVertexStart + n, index);
                            indices[currentIndex++] = index;
                        }
                        else
                        {
                            faceTriangles[n3 + 1]   = new FaceVertex(bottomVertexStart + n, index);
                            indices[currentIndex++] = index;

                            faceTriangles[n3 + 2]   = new FaceVertex(bottomCenterVertex, bottomStartIndex + segments + 1);
                            indices[currentIndex++] = bottomStartIndex + segments + 1;
                        }
                    }
                    faces[segments] = new Face(faceTriangles);
                }

                if (indices.Length != currentIndex)
                {
                    Log.Fatal("SimpleMeshGenerator: GenerateCone: indices.Length != currentIndex.");
                }
            }

            if (origin == ConeOrigin.Center)
            {
                Vector3 offset    = new Vector3(-Math.Abs(height) * .5, 0, 0);
                var     newValues = new Vector3[positions.Length];
                for (int n = 0; n < positions.Length; n++)
                {
                    newValues[n] = positions[n] + offset;
                }
                positions = newValues;
            }

            positions = RotateByAxis(axis, positions);
            normals   = RotateByAxis(axis, normals);
            tangents  = RotateByAxis(axis, tangents);
        }
Ejemplo n.º 19
0
        public Mesh LoadFromString(string objModel)
        {
            // Seperate lines from the file
            List <string> lines = new List <string>(objModel.Split('\n'));

            // Lists to hold model data
            List <Vector3> verts   = new List <Vector3>();
            List <Vector3> normals = new List <Vector3>();
            List <Vector2> texs    = new List <Vector2>();

            List <Vector3> decodedVertices = new List <Vector3>();
            List <Vector3> decodedNormals  = new List <Vector3>();
            List <Vector2> decodedUvCoords = new List <Vector2>();

            List <Tuple <TempVertex, TempVertex, TempVertex> > faces = new List <Tuple <TempVertex, TempVertex, TempVertex> >();

            // Base values
            verts.Add(new Vector3());
            texs.Add(new Vector2());
            normals.Add(new Vector3());

            // Read file line by line
            foreach (String line in lines)
            {
                if (line.StartsWith("v ")) // Vertex definition
                {
                    // Cut off beginning of line
                    String temp = line.Substring(2);

                    Vector3 vec = new Vector3();

                    if (temp.Trim().Count((char c) => c == ' ') == 2) // Check if there's enough elements for a vertex
                    {
                        String[] vertparts = temp.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);

                        // Attempt to parse each part of the vertice
                        bool success = float.TryParse(vertparts[0], NumberStyles.Any, CultureInfo.InvariantCulture, out vec.X);
                        success |= float.TryParse(vertparts[1], NumberStyles.Any, CultureInfo.InvariantCulture, out vec.Y);
                        success |= float.TryParse(vertparts[2], NumberStyles.Any, CultureInfo.InvariantCulture, out vec.Z);

                        // If any of the parses failed, report the error
                        if (!success)
                        {
                            Console.WriteLine("Error parsing vertex: {0}", line);
                        }
                    }
                    else
                    {
                        Console.WriteLine("Error parsing vertex: {0}", line);
                    }

                    verts.Add(vec);
                }
                else if (line.StartsWith("vt ")) // Texture coordinate
                {
                    // Cut off beginning of line
                    String temp = line.Substring(2);

                    Vector2 vec = new Vector2();

                    if (temp.Trim().Count((char c) => c == ' ') > 0) // Check if there's enough elements for a vertex
                    {
                        String[] texcoordparts = temp.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);

                        // Attempt to parse each part of the vertice
                        bool success = float.TryParse(texcoordparts[0], NumberStyles.Any, CultureInfo.InvariantCulture, out vec.X);
                        success |= float.TryParse(texcoordparts[1], NumberStyles.Any, CultureInfo.InvariantCulture, out vec.Y);

                        // If any of the parses failed, report the error
                        if (!success)
                        {
                            Console.WriteLine("Error parsing texture coordinate: {0}", line);
                        }
                    }
                    else
                    {
                        Console.WriteLine("Error parsing texture coordinate: {0}", line);
                    }

                    texs.Add(vec);
                }
                else if (line.StartsWith("vn ")) // Normal vector
                {
                    // Cut off beginning of line
                    String temp = line.Substring(2);

                    Vector3 vec = new Vector3();

                    if (temp.Trim().Count((char c) => c == ' ') == 2) // Check if there's enough elements for a normal
                    {
                        String[] vertparts = temp.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);


                        // Attempt to parse each part of the vertice
                        bool success = float.TryParse(vertparts[0], NumberStyles.Any, CultureInfo.InvariantCulture, out vec.X);
                        success |= float.TryParse(vertparts[1], NumberStyles.Any, CultureInfo.InvariantCulture, out vec.Y);
                        success |= float.TryParse(vertparts[2], NumberStyles.Any, CultureInfo.InvariantCulture, out vec.Z);

                        // If any of the parses failed, report the error
                        if (!success)
                        {
                            Console.WriteLine("Error parsing normal: {0}", line);
                        }
                    }
                    else
                    {
                        Console.WriteLine("Error parsing normal: {0}", line);
                    }

                    normals.Add(vec);
                }
                else if (line.StartsWith("f ")) // Face definition
                {
                    // Cut off beginning of line
                    String temp = line.Substring(2);

                    Tuple <TempVertex, TempVertex, TempVertex> face = new Tuple <TempVertex, TempVertex, TempVertex>(new TempVertex(), new TempVertex(), new TempVertex());

                    if (temp.Trim().Count((char c) => c == ' ') == 2) // Check if there's enough elements for a face
                    {
                        String[] faceparts = temp.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);

                        int v1, v2, v3;
                        int t1, t2, t3;
                        int n1, n2, n3;

                        // Attempt to parse each part of the face
                        bool success = int.TryParse(faceparts[0].Split('/')[0], out v1);
                        success |= int.TryParse(faceparts[1].Split('/')[0], out v2);
                        success |= int.TryParse(faceparts[2].Split('/')[0], out v3);

                        if (faceparts[0].Count((char c) => c == '/') >= 2)
                        {
                            success |= int.TryParse(faceparts[0].Split('/')[1], out t1);
                            success |= int.TryParse(faceparts[1].Split('/')[1], out t2);
                            success |= int.TryParse(faceparts[2].Split('/')[1], out t3);
                            success |= int.TryParse(faceparts[0].Split('/')[2], out n1);
                            success |= int.TryParse(faceparts[1].Split('/')[2], out n2);
                            success |= int.TryParse(faceparts[2].Split('/')[2], out n3);
                        }
                        else
                        {
                            if (texs.Count > v1 && texs.Count > v2 && texs.Count > v3)
                            {
                                t1 = v1;
                                t2 = v2;
                                t3 = v3;
                            }
                            else
                            {
                                t1 = 0;
                                t2 = 0;
                                t3 = 0;
                            }


                            if (normals.Count > v1 && normals.Count > v2 && normals.Count > v3)
                            {
                                n1 = v1;
                                n2 = v2;
                                n3 = v3;
                            }
                            else
                            {
                                n1 = 0;
                                n2 = 0;
                                n3 = 0;
                            }
                        }


                        // If any of the parses failed, report the error
                        if (!success)
                        {
                            Console.WriteLine("Error parsing face: {0}", line);
                        }
                        else
                        {
                            TempVertex tv1 = new TempVertex(v1, n1, t1);
                            TempVertex tv2 = new TempVertex(v2, n2, t2);
                            TempVertex tv3 = new TempVertex(v3, n3, t3);
                            face = new Tuple <TempVertex, TempVertex, TempVertex>(tv1, tv2, tv3);
                            faces.Add(face);
                        }
                    }
                    else
                    {
                        Console.WriteLine("Error parsing face: {0}", line);
                    }
                }
            }

            // Create the ObjVolume
            Mesh loadedModel = new Mesh();

            foreach (var face in faces)
            {
                FaceVertex v1 = new FaceVertex(verts[face.Item1.Vertex], normals[face.Item1.Normal], texs[face.Item1.Texcoord]);
                FaceVertex v2 = new FaceVertex(verts[face.Item2.Vertex], normals[face.Item2.Normal], texs[face.Item2.Texcoord]);
                FaceVertex v3 = new FaceVertex(verts[face.Item3.Vertex], normals[face.Item3.Normal], texs[face.Item3.Texcoord]);

                Vector2 calculatedUV  = new Vector2(texs[face.Item1.Texcoord].X, 1.0f - texs[face.Item1.Texcoord].Y);
                Vector2 calculatedUV2 = new Vector2(texs[face.Item2.Texcoord].X, 1.0f - texs[face.Item2.Texcoord].Y);
                Vector2 calculatedUV3 = new Vector2(texs[face.Item3.Texcoord].X, 1.0f - texs[face.Item3.Texcoord].Y);

                decodedVertices.AddRange(new Vector3[] { verts[face.Item1.Vertex], verts[face.Item2.Vertex], verts[face.Item3.Vertex] });
                decodedNormals.AddRange(new Vector3[] { normals[face.Item1.Normal], normals[face.Item2.Normal], normals[face.Item3.Normal] });
                decodedUvCoords.AddRange(new Vector2[] { calculatedUV, calculatedUV2, calculatedUV3 });
            }

            loadedModel.Indeces  = Enumerable.Range(0, decodedVertices.Count).ToArray();
            loadedModel.Vertices = decodedVertices.ToArray();
            loadedModel.Normals  = decodedNormals.ToArray();
            loadedModel.UvCoords = decodedUvCoords.ToArray();

            return(loadedModel);
        }
Ejemplo n.º 20
0
        public static void GenerateCylinder(int axis, double radius, double height, int segments, bool needTop, bool needSide, bool needBottom, out Vector3[] positions, out Vector3[] normals, out Vector4[] tangents, out Vector2[] texCoords, out int[] indices, out Face[] faces)
        {
            if (axis < 0 || axis > 2)
            {
                Log.Fatal("SimpleMeshGenerator: GenerateCylinder: axis < 0 || axis > 2.");
            }
            //if( radius < 0 )
            //	Log.Fatal( "SimpleMeshGenerator: GenerateCylinder: radius < 0." );
            //if( height < 0 )
            //	Log.Fatal( "SimpleMeshGenerator: GenerateCylinder: height < 0." );
            if (segments < 3)
            {
                Log.Fatal("SimpleMeshGenerator: GenerateCylinder: segments < 3.");
            }

            int topIndex      = 0;
            int topStartIndex = 0;

            int bottomIndex      = 0;
            int bottomStartIndex = 0;

            int sideTopIndex    = 0;
            int sideBottomIndex = 0;

            //positions
            {
                int vertexCount = 0;

                if (needSide)
                {
                    vertexCount += (segments + 1) * 2;
                }
                if (needTop)
                {
                    vertexCount += segments + 1;
                }
                if (needBottom)
                {
                    vertexCount += segments + 1;
                }

                positions = new Vector3[vertexCount];
                normals   = new Vector3[vertexCount];
                tangents  = new Vector4[vertexCount];
                texCoords = new Vector2[vertexCount];

                double[] cosTable = new double[segments + 1];
                double[] sinTable = new double[segments + 1];
                {
                    double angleStep = Math.PI * 2 / segments;
                    for (int n = 0; n < segments + 1; n++)
                    {
                        double angle = angleStep * n;
                        cosTable[n] = Math.Cos(angle);
                        sinTable[n] = Math.Sin(angle);
                    }
                }

                int currentPosition = 0;

                if (needSide)
                {
                    sideTopIndex = currentPosition;
                    for (int n = 0; n < segments + 1; n++)
                    {
                        positions[currentPosition] = new Vector3(height * .5, cosTable[n] * radius, sinTable[n] * radius);
                        normals[currentPosition]   = new Vector3(0, cosTable[n], sinTable[n]);
                        if (radius < 0 || height < 0)
                        {
                            tangents[currentPosition] = new Vector4(-1, 0, 0, -1);
                        }
                        else
                        {
                            tangents[currentPosition] = new Vector4(1, 0, 0, -1);
                        }
                        texCoords[currentPosition] = new Vector2(1, (double)n / (double)segments * 2);
                        currentPosition++;
                    }

                    sideBottomIndex = currentPosition;
                    for (int n = 0; n < segments + 1; n++)
                    {
                        positions[currentPosition] = new Vector3(-height * .5, cosTable[n] * radius, sinTable[n] * radius);
                        normals[currentPosition]   = new Vector3(0, cosTable[n], sinTable[n]);
                        if (radius < 0 || height < 0)
                        {
                            tangents[currentPosition] = new Vector4(-1, 0, 0, -1);
                        }
                        else
                        {
                            tangents[currentPosition] = new Vector4(1, 0, 0, -1);
                        }
                        texCoords[currentPosition] = new Vector2(0, (double)n / (double)segments * 2);
                        currentPosition++;
                    }
                }

                if (needTop)
                {
                    topStartIndex = currentPosition;
                    for (int n = 0; n < segments; n++)
                    {
                        positions[currentPosition] = new Vector3(height * .5f, cosTable[n] * radius, sinTable[n] * radius);
                        normals[currentPosition]   = new Vector3(1, 0, 0);
                        tangents[currentPosition]  = new Vector4(0, 0, -1, -1);
                        if (radius < 0 || height < 0)
                        {
                            texCoords[currentPosition] = new Vector2(sinTable[n], cosTable[n]) * 0.5 + new Vector2(0.5, 0.5);
                        }
                        else
                        {
                            texCoords[currentPosition] = new Vector2(-sinTable[n], -cosTable[n]) * 0.5 + new Vector2(0.5, 0.5);
                        }
                        currentPosition++;
                    }

                    topIndex = currentPosition;
                    positions[currentPosition] = new Vector3(height * .5, 0, 0);
                    normals[currentPosition]   = new Vector3(1, 0, 0);
                    tangents[currentPosition]  = new Vector4(0, 0, -1, -1);
                    texCoords[currentPosition] = new Vector2(0.5, 0.5);
                    currentPosition++;
                }

                if (needBottom)
                {
                    bottomStartIndex = currentPosition;
                    for (int n = 0; n < segments; n++)
                    {
                        positions[currentPosition] = new Vector3(-height * .5, cosTable[n] * radius, sinTable[n] * radius);
                        normals[currentPosition]   = new Vector3(-1, 0, 0);
                        tangents[currentPosition]  = new Vector4(0, 0, -1, -1);
                        if (radius < 0 || height < 0)
                        {
                            texCoords[currentPosition] = new Vector2(sinTable[n], -cosTable[n]) * 0.5 + new Vector2(0.5, 0.5);
                        }
                        else
                        {
                            texCoords[currentPosition] = new Vector2(-sinTable[n], cosTable[n]) * 0.5 + new Vector2(0.5, 0.5);
                        }
                        currentPosition++;
                    }

                    bottomIndex = currentPosition;
                    positions[currentPosition] = new Vector3(-height * .5, 0, 0);
                    normals[currentPosition]   = new Vector3(-1, 0, 0);
                    tangents[currentPosition]  = new Vector4(0, 0, -1, -1);
                    texCoords[currentPosition] = new Vector2(0.5, 0.5);
                    currentPosition++;
                }

                if (positions.Length != currentPosition)
                {
                    Log.Fatal("SimpleMeshGenerator: GenerateCylinder: positions.Length != currentPosition.");
                }
            }

            //indices and faces
            {
                int faceCount = 0;
                if (needSide)
                {
                    faceCount += segments;
                }
                if (needTop)
                {
                    faceCount += 1;
                }
                if (needBottom)
                {
                    faceCount += 1;
                }

                //side faces - faces[0..segments) ; top - faces[segments]; bottom - faces[segments + 1]
                faces = new Face[faceCount];

                //Vertex indices will be: on top [0..segments), top center [segments], on bottom [segments+1..segments*2+1), bottom center[segments*2+1]
                const int topVertexStart     = 0;
                int       topCenterVertex    = segments;
                int       bottomVertexStart  = segments + 1;
                int       bottomCenterVertex = segments * 2 + 1;


                int indexCount = 0;

                if (needSide)
                {
                    indexCount += segments * 2 * 3;
                }
                if (needTop)
                {
                    indexCount += segments * 3;
                }
                if (needBottom)
                {
                    indexCount += segments * 3;
                }

                indices = new int[indexCount];

                int currentIndex = 0;

                if (needSide)
                {
                    for (int n = 0; n < segments; n++)
                    {
                        int start = n;
                        int end   = (n + 1);                        // % segments;

                        indices[currentIndex++] = sideTopIndex + end;
                        indices[currentIndex++] = sideTopIndex + start;
                        indices[currentIndex++] = sideBottomIndex + start;

                        indices[currentIndex++] = sideBottomIndex + start;
                        indices[currentIndex++] = sideBottomIndex + end;
                        indices[currentIndex++] = sideTopIndex + end;

                        int endClipped = end % segments;
                        faces[n] = new Face
                        {
                            Triangles = new[] {
                                new FaceVertex(topVertexStart + endClipped, sideTopIndex + end),
                                new FaceVertex(topVertexStart + start, sideTopIndex + start),
                                new FaceVertex(bottomVertexStart + start, sideBottomIndex + start),
                                new FaceVertex(bottomVertexStart + start, sideBottomIndex + start),
                                new FaceVertex(bottomVertexStart + endClipped, sideBottomIndex + end),
                                new FaceVertex(topVertexStart + endClipped, sideTopIndex + end)
                            }
                        };
                    }
                }
                if (needTop)
                {
                    var faceTriangles = new FaceVertex[segments * 3];
                    for (int n = 0; n < segments; n++)
                    {
                        int start = n;
                        int end   = (n + 1) % segments;
                        int n3    = n * 3;

                        faceTriangles[n3]       = new FaceVertex(topVertexStart + start, topStartIndex + start);
                        indices[currentIndex++] = topStartIndex + start;

                        faceTriangles[n3 + 1]   = new FaceVertex(topVertexStart + end, topStartIndex + end);
                        indices[currentIndex++] = topStartIndex + end;

                        faceTriangles[n3 + 2]   = new FaceVertex(topCenterVertex, topIndex);
                        indices[currentIndex++] = topIndex;
                    }
                    faces[segments] = new Face(faceTriangles);
                }
                if (needBottom)
                {
                    var faceTriangles = new FaceVertex[segments * 3];
                    for (int n = 0; n < segments; n++)
                    {
                        int start = n;
                        int end   = (n + 1) % segments;
                        int n3    = n * 3;

                        faceTriangles[n3]       = new FaceVertex(bottomVertexStart + end, bottomStartIndex + end);
                        indices[currentIndex++] = bottomStartIndex + end;

                        faceTriangles[n3 + 1]   = new FaceVertex(bottomVertexStart + start, bottomStartIndex + start);
                        indices[currentIndex++] = bottomStartIndex + start;

                        faceTriangles[n3 + 2]   = new FaceVertex(bottomCenterVertex, bottomIndex);
                        indices[currentIndex++] = bottomIndex;
                    }
                    faces[segments + 1] = new Face(faceTriangles);
                }

                if (indices.Length != currentIndex)
                {
                    Log.Fatal("SimpleMeshGenerator: GenerateCylinder: indices.Length != currentIndex.");
                }
            }

            positions = RotateByAxis(axis, positions);
            normals   = RotateByAxis(axis, normals);
            tangents  = RotateByAxis(axis, tangents);
        }
Ejemplo n.º 21
0
        protected void TriangleMeshAdapater(LoadResult objmesh)
        {
            HashSet <string> uniqPairs = new HashSet <string> ();
            List <Face>      newFaces  = new List <Face> ();

            foreach (Face face in objmesh.Groups[0].Faces)
            {
                // Create vertex/tex pairs list
                for (int i = 0; i < face.Count; i++)
                {
                    FaceVertex fv       = face [i];
                    string     pairName = string.Format("{0}/{1}", fv.VertexIndex, fv.TextureIndex < 0 ? 0 : fv.TextureIndex);
                    uniqPairs.Add(pairName);
                }
                // Split quads into triangles
                if (face.Count == 4)                     // a quad
                //throw new NotImplementedException ("Face needs to be triangulated!");
                {
                    Face glface = new Face();
                    glface.AddVertex(new FaceVertex(face [0].VertexIndex, face [0].TextureIndex, face [0].NormalIndex));
                    glface.AddVertex(new FaceVertex(face [2].VertexIndex, face [2].TextureIndex, face [2].NormalIndex));
                    glface.AddVertex(new FaceVertex(face [3].VertexIndex, face [3].TextureIndex, face [3].NormalIndex));
                    // Added the following in Face.cs
                    //public void RemoveVertexAt (int index) { _vertices.RemoveAt (index); }
                    face.RemoveVertexAt(3);
                    newFaces.Add(glface);
                }
                else if (face.Count > 4)
                {
                    throw new NotImplementedException("Face needs to be triangulated!");
                }
            }
            ((List <Face>)(objmesh.Groups [0].Faces)).AddRange(newFaces);

            // Build OpenGL vertex / tex arrrays
            int nbPairs = uniqPairs.Count;

            string [] pairs = new string [nbPairs];
            uniqPairs.CopyTo(pairs);
            Points    = new Point3DCollection(nbPairs);
            TexCoords = new PointCollection(nbPairs);
            foreach (string pairName in pairs)
            {
                string [] def = pairName.Split('/');
                ObjLoader.Loader.Data.VertexData.Vertex vertex = objmesh.Vertices [Convert.ToInt32(def [0]) - 1];
                Points.Add(new Point3D(vertex.X, vertex.Y, vertex.Z));
                ObjLoader.Loader.Data.VertexData.Texture t = objmesh.Textures [Convert.ToInt32(def [1]) == 0 ? 0 : Convert.ToInt32(def [1]) - 1];
                TexCoords.Add(new System.Windows.Point(t.X, 1.0 - t.Y));
                //System.Diagnostics.Debug.Print ("{0}\t- {1},\t{2},\t{3}\t- {4}\t{5}", Points.Count, vertex.X, vertex.Y, vertex.Z, t.X, t.Y) ;
            }
            //System.Diagnostics.Debug.Print (" ") ;

            Normals = new Vector3DCollection();
            Indices = new Int32Collection();
            foreach (Face face in objmesh.Groups[0].Faces)
            {
                for (int i = 0; i < face.Count; i++)
                {
                    FaceVertex fv       = face [i];
                    string     pairName = string.Format("{0}/{1}", fv.VertexIndex, fv.TextureIndex < 0 ? 0 : fv.TextureIndex);
                    int        index    = Array.IndexOf(pairs, pairName);
                    Indices.Add(index);
                    //System.Diagnostics.Debug.Print ("{0}\t/{1}\t= {2}", i, pairName, index) ;
                }
            }
        }
Ejemplo n.º 22
0
        public static void Read(string fileName, ConversionSettings conversionSettings, ref DisplayList dsp, out Dictionary <string, TextureInfo> allMaterials, out string[] messages)
        {
            List <string> messageList   = new List <string>();
            string        currentObject = "";

            Subset            LastFrame    = null;
            List <Subset>     Frames       = new List <Subset>();
            List <Vertex>     Vertices     = new List <Vertex>();
            List <int>        Indices      = new List <int>();
            List <FaceVertex> faceVertices = new List <FaceVertex>();

            List <Vertex> dspVertexBuffer = new List <Vertex>();
            List <int[]>  dspIndexBuffers = new List <int[]>();
            List <int>    dspTextureKeys  = new List <int>();

            int[] dspIndices;
            int   minVertexIndex = 0;

            List <Vector3> positions = new List <Vector3>();
            List <Vector2> texCoords = new List <Vector2>();
            List <Vector3> normals   = new List <Vector3>();

            allMaterials = new Dictionary <string, TextureInfo>();
            allMaterials["<Undefined>"] = new TextureInfo(null);

            string[] fileNameSplit    = fileName.Split(new char[] { '/', '\\' });
            string   fileRelativePath = fileName.Remove(fileName.Length - (fileNameSplit[fileNameSplit.Length - 1].Length), fileNameSplit[fileNameSplit.Length - 1].Length);

            if (!System.IO.File.Exists(fileName))
            {
                messages = new string[] { "File " + fileName + " was not found." };
                return;
            }
            StreamReader rd             = new StreamReader(fileName);
            StreamReader materialReader = null;

            while (!rd.EndOfStream)
            {
                string   line  = rd.ReadLine();
                string[] split = line.Split(' ');
                if (split[0] == "mtllib")
                {
                    materialReader = new StreamReader(fileRelativePath + line.Remove(0, split[0].Length + 1));
                    string currentMtl = null;
                    while (!materialReader.EndOfStream)
                    {
                        string   matLine  = materialReader.ReadLine();
                        string[] matSplit = matLine.Split(' ');
                        if (matSplit[0] == "newmtl")
                        {
                            currentMtl = matLine.Remove(0, matSplit[0].Length);
                        }
                        if (matSplit[0] == "map_Kd")
                        {
                            TextureInfo newTex;
                            string      fullPath = matLine.Remove(0, matSplit[0].Length).Trim();
                            if (fullPath[1] != ':')
                            {
                                fullPath = fileRelativePath + fullPath;
                            }
                            allMaterials.Add(currentMtl, newTex = new TextureInfo(fullPath));
                        }
                    }
                }
                else if (split[0] == "o") //Object
                {
                    if (LastFrame == null)
                    {
                        LastFrame = new Subset();
                    }
                    currentObject = split[1];
                }
                else if (split[0] == "v") // Vertex
                {
                    positions.Add(cvt.ParseVector3(split, 1));
                }
                else if (split[0] == "vn")// Vertex Normal
                {
                    normals.Add(cvt.ParseVector3(split, 1));
                }
                else if (split[0] == "vt") // Vertex TexCoord
                {
                    texCoords.Add(cvt.parseVector2(split, 1));
                }
                else if (split[0] == "usemtl")
                {
                    LastFrame.VertexBuffer = Vertices.ToArray();
                    LastFrame.IndexBuffer  = Indices.ToArray();

                    dspIndices = new int[LastFrame.IndexBuffer.Length];
                    for (int i = 0; i < LastFrame.IndexBuffer.Length; i += 3)
                    {
                        dspIndices[i]     = LastFrame.IndexBuffer[i + 2] + minVertexIndex;
                        dspIndices[i + 1] = LastFrame.IndexBuffer[i + 1] + minVertexIndex;
                        dspIndices[i + 2] = LastFrame.IndexBuffer[i] + minVertexIndex;
                    }

                    if (Indices.Count > 0)
                    {
                        dspIndexBuffers.Add(dspIndices);
                        LastFrame.CreatePatches();
                        Frames.Add(LastFrame);
                    }
                    Indices.Clear();
                    LastFrame = new Subset();
                    string mtlName = line.Remove(0, split[0].Length);
                    if (!allMaterials.TryGetValue(mtlName, out LastFrame.Texture))
                    {
                        messageList.Add("Object " + currentObject + " has unassigned faces.");
                        LastFrame.Texture = allMaterials["<Undefined>"];
                    }
                }
                else if (split[0] == "f") // Face
                {
                    int i0 = 0, ix = 0;
                    for (int i = 1; i < split.Length; i++)
                    {
                        string[]   vertexIndices = split[i].Split('/');
                        FaceVertex faceVertex    = new FaceVertex();
                        int.TryParse(vertexIndices[0], out faceVertex.Vertex);
                        if (vertexIndices.Length > 1)
                        {
                            int.TryParse(vertexIndices[1], out faceVertex.Texture);
                        }
                        if (vertexIndices.Length > 2)
                        {
                            int.TryParse(vertexIndices[2], out faceVertex.Normal);
                        }
                        int index = 0;
                        foreach (FaceVertex v in faceVertices)
                        {
                            if (v.Vertex == faceVertex.Vertex && v.Texture == faceVertex.Texture && v.Normal == faceVertex.Normal)
                            {
                                break;
                            }
                            index++;
                        }
                        if (i > 3)
                        {
                            Indices.Add(i0);
                            Indices.Add(ix);
                        }
                        Indices.Add(index);

                        if (i == 1)
                        {
                            i0 = index;
                        }
                        ix = index;
                        if (index == faceVertices.Count)
                        {
                            faceVertices.Add(faceVertex);
                            Vertex  newVertex;
                            Vector2 texCoord = Vector2.Empty;
                            if (faceVertex.Texture > 0)
                            {
                                texCoord = texCoords[faceVertex.Texture - 1];
                            }
                            Vector3 normal = Vector3.Empty;
                            if (faceVertex.Normal > 0)
                            {
                                normal = normals[faceVertex.Normal - 1];
                            }

                            Vertices.Add(newVertex = new Vertex(positions[faceVertex.Vertex - 1], texCoord, normal));
                            dspVertexBuffer.Add(newVertex);
                        }
                    }
                }
            }
            rd.BaseStream.Close();
            materialReader.Close();
            LastFrame.IndexBuffer  = Indices.ToArray();
            LastFrame.VertexBuffer = Vertices.ToArray();

            dspIndices = new int[LastFrame.IndexBuffer.Length];
            for (int i = 0; i < LastFrame.IndexBuffer.Length; i += 3)
            {
                dspIndices[i]     = LastFrame.IndexBuffer[i + 2] + minVertexIndex;
                dspIndices[i + 1] = LastFrame.IndexBuffer[i + 1] + minVertexIndex;
                dspIndices[i + 2] = LastFrame.IndexBuffer[i] + minVertexIndex;
            }
            dspIndexBuffers.Add(dspIndices);

            LastFrame.CreatePatches();
            Frames.Add(LastFrame);

            dsp.subsets = Frames.ToArray();
            messages    = messageList.ToArray();
        }
Ejemplo n.º 23
0
        public void Push(FaceVertex face, Model_Prefab_Transform[] transforms)
        {
            var vIdx = face.VertexIndex - 1;
            var nIdx = face.NormalIndex - 1;
            var tIdx = face.TextureIndex - 1;
            //PLog.Info("vIdx<{0}>  nIdx<{1}>  tIdx<{2}>", vIdx, nIdx, tIdx);
            var scaleVec = Vector3.one;

            if (Model.Vertices.Count > vIdx && vIdx > -1)
            {
                var   v = Model.Vertices[vIdx];
                float sX = 1f, sY = 1f, sZ = 1f;

                if (transforms != null)
                {
                    foreach (var trans in transforms)
                    {
                        switch (trans)
                        {
                        case Model_Prefab_Transform.Flip_X:
                            sX = -1f;
                            break;

                        case Model_Prefab_Transform.Flip_Y:
                            sY = -1f;
                            break;

                        case Model_Prefab_Transform.Flip_Z:
                            sZ = -1f;
                            break;

                        default:
                            throw new NotImplementedException($"Model_Prefab_Transform: {Enum.GetName(typeof(Model_Prefab_Transform), trans)} is not yet implemented!");
                            break;
                        }
                    }
                }

                scaleVec = new Vector3(sX, sY, sZ);
                var vert = new Vector3(v.X, v.Y, v.Z);
                vert.Scale(scaleVec);

                var vi = verts.Length;
                Push_Vert(vert);
                Push_Indice(vi);
            }

            if (Model.Normals.Count > nIdx && nIdx > -1)
            {
                var n      = Model.Normals[nIdx];
                var normal = new Vector3(n.X, n.Y, n.Z);
                normal.Scale(scaleVec);
                Push_Normal(normal);
            }

            if (Model.Textures.Count <= tIdx || tIdx <= -1)
            {
                return;
            }

            var u = Model.Textures[tIdx];

            Push_UV(new Vector2(u.X, u.Y));
        }