예제 #1
0
        public static OptFile An8ToOpt(string an8Path, bool scale)
        {
            string an8Directory = Path.GetDirectoryName(an8Path);

            var an8 = An8File.FromFile(an8Path);
            var opt = new OptFile();

            foreach (var mesh in an8.Objects
                .SelectMany(t => t.Components)
                .SelectMany(t => Converter.EnumMeshes(t)))
            {
                var optMesh = new Mesh();
                opt.Meshes.Add(optMesh);

                if (scale)
                {
                    foreach (var v in mesh.Points)
                    {
                        optMesh.Vertices.Add(new Vector(v.X / OptFile.ScaleFactor, v.Z / OptFile.ScaleFactor, v.Y / OptFile.ScaleFactor));
                    }
                }
                else
                {
                    foreach (var v in mesh.Points)
                    {
                        optMesh.Vertices.Add(new Vector(v.X, v.Z, v.Y));
                    }
                }

                foreach (var v in mesh.TexCoords)
                {
                    optMesh.TextureCoordinates.Add(new TextureCoordinates(v.U, -v.V));
                }

                foreach (var v in mesh.Normals)
                {
                    optMesh.VertexNormals.Add(new Vector(v.X, v.Z, v.Y));
                }

                optMesh.TextureCoordinates.Add(new TextureCoordinates(0, 0));
                optMesh.TextureCoordinates.Add(new TextureCoordinates(1, 0));
                optMesh.TextureCoordinates.Add(new TextureCoordinates(1, 1));
                optMesh.TextureCoordinates.Add(new TextureCoordinates(0, 1));

                var optLod = new MeshLod();
                optMesh.Lods.Add(optLod);

                foreach (var face in mesh.Faces)
                {
                    if (face.PointIndexes.Length < 3)
                    {
                        continue;
                    }

                    bool isQuad = face.PointIndexes.Length > 3;

                    var optFaceGroup = new FaceGroup();
                    optLod.FaceGroups.Add(optFaceGroup);

                    var materialName = mesh.MaterialList.ElementAtOrDefault(face.MaterialIndex);

                    if (!string.IsNullOrEmpty(materialName))
                    {
                        optFaceGroup.Textures.Add(materialName);
                    }

                    Index verticesIndex = new Index(
                        face.PointIndexes[0],
                        face.PointIndexes[1],
                        face.PointIndexes[2],
                        isQuad ? face.PointIndexes[3] : -1);

                    if (verticesIndex.A >= optMesh.Vertices.Count)
                    {
                        verticesIndex.A = 0;
                    }

                    if (verticesIndex.B >= optMesh.Vertices.Count)
                    {
                        verticesIndex.B = 0;
                    }

                    if (verticesIndex.C >= optMesh.Vertices.Count)
                    {
                        verticesIndex.C = 0;
                    }

                    if (verticesIndex.D >= optMesh.Vertices.Count)
                    {
                        verticesIndex.D = 0;
                    }

                    Index textureCoordinatesIndex = new Index(
                        face.TexCoordIndexes[0],
                        face.TexCoordIndexes[1],
                        face.TexCoordIndexes[2],
                        isQuad ? face.TexCoordIndexes[3] : -1);

                    if (textureCoordinatesIndex.A >= optMesh.TextureCoordinates.Count)
                    {
                        textureCoordinatesIndex.A = 0;
                    }

                    if (textureCoordinatesIndex.B >= optMesh.TextureCoordinates.Count)
                    {
                        textureCoordinatesIndex.B = 0;
                    }

                    if (textureCoordinatesIndex.C >= optMesh.TextureCoordinates.Count)
                    {
                        textureCoordinatesIndex.C = 0;
                    }

                    if (textureCoordinatesIndex.D >= optMesh.TextureCoordinates.Count)
                    {
                        textureCoordinatesIndex.D = 0;
                    }

                    Index vertexNormalsIndex = new Index(
                        face.NormalIndexes[0],
                        face.NormalIndexes[1],
                        face.NormalIndexes[2],
                        isQuad ? face.NormalIndexes[3] : -1);

                    if (vertexNormalsIndex.A >= optMesh.VertexNormals.Count)
                    {
                        vertexNormalsIndex.A = 0;
                    }

                    if (vertexNormalsIndex.B >= optMesh.VertexNormals.Count)
                    {
                        vertexNormalsIndex.B = 0;
                    }

                    if (vertexNormalsIndex.C >= optMesh.VertexNormals.Count)
                    {
                        vertexNormalsIndex.C = 0;
                    }

                    if (vertexNormalsIndex.D >= optMesh.VertexNormals.Count)
                    {
                        vertexNormalsIndex.D = 0;
                    }

                    if (textureCoordinatesIndex.A < 0 || textureCoordinatesIndex.B < 0 || textureCoordinatesIndex.C < 0 || (verticesIndex.D >= 0 && textureCoordinatesIndex.D < 0))
                    {
                        textureCoordinatesIndex.A = optMesh.TextureCoordinates.Count - 4;
                        textureCoordinatesIndex.B = optMesh.TextureCoordinates.Count - 3;
                        textureCoordinatesIndex.C = optMesh.TextureCoordinates.Count - 2;
                        textureCoordinatesIndex.D = verticesIndex.D < 0 ? -1 : optMesh.TextureCoordinates.Count - 1;
                    }

                    Vector normal = Vector.Normal(
                        optMesh.Vertices.ElementAtOrDefault(verticesIndex.A),
                        optMesh.Vertices.ElementAtOrDefault(verticesIndex.B),
                        optMesh.Vertices.ElementAtOrDefault(verticesIndex.C));

                    if (vertexNormalsIndex.A < 0 || vertexNormalsIndex.B < 0 || vertexNormalsIndex.C < 0 || (verticesIndex.D >= 0 && vertexNormalsIndex.D < 0))
                    {
                        optMesh.VertexNormals.Add(normal);

                        vertexNormalsIndex.A = optMesh.VertexNormals.Count - 1;
                        vertexNormalsIndex.B = optMesh.VertexNormals.Count - 1;
                        vertexNormalsIndex.C = optMesh.VertexNormals.Count - 1;
                        vertexNormalsIndex.D = verticesIndex.D < 0 ? -1 : optMesh.VertexNormals.Count - 1;
                    }

                    var optFace = new Face()
                    {
                        VerticesIndex = verticesIndex,
                        TextureCoordinatesIndex = textureCoordinatesIndex,
                        VertexNormalsIndex = vertexNormalsIndex,
                        Normal = normal
                    };

                    optFaceGroup.Faces.Add(optFace);
                }
            }

            opt.CompactBuffers();
            opt.ComputeHitzones();

            foreach (var material in an8.Materials
                .Concat(an8.Objects.SelectMany(t => t.Materials))
                .Where(t => t.FrontSurface != null)
                .Select(t => new
                {
                    Name = t.Name,
                    Diffuse = t.FrontSurface.Diffuse,
                    Alpha = t.FrontSurface.Alpha
                }))
            {
                Texture texture;

                var an8Texture = material.Diffuse.TextureName != null ?
                    an8.Textures.FirstOrDefault(t => string.Equals(t.Name, material.Diffuse.TextureName, StringComparison.Ordinal)) :
                    null;

                if (an8Texture == null)
                {
                    byte r = material.Diffuse.Red;
                    byte g = material.Diffuse.Green;
                    byte b = material.Diffuse.Blue;

                    int width = 8;
                    int height = 8;
                    int length = width * height;
                    byte[] data = new byte[length * 4];

                    for (int i = 0; i < length; i++)
                    {
                        data[i * 4 + 0] = b;
                        data[i * 4 + 1] = g;
                        data[i * 4 + 2] = r;
                        data[i * 4 + 3] = 255;
                    }

                    texture = new Texture();
                    texture.Name = material.Name;
                    texture.Width = width;
                    texture.Height = height;
                    texture.ImageData = data;
                }
                else
                {
                    string colorFileName = Path.Combine(an8Directory, Path.GetFileName(an8Texture.Files[0]));

                    texture = Texture.FromFile(colorFileName);
                    texture.Name = material.Name;
                }

                if (material.Alpha > 0 && material.Alpha < 255)
                {
                    byte alpha = (byte)material.Alpha;

                    int length = texture.Width * texture.Height;

                    byte[] alphaData = new byte[length];
                    var data = texture.ImageData;

                    for (int i = 0; i < length; i++)
                    {
                        alphaData[i] = alpha;
                        data[i * 4 + 3] = alpha;
                    }

                    texture.AlphaData = alphaData;
                }

                opt.Textures.Add(texture.Name, texture);
            }

            opt.GenerateTexturesMipmaps();

            return opt;
        }
