Beispiel #1
0
 public Picture(BinaryReaderX br) : base(br)
 {
     vertexColorLT      = new Color4(br);
     vertexColorRT      = new Color4(br);
     vertexColorLB      = new Color4(br);
     vertexColorRB      = new Color4(br);
     matID              = br.ReadUInt16();
     texCoordEntryCount = br.ReadUInt16();
     TexCoordEntries    = new TexCoord[texCoordEntryCount];
     for (int i = 0; i < texCoordEntryCount; i++)
     {
         TexCoordEntries[i] = new TexCoord(br);
     }
 }
Beispiel #2
0
 public WindowContent(EndianBinaryReader er)
 {
     VertexColorLT     = er.ReadColor8();
     VertexColorRT     = er.ReadColor8();
     VertexColorLB     = er.ReadColor8();
     VertexColorRB     = er.ReadColor8();
     MaterialId        = er.ReadUInt16();
     NrTexCoordEntries = er.ReadUInt16();
     TexCoordEntries   = new TexCoord[NrTexCoordEntries];
     for (int i = 0; i < NrTexCoordEntries; i++)
     {
         TexCoordEntries[i] = new TexCoord(er);
     }
 }
Beispiel #3
0
 public pic1(EndianBinaryReader er)
     : base(er)
 {
     VertexColorLT = er.ReadColor8();
     VertexColorRT = er.ReadColor8();
     VertexColorLB = er.ReadColor8();
     VertexColorRB = er.ReadColor8();
     MaterialId = er.ReadUInt16();
     NrTexCoordEntries = er.ReadUInt16();
     TexCoordEntries = new TexCoord[NrTexCoordEntries];
     for (int i = 0; i < NrTexCoordEntries; i++)
     {
         TexCoordEntries[i] = new TexCoord(er);
     }
 }
Beispiel #4
0
        public PIC1(Header header, string name) : base()
        {
            LoadDefaults();
            Name = name;

            ParentLayout = header;

            ColorTopLeft     = STColor8.White;
            ColorTopRight    = STColor8.White;
            ColorBottomLeft  = STColor8.White;
            ColorBottomRight = STColor8.White;
            TexCoords        = new TexCoord[1];
            TexCoords[0]     = new TexCoord();

            Material = new Material(name, header);
        }
 public BSEffectShaderProperty()
 {
     shaderFlags1_sk     = (SkyrimShaderPropertyFlags1)2147483648;
     shaderFlags2_sk     = (SkyrimShaderPropertyFlags2)32;
     shaderFlags1_fo4    = (Fallout4ShaderPropertyFlags1)2147483648;
     shaderFlags2_fo4    = (Fallout4ShaderPropertyFlags2)32;
     uvScale             = 1.0, 1.0;
     textureClampMode    = (byte)0;
     lightingInfluence   = (byte)0;
     envMapMinLod        = (byte)0;
     unknownByte         = (byte)0;
     falloffStartAngle   = 1.0f;
     falloffStopAngle    = 1.0f;
     falloffStartOpacity = 0.0f;
     falloffStopOpacity  = 0.0f;
     emissiveMultiple    = 0.0f;
     softFalloffDepth    = 0.0f;
     environmentMapScale = 0.0f;
 }
        internal override void Process(ParsingContext context)
        {
            var reader = context.reader;
            var chunk = this;

            int cnt = reader.ReadUInt16();
            chunk.BytesRead += 2;

            Console.WriteLine("	TexCoords: {0}", cnt);
            var texCoords = new TexCoord[cnt];
            for (int ii = 0; ii < cnt; ii++)
            {
                texCoords[ii] = new TexCoord(reader.ReadSingle(), reader.ReadSingle());
            }

            chunk.BytesRead += (uint)(cnt * (4 * 2));

            this.texCoords = texCoords;
        }
Beispiel #7
0
        public bool Equals(Vertex vertex, bool checkBones)
        {
            if (checkBones)
            {
                if (BoneWeights.Count != vertex.BoneWeights.Count)
                {
                    return(false);
                }

                if (!BoneWeights.SequenceEqual(vertex.BoneWeights))
                {
                    return(false);
                }
            }

            return(Position.Equals(vertex.Position) &&
                   Normal.Equals(vertex.Normal) &&
                   TexCoord.Equals(vertex.TexCoord));
        }
Beispiel #8
0
 //Constructor
 public TexDesc()
 {
     unchecked {
         image               = null;
         source              = null;
         clampMode           = TexClampMode.WRAP_S_WRAP_T;
         filterMode          = TexFilterMode.FILTER_TRILERP;
         flags               = (ushort)0;
         maxAnisotropy       = (ushort)0;
         uvSet               = (uint)0;
         ps2L                = (short)0;
         ps2K                = (short)-75;
         unknown1            = (ushort)0;
         hasTextureTransform = false;
         scale               = 1.0, 1.0;
         rotation            = 0.0f;
         transformMethod     = (TransformMethod)0;
     }
 }
Beispiel #9
0
        internal override void Process(ParsingContext context)
        {
            var reader = context.reader;
            var chunk  = this;

            int cnt = reader.ReadUInt16();

            chunk.BytesRead += 2;

            Console.WriteLine("	TexCoords: {0}", cnt);
            var texCoords = new TexCoord[cnt];

            for (int ii = 0; ii < cnt; ii++)
            {
                texCoords[ii] = new TexCoord(reader.ReadSingle(), reader.ReadSingle());
            }

            chunk.BytesRead += (uint)(cnt * (4 * 2));

            this.texCoords = texCoords;
        }
Beispiel #10
0
        public PIC1(FileReader reader, BLOHeader header) : base(reader, header)
        {
            byte numParams = reader.ReadByte();

            if (numParams > 0)
            {
                TextureName = BloResource.Read(reader, header);
                numParams--;
            }
            if (numParams > 0)
            {
                PaletteName = BloResource.Read(reader, header);
                numParams--;
            }
            if (numParams > 0)
            {
                Binding = reader.ReadByte();
                numParams--;
            }

            Material = new Material();

            if (TextureName == string.Empty)
            {
                Material.TextureMaps = new BxlytTextureRef[0];
            }
            else
            {
                Material.TextureMaps    = new BxlytTextureRef[1];
                Material.TextureMaps[0] = new BxlytTextureRef()
                {
                    Name = TextureName,
                };
            }


            TexCoords    = new TexCoord[1];
            TexCoords[0] = new TexCoord();
        }
 public BSLightingShaderProperty()
 {
     shaderFlags1_sk             = (SkyrimShaderPropertyFlags1)2185233153;
     shaderFlags2_sk             = (SkyrimShaderPropertyFlags2)32801;
     shaderFlags1_fo4            = (Fallout4ShaderPropertyFlags1)2151678465;
     shaderFlags2_fo4            = (Fallout4ShaderPropertyFlags2)1;
     uvScale                     = (1.0, 1.0);
     textureSet                  = null;
     emissiveColor               = (0.0, 0.0, 0.0);
     emissiveMultiple            = 0.0f;
     textureClampMode            = (TexClampMode)3;
     alpha                       = 1.0f;
     refractionStrength          = 0.0f;
     glossiness                  = 80f;
     smoothness                  = 1.0f;
     specularStrength            = 1.0f;
     lightingEffect1             = 0.3f;
     lightingEffect2             = 2.0f;
     subsurfaceRolloff           = 0.3f;
     rimlightPower               = 3.402823466e+38f;
     backlightPower              = 0.0f;
     grayscaleToPaletteScale     = 0.0f;
     fresnelPower                = 5.0f;
     wetnessSpecScale            = -1.0f;
     wetnessSpecPower            = -1.0f;
     wetnessMinVar               = -1.0f;
     wetnessEnvMapScale          = -1.0f;
     wetnessFresnelPower         = -1.0f;
     wetnessMetalness            = -1.0f;
     environmentMapScale         = 1.0f;
     unknownEnvMapShort          = (ushort)0;
     unknownSkinTintInt          = (uint)0;
     maxPasses                   = 0.0f;
     scale                       = 0.0f;
     parallaxInnerLayerThickness = 0.0f;
     parallaxRefractionScale     = 0.0f;
     parallaxEnvmapStrength      = 0.0f;
     eyeCubemapScale             = 0.0f;
 }