예제 #2
0
        public static OptFile RhinoToOpt(string rhinoPath, bool scale)
        {
            string rhinoDirectory = Path.GetDirectoryName(rhinoPath);

            var opt = new OptFile();

            using (var file = Rhino.FileIO.File3dm.Read(rhinoPath))
            {
                float scaleFactor = scale ? (1.0f / OptFile.ScaleFactor) : 1.0f;

                if (file.Settings.ModelUnitSystem != Rhino.UnitSystem.Meters)
                {
                    scaleFactor *= (float)Rhino.RhinoMath.UnitScale(file.Settings.ModelUnitSystem, Rhino.UnitSystem.Meters);
                    scale = true;
                }

                var groups = file.Objects
                    .Where(t =>
                    {
                        using (var geometry = t.Geometry)
                        {
                            return geometry.ObjectType == Rhino.DocObjects.ObjectType.Mesh;
                        }
                    })
                    .GroupBy(t =>
                    {
                        using (var attributes = t.Attributes)
                        {
                            return attributes.LayerIndex;
                        }
                    })
                    .ToList();

                foreach (var group in groups)
                {
                    var mesh = new Mesh();
                    opt.Meshes.Add(mesh);

                    var lod = new MeshLod();
                    mesh.Lods.Add(lod);

                    foreach (var obj in group)
                    {
                        var faceGroup = new FaceGroup();
                        lod.FaceGroups.Add(faceGroup);

                        int baseIndex = mesh.Vertices.Count;

                        using (var geometry = (Rhino.Geometry.Mesh)obj.Geometry)
                        {
                            if (scale)
                            {
                                foreach (var vertex in geometry.Vertices)
                                {
                                    mesh.Vertices.Add(new Vector(vertex.X * scaleFactor, vertex.Y * scaleFactor, vertex.Z * scaleFactor));
                                }
                            }
                            else
                            {
                                foreach (var vertex in geometry.Vertices)
                                {
                                    mesh.Vertices.Add(new Vector(vertex.X, vertex.Y, vertex.Z));
                                }
                            }

                            foreach (var texCoords in geometry.TextureCoordinates)
                            {
                                mesh.TextureCoordinates.Add(new TextureCoordinates(texCoords.X, -texCoords.Y));
                            }

                            foreach (var normal in geometry.Normals)
                            {
                                mesh.VertexNormals.Add(new Vector(normal.X, normal.Y, normal.Z));
                            }

                            foreach (var geoFace in geometry.Faces)
                            {
                                var face = new Face();
                                faceGroup.Faces.Add(face);

                                Index index = geoFace.IsTriangle ?
                                    new Index(baseIndex + geoFace.C, baseIndex + geoFace.B, baseIndex + geoFace.A) :
                                    new Index(baseIndex + geoFace.D, baseIndex + geoFace.C, baseIndex + geoFace.B, baseIndex + geoFace.A);

                                face.VerticesIndex = index;
                                face.VertexNormalsIndex = index;
                                face.TextureCoordinatesIndex = index;

                                face.Normal = Vector.Normal(mesh.Vertices[index.A], mesh.Vertices[index.B], mesh.Vertices[index.C]);
                            }
                        }

                        using (var attributes = obj.Attributes)
                        {
                            if (attributes.MaterialIndex != -1)
                            {
                                using (var material = file.Materials[attributes.MaterialIndex])
                                {
                                    faceGroup.Textures.Add(material.Name);
                                }
                            }
                        }
                    }
                }

                opt.CompactBuffers();
                opt.ComputeHitzones();

                for (int materialIndex = 0; materialIndex < file.Materials.Count; materialIndex++)
                {
                    using (var material = file.Materials[materialIndex])
                    {
                        if (opt.Textures.ContainsKey(material.Name))
                        {
                            continue;
                        }

                        string colorMap = null;
                        string alphaMap = null;

                        using (var tex = material.GetBitmapTexture())
                        {
                            if (tex != null && !string.IsNullOrEmpty(tex.FileName))
                            {
                                colorMap = Path.GetFileName(tex.FileName);
                            }
                        }

                        using (var tex = material.GetTransparencyTexture())
                        {
                            if (tex != null && !string.IsNullOrEmpty(tex.FileName))
                            {
                                alphaMap = Path.GetFileName(tex.FileName);
                            }
                        }

                        Texture texture;

                        if (colorMap == null)
                        {
                            var color = material.DiffuseColor;
                            byte r = color.R;
                            byte g = color.G;
                            byte b = color.B;

                            int width = 8;
                            int height = 8;
                            int length = width * height;
                            byte[] data = new byte[length * 4];

                            for (int i = 0; i < length; i++)
                            {
                                data[i * 4 + 0] = b;
                                data[i * 4 + 1] = g;
                                data[i * 4 + 2] = r;
                                data[i * 4 + 3] = 255;
                            }

                            texture = new Texture();
                            texture.Name = material.Name;
                            texture.Width = width;
                            texture.Height = height;
                            texture.ImageData = data;
                        }
                        else
                        {
                            string colorFileName = Path.Combine(rhinoDirectory, colorMap);

                            texture = Texture.FromFile(colorFileName);
                            texture.Name = material.Name;
                        }

                        if (alphaMap != null)
                        {
                            string alphaFileName = Path.Combine(rhinoDirectory, alphaMap);

                            texture.SetAlphaMap(alphaFileName);
                        }
                        else if (material.Transparency > 0.0 && material.Transparency < 1.0)
                        {
                            byte alpha = (byte)(material.Transparency * 255.0f);

                            int length = texture.Width * texture.Height;

                            byte[] alphaData = new byte[length];
                            var data = texture.ImageData;

                            for (int i = 0; i < length; i++)
                            {
                                alphaData[i] = alpha;
                                data[i * 4 + 3] = alpha;
                            }

                            texture.AlphaData = alphaData;
                        }

                        opt.Textures.Add(texture.Name, texture);
                    }
                }

                opt.GenerateTexturesMipmaps();
            }

            return opt;
        }