Beispiel #12
0
        public bool Equals(Vertex other)
        {
            const float precision = 0.00001f;

            if (other == null)
            {
                return(false);
            }
            if (Influence != other.Influence)
            {
                return(false);
            }
            if (!Position.Equals(other.Position, precision))
            {
                return(false);
            }
            if (!Normal.Equals(other.Normal, precision))
            {
                return(false);
            }
            if (!Binormal.Equals(other.Binormal, precision))
            {
                return(false);
            }
            if (!Tangent.Equals(other.Tangent, precision))
            {
                return(false);
            }
            if (!Color.Equals(other.Color, precision))
            {
                return(false);
            }
            if (!TexCoord.Equals(other.TexCoord, precision))
            {
                return(false);
            }
            return(true);
        }
Beispiel #13
0
        public PIC2(FileReader reader, BLOHeader header) : base(reader, header)
        {
            TexCoords    = new TexCoord[1];
            TexCoords[0] = new TexCoord();

            ushort sectionSize = reader.ReadUInt16();

            Console.WriteLine($"PIC2 {sectionSize}");
            MaterialIndex = reader.ReadUInt16();
            Material      = header.Materials[MaterialIndex];
            uint unk = reader.ReadUInt32();
            //These increase for each material
            ushort index1 = reader.ReadUInt16();
            ushort index2 = reader.ReadUInt16();
            ushort index3 = reader.ReadUInt16();
            ushort index4 = reader.ReadUInt16();

            //I think these are texture coordinates
            TexCoords[0].TopLeft = new Vector2F(
                reader.ReadInt16() / 256f,
                reader.ReadInt16() / 256f);
            TexCoords[0].TopRight = new Vector2F(
                reader.ReadInt16() / 256f,
                reader.ReadInt16() / 256f);
            TexCoords[0].BottomLeft = new Vector2F(
                reader.ReadInt16() / 256f,
                reader.ReadInt16() / 256f);
            TexCoords[0].BottomRight = new Vector2F(
                reader.ReadInt16() / 256f,
                reader.ReadInt16() / 256f);

            ColorTopLeft     = STColor8.FromBytes(reader.ReadBytes(4));
            ColorTopRight    = STColor8.FromBytes(reader.ReadBytes(4));
            ColorBottomLeft  = STColor8.FromBytes(reader.ReadBytes(4));
            ColorBottomRight = STColor8.FromBytes(reader.ReadBytes(4));
        }
        public void Read(Reader reader)
        {
            offset = Pointer.Current(reader);
            if (geo.Type == 4 || geo.Type == 5 || geo.Type == 6)
            {
                // Optimized
                num_vertices_actual = reader.ReadUInt32();
                num_vertices        = reader.ReadUInt32();
                num_uvs             = reader.ReadUInt32();
                unk3 = reader.ReadUInt32();
            }
            else
            {
                num_vertices        = geo.num_triangles[index] * 3;
                num_uvs             = (num_vertices + 3) >> 2;
                num_vertices_actual = num_vertices;
            }
            VisualMaterial vm = geo.visualMaterials[index];
            bool           hasUv0 = true, hasUv1 = false, hasNormals = false;
            uint           num_textures = 1;

            if (vm != null && vm.num_textures_in_material > 0)
            {
                hasUv0       = false;
                num_textures = vm.num_textures_in_material;
                for (int i = 0; i < vm.num_textures_in_material; i++)
                {
                    switch (vm.textures[i].uvFunction)
                    {
                    case 4: hasNormals = true; break;

                    case 1: hasUv1 = true; break;

                    case 0: hasUv0 = true; break;
                    }
                }
            }
            vertices = new Vertex[num_vertices];
            for (int i = 0; i < num_vertices; i++)
            {
                vertices[i] = new Vertex(reader);
            }
            if (geo.Type == 1 && Settings.s.game == Settings.Game.R3)
            {
                uvUnoptimized = new UVUnoptimized[num_vertices];
                for (int i = 0; i < uvUnoptimized.Length; i++)
                {
                    uvUnoptimized[i] = new UVUnoptimized(reader);
                }
            }
            else
            {
                if (hasUv0)
                {
                    uv0 = new TexCoord[num_uvs];
                    for (int i = 0; i < uv0.Length; i++)
                    {
                        uv0[i] = new TexCoord(reader);
                    }
                }
                if (hasUv1)
                {
                    uv1 = new TexCoord[num_uvs];
                    for (int i = 0; i < uv1.Length; i++)
                    {
                        uv1[i] = new TexCoord(reader);
                    }
                }
                if (hasNormals)
                {
                    normals = new Normal[num_vertices];
                    for (int i = 0; i < normals.Length; i++)
                    {
                        normals[i] = new Normal(reader);
                    }
                }
                if ((geo.flags & 0x100) != 0)
                {
                    uv_unk = new TexCoord[num_uvs];
                    for (int i = 0; i < uv_unk.Length; i++)
                    {
                        uv_unk[i] = new TexCoord(reader);
                    }
                }
            }
            colors = new VertexColor[num_textures][];             // Seem to be in a color-like format? 7F 7F 7F 80, repeated 4 times
            for (int i = 0; i < colors.Length; i++)
            {
                colors[i] = new VertexColor[num_uvs];
                for (int j = 0; j < colors[i].Length; j++)
                {
                    colors[i][j] = new VertexColor(reader);
                }
            }
            if (geo.isSinus != 0)
            {
                sinusState = new VectorForSinusEffect[num_uvs];
                for (int i = 0; i < sinusState.Length; i++)
                {
                    sinusState[i] = new VectorForSinusEffect(reader);
                }
            }
            if ((index < geo.num_elements - 1 && Pointer.Current(reader) != geo.off_elements_array[index + 1]) ||
                (index == geo.num_elements - 1 && Pointer.Current(reader) != geo.off_uint1))
            {
                UnityEngine.Debug.LogWarning("B " + geo.Offset + " - " + offset + " - " + hasUv0 + " - " + hasUv1 + " - " + hasNormals);
            }
            else
            {
                //UnityEngine.Debug.LogWarning("G " + geo.Offset + " - " + offset + " - " + hasUv0 + " - " + hasUv1 + " - " + hasUv4);
            }

            /*normals = new Vertex[num_vertices];
             * for (int i = 0; i < num_vertices; i++) {
             *      normals[i] = new Vertex(reader);
             * }*/
        }
Beispiel #15
0
 protected bool Equals(TexCoord other)
 {
     return(MinU.Equals(other.MinU) && MinV.Equals(other.MinV) && MaxU.Equals(other.MaxU) && MaxV.Equals(other.MaxV));
 }
Beispiel #16
0
        //public override bool Equals(object obj)
        //{
        //    return obj is Vertex vertex &&
        //           Position.Equals(vertex.Position) &&
        //           Normal.Equals(vertex.Normal) &&
        //           TexCoord.Equals(vertex.TexCoord);
        //}

        public bool Equals(Vertex vertex)
        {
            return(Position.Equals(vertex.Position) &&
                   Normal.Equals(vertex.Normal) &&
                   TexCoord.Equals(vertex.TexCoord));
        }
Beispiel #17
0
 public static void NifStream(TexCoord val, OStream s, NifInfo info)
 {
     WriteFloat(val.u, s);
     WriteFloat(val.v, s);
 }
        public static void Read(string fileName, ConversionSettings conversionSettings, ref DisplayList dsp, out Dictionary <string, TextureInfo> allMaterials, out string[] messages)
        {
            messages = new string[0];
            if (conversionSettings.colorInterpretation == ConversionSettings.ColorInterpretation.Undefined)
            {
                if (!conversionSettings.DoColorInterpretationDialog())
                {
                    allMaterials = null;
                    return;
                }
            }
            string rootDirectory = System.IO.Path.GetDirectoryName(fileName);

            System.Xml.XmlDataDocument doc = new XmlDataDocument();
            doc.Load(fileName);
            XmlNamespaceManager mgr = new XmlNamespaceManager(doc.NameTable);

            mgr.AddNamespace("df", doc.DocumentElement.NamespaceURI);
            List <Subset> meshes              = new List <Subset>();
            XmlNode       imageLibraryNode    = doc.SelectSingleNode("//df:COLLADA/df:library_images", mgr);
            XmlNode       materialLibraryNode = doc.SelectSingleNode("//df:COLLADA/df:library_materials", mgr);
            XmlNode       effectLibraryNode   = doc.SelectSingleNode("//df:COLLADA/df:library_effects", mgr);
            XmlNode       geometryLibraryNode = doc.SelectSingleNode("//df:COLLADA/df:library_geometries", mgr);
            XmlNode       sceneLibraryNode    = doc.SelectSingleNode("//df:COLLADA/df:library_visual_scenes", mgr);
            XmlNodeList   geometryNodes       = sceneLibraryNode.SelectNodes("df:visual_scene/df:node/df:instance_geometry", mgr);
            bool          flipYZ              = doc.SelectSingleNode("//df:COLLADA/df:asset/df:up_axis", mgr).InnerText == "Z_UP";

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

            foreach (XmlNode geometryNode in geometryNodes)
            {
                XmlNode meshNode      = geometryLibraryNode.SelectSingleNode("df:geometry[@id='" + geometryNode.Attributes["url"].Value.Remove(0, 1) + "']/df:mesh", mgr);
                XmlNode transformNode = geometryNode.SelectSingleNode("../df:matrix[@sid='transform']", mgr);
                Matrix  transform     = Matrix.identity;
                if (transformNode != null)
                {
                    transform.m = Array.ConvertAll <string, float>(transformNode.InnerText.Split(' '), (s) => float.Parse(s, NumberStyles.Any, CultureInfo.InvariantCulture));
                }
                Matrix normalTransform = transform.InvertTranspose();
                foreach (XmlNode trianglesNode in meshNode.SelectNodes("df:triangles", mgr))
                {
                    Subset meshSubset = new Subset();
                    meshes.Add(meshSubset);
                    List <Vertex> vertexBuffer = new List <Vertex>(); //final vertex buffer for this material
                    List <int>    indexBuffer  = new List <int>();    //final index buffer for this material

                    //Data to be read from XML
                    XmlAttribute materialAttribute = trianglesNode.Attributes["material"];
                    if (materialAttribute == null)
                    {
                        messages = new string[] { "Mesh without materials found. Skipping..." };
                        continue;
                    }
                    string  material    = materialAttribute.Value;
                    string  effect      = materialLibraryNode.SelectSingleNode("df:material[@id='" + material + "']/df:instance_effect", mgr).Attributes["url"].Value.Remove(0, 1);
                    XmlNode effectNode  = effectLibraryNode.SelectSingleNode("df:effect[@id='" + effect + "']/df:profile_COMMON", mgr);
                    XmlNode textureNode = effectNode.SelectSingleNode("df:technique/*/df:diffuse/df:texture", mgr);
                    if (textureNode == null)
                    {
                        meshSubset.Texture = allMaterials["<Undefined>"];
                    }
                    else
                    {
                        string surfaceName   = effectNode.SelectSingleNode("df:newparam[@sid='" + textureNode.Attributes["texture"].Value + "']/df:sampler2D/df:source", mgr).InnerText;
                        string init_from     = effectNode.SelectSingleNode("df:newparam[@sid='" + surfaceName + "']/df:surface/df:init_from", mgr).InnerText;
                        string imageFileName = imageLibraryNode.SelectSingleNode("df:image[@id='" + init_from + "']/df:init_from", mgr).InnerText;
                        string fullPath      = imageFileName;
                        if (imageFileName[1] != ':') //Path is not absolute. Make Absolute
                        {
                            fullPath = System.IO.Path.Combine(rootDirectory, imageFileName);
                        }
                        fullPath = Uri.UnescapeDataString(fullPath);
                        if (!allMaterials.TryGetValue(imageFileName, out meshSubset.Texture))
                        {
                            meshSubset.Texture = allMaterials[imageFileName] = new TextureInfo(fullPath);
                        }
                    }

                    int vertexOffset, normalOffset, texCoordOffset, colorOffset;
                    vertexOffset = normalOffset = texCoordOffset = colorOffset = -1;
                    Vec3[]     positions = null, normals = null;
                    TexCoord[] texCoords = null;
                    Color[]    colors    = null;

                    XmlNode vertexNode = trianglesNode.SelectSingleNode("df:input[@semantic='VERTEX']", mgr);
                    if (vertexNode != null)
                    {
                        XmlNode vertexSource = meshNode.SelectSingleNode("df:vertices[@id='" + vertexNode.Attributes["source"].Value.Remove(0, 1) + "']", mgr);
                        XmlNode vertexSourceSource /*jeez pls give me vertex positions now*/ = meshNode.SelectSingleNode("df:source[@id='" + vertexSource.SelectSingleNode("df:input[@semantic='POSITION']", mgr).Attributes["source"].Value.Remove(0, 1) + "']", mgr);
                        positions    = ReadXMLVectorNode <Vec3>(vertexSourceSource, mgr);
                        vertexOffset = int.Parse(vertexNode.Attributes["offset"].Value);
                    }

                    XmlNode normalNode = trianglesNode.SelectSingleNode("df:input[@semantic='NORMAL']", mgr);
                    if (normalNode != null)
                    {
                        XmlNode normalSource = meshNode.SelectSingleNode("df:source[@id='" + normalNode.Attributes["source"].Value.Remove(0, 1) + "']", mgr);
                        normals      = ReadXMLVectorNode <Vec3>(normalSource, mgr);
                        normalOffset = int.Parse(normalNode.Attributes["offset"].Value);
                    }

                    XmlNode texCoordNode = trianglesNode.SelectSingleNode("df:input[@semantic='TEXCOORD']", mgr);
                    if (texCoordNode != null)
                    {
                        XmlNode texCoordSource = meshNode.SelectSingleNode("df:source[@id='" + texCoordNode.Attributes["source"].Value.Remove(0, 1) + "']", mgr);
                        texCoords      = ReadXMLVectorNode <TexCoord>(texCoordSource, mgr);
                        texCoordOffset = int.Parse(texCoordNode.Attributes["offset"].Value);
                    }

                    XmlNode colorNode = trianglesNode.SelectSingleNode("df:input[@semantic='COLOR']", mgr);
                    if (colorNode != null)
                    {
                        XmlNode colorSource = meshNode.SelectSingleNode("df:source[@id='" + colorNode.Attributes["source"].Value.Remove(0, 1) + "']", mgr);
                        colors      = ReadXMLVectorNode <Color>(colorSource, mgr);
                        colorOffset = int.Parse(colorNode.Attributes["offset"].Value);
                    }

                    int[]    indices      = Array.ConvertAll(trianglesNode.SelectSingleNode("df:p", mgr).InnerText.Split(' '), (string s) => int.Parse(s));
                    Vertex[] vertices     = new Vertex[int.Parse(trianglesNode.Attributes["count"].Value) * 3];
                    int      stride       = indices.Length / vertices.Length;
                    int      currentIndex = 0;
                    Color    defaultColor = new Color();
                    defaultColor.R = defaultColor.G = defaultColor.B = defaultColor.A = 1;
                    for (int i = 0; i < vertices.Length; i++)
                    {
                        Vec3 position = positions == null ? new Vec3() : positions[indices[i * stride + vertexOffset]];
                        position = position.TransformPosition(transform);
                        Vec3 normal = normals == null ? new Vec3() : normals[indices[i * stride + normalOffset]];
                        normal = normal.TransformNormal(normalTransform);
                        TexCoord texCoord = texCoords == null ? new TexCoord() : texCoords[indices[i * stride + texCoordOffset]];
                        Color    color    = colors == null ? defaultColor : colors[indices[i * stride + colorOffset]];
                        vertices[i] = flipYZ ? new Vertex(new Vector3(position.X, position.Z, -position.Y), new Vector2(texCoord.S, texCoord.T), new Vector3(normal.X, normal.Z, -normal.Y))
                            : new Vertex(new Vector3(position.X, position.Y, position.Z), new Vector2(texCoord.S, texCoord.T), new Vector3(normal.X, normal.Y, normal.Z));
                        Color c = colors == null ? defaultColor : colors[indices[i * stride + 3]];
                        if (conversionSettings.colorInterpretation == ConversionSettings.ColorInterpretation.ReplaceNormal)
                        {
                            vertices[i].nx = (sbyte)(c.R * 255);
                            vertices[i].ny = (sbyte)(c.G * 255);
                            vertices[i].nz = (sbyte)(c.B * 255);
                            vertices[i].c  = 255;
                        }
                        else if (conversionSettings.colorInterpretation == ConversionSettings.ColorInterpretation.ConvertRedToAlpha)
                        {
                            vertices[i].c = (byte)(c.R * 255);
                        }
                        else if (conversionSettings.colorInterpretation == ConversionSettings.ColorInterpretation.ConvertGreenToAlpha)
                        {
                            vertices[i].c = (byte)(c.G * 255);
                        }
                        else if (conversionSettings.colorInterpretation == ConversionSettings.ColorInterpretation.ConvertBlueToAlpha)
                        {
                            vertices[i].c = (byte)(c.B * 255);
                        }
                        else if (conversionSettings.colorInterpretation == ConversionSettings.ColorInterpretation.ConvertRedToAlpha)
                        {
                            vertices[i].c = (byte)((c.R + c.G + c.B) / 3 * 255);
                        }

                        int k = 0;
                        foreach (Vertex v in vertexBuffer)
                        {
                            if (v.Equals(vertices[i]))
                            {
                                indexBuffer.Add(k);
                                goto skipNewVertex;
                            }
                            k++;
                        }
                        vertexBuffer.Add(vertices[i]);
                        indexBuffer.Add(currentIndex++);
                        skipNewVertex :;
                    }
                    meshSubset.IndexBuffer  = indexBuffer.ToArray();
                    meshSubset.VertexBuffer = vertexBuffer.ToArray();
                    meshSubset.CreatePatches();
                }
            }
            dsp.subsets = meshes.ToArray();
        }
Beispiel #19
0
        /*!
         * Generate or update a NiStringExtraData object with precalculated
         * tangent and binormal data (Oblivion specific)
         * \param[in] method Calculation method. [0 - Nifskope; 1 - Obsidian]
         */
        public void UpdateTangentSpace(int method = 0)
        {
            var niTriGeomData = data as NiTriBasedGeomData;

            /* No data, no tangent space */
            if (niTriGeomData == null)
            {
                throw new Exception("There is no NiTriBasedGeomData attached the NiGeometry upon which UpdateTangentSpace was called.");
            }

            //Check if there are any UVs or Vertices before trying to retrive them
            if (niTriGeomData.UVSetCount == 0)
            {
                //There are no UVs, do nothing
                return;
            }

            if (niTriGeomData.VertexCount == 0)
            {
                //There are no Vertices, do nothing
                return;
            }
            //Get mesh data from data object
            var verts = niTriGeomData.Vertices;
            var norms = niTriGeomData.Normals;
            var tris  = niTriGeomData.GetTriangles();
            var uvs   = niTriGeomData.GetUVSet(0);

            /* check for data validity */
            if (verts.Count != norms.Count || verts.Count != uvs.Count || tris.empty())
            {
                //Do nothing, there is no shape in this data.
                return;
            }

            var tangents   = new Vector3[verts.Count];
            var bitangents = new Vector3[verts.Count];

            if (method == 0) // Nifskope algorithm
            {
                for (int t = 0; t < (int)tris.size(); t++)
                {
                    var tri  = tris[t];
                    var i1   = tri[0];
                    var i2   = tri[1];
                    var i3   = tri[2];
                    var v1   = verts[i1];
                    var v2   = verts[i2];
                    var v3   = verts[i3];
                    var w1   = uvs[i1];
                    var w2   = uvs[i2];
                    var w3   = uvs[i3];
                    var v2v1 = v2 - v1;
                    var v3v1 = v3 - v1;

                    var w2w1 = new TexCoord(w2.u - w1.u, w2.v - w1.v);
                    var w3w1 = new TexCoord(w3.u - w1.u, w3.v - w1.v);
                    var r    = w2w1.u * w3w1.v - w3w1.u * w2w1.v;
                    r = (r >= 0.0f ? +1.0f : -1.0f);
                    var sdir = new Vector3(
                        (w3w1.v * v2v1.x - w2w1.v * v3v1.x) * r,
                        (w3w1.v * v2v1.y - w2w1.v * v3v1.y) * r,
                        (w3w1.v * v2v1.z - w2w1.v * v3v1.z) * r);
                    var tdir = new Vector3(
                        (w2w1.u * v3v1.x - w3w1.u * v2v1.x) * r,
                        (w2w1.u * v3v1.y - w3w1.u * v2v1.y) * r,
                        (w2w1.u * v3v1.z - w3w1.u * v2v1.z) * r);
                    sdir = sdir.Normalized();
                    tdir = tdir.Normalized();

                    // no duplication, just smoothing
                    for (var j = 0; j < 3; j++)
                    {
                        var i = tri[j];
                        tangents[i]   += tdir;
                        bitangents[i] += sdir;
                    }
                }

                // for each vertex calculate tangent and binormal
                for (var i = 0; i < verts.Count; i++)
                {
                    var n = norms[i];
                    var t = tangents[i];
                    var b = bitangents[i];
                    if (t == new Vector3() || b == new Vector3())
                    {
                        t.x = n.y;
                        t.y = n.z;
                        t.z = n.x;
                        b   = n.CrossProduct(t);
                    }
                    else
                    {
                        t = t.Normalized();
                        t = (t - n * n.DotProduct(t));
                        t = t.Normalized();
                        b = b.Normalized();
                        b = (b - n * n.DotProduct(b));
                        b = (b - t * t.DotProduct(b));
                        b = b.Normalized();
                    }
                }
            }
            else if (method == 1)                                   // Obsidian Algorithm
            {
                for (var faceNo = 0; faceNo < tris.Count; ++faceNo) // for each face
                {
                    var t = tris[faceNo];                           // get face
                    int i0 = t[0], i1 = t[1], i2 = t[2];            // get vertex numbers
                    var side_0 = verts[i0] - verts[i1];
                    var side_1 = verts[i2] - verts[i1];

                    var delta_U_0 = uvs[i0].u - uvs[i1].u;
                    var delta_U_1 = uvs[i2].u - uvs[i1].u;
                    var delta_V_0 = uvs[i0].v - uvs[i1].v;
                    var delta_V_1 = uvs[i2].v - uvs[i1].v;

                    var face_tangent    = (side_0 * delta_V_1 - side_1 * delta_V_0).Normalized();
                    var face_bi_tangent = (side_0 * delta_U_1 - side_1 * delta_U_0).Normalized();
                    var face_normal     = (side_0 ^ side_1).Normalized();

                    // no duplication, just smoothing
                    for (var j = 0; j <= 2; j++)
                    {
                        var i = t[j];
                        tangents[i]   += face_tangent;
                        bitangents[i] += face_bi_tangent;
                    }
                }

                // for each.getPosition(), normalize the Tangent and Binormal
                for (var i = 0; i < verts.Count; i++)
                {
                    bitangents[i] = bitangents[i].Normalized();
                    tangents[i]   = tangents[i].Normalized();
                }
            }

            if ((niTriGeomData.TspaceFlag & 0xF0) == 0)
            {
                // generate the byte data
                var vCount  = verts.Count;
                var fSize   = sizeof(float) * 3;
                var binData = new byte[2 * vCount * fSize];
                for (var i = 0; i < verts.Count; i++)
                {
                    float[] tan_xyz = new float[3], bin_xyz = new float[3];
                    tan_xyz[0] = tangents[i].x;
                    tan_xyz[1] = tangents[i].y;
                    tan_xyz[2] = tangents[i].z;
                    bin_xyz[0] = bitangents[i].x;
                    bin_xyz[1] = bitangents[i].y;
                    bin_xyz[2] = bitangents[i].z;

                    var tan_Bytes = BitConverter.GetBytes(tan_xyz);
                    var bin_Bytes = BitConverter.GetBytes(bin_xyz);
                    for (var j = 0; j < fSize; j++)
                    {
                        binData[i * fSize + j]            = tan_Bytes[j];
                        binData[(i + vCount) * fSize + j] = bin_Bytes[j];
                    }
                }

                // update or create the tangent space extra data
                NiBinaryExtraData tspaceRef = null;
                var props = GetExtraData();
                foreach (var prop in props)
                {
                    if (prop.Name == "Tangent space (binormal & tangent vectors)")
                    {
                        tspaceRef = prop as NiBinaryExtraData;
                        break;
                    }
                }
                if (tspaceRef == null)
                {
                    tspaceRef      = new NiBinaryExtraData();
                    tspaceRef.Name = "Tangent space (binormal & tangent vectors)";
                    AddExtraData((NiExtraData)tspaceRef);
                }
                tspaceRef.Data = binData;
            }
            else
            {
                // swap bitangents and tangents: [ niftools-Bugs-2466995 ]
                niTriGeomData.Tangents   = bitangents;
                niTriGeomData.Bitangents = tangents;
            }
        }