Example #1
0
        private VertexDeclaration GetVertexDeclaration(ShaderFX shader)
        {
            var d = new VertexDeclaration();

            d.Types      = VertexDeclarationTypes.GTAV1;
            d.Unknown_6h = 0;

            switch (shader.Name)
            {
            default:
            case 3839837909:     //default
                d.Flags  = 89;
                d.Stride = 36;
                d.Count  = 4;
                break;

            case 1330140418:     //normal
                d.Flags  = 16473;
                d.Stride = 52;
                d.Count  = 5;
                break;
            }

            return(d);
        }
Example #2
0
 private void UpdateRenderableParams(DrawableBase dwbl, ShaderFX shader)
 {
     foreach (var model in dwbl.AllModels)
     {
         if (model?.Geometries == null)
         {
             continue;
         }
         foreach (var geom in model.Geometries)
         {
             if (geom.Shader == shader)
             {
                 geom.UpdateRenderableParameters = true;
             }
         }
     }
 }
Example #3
0
        private ShaderFX TryConvertMaterial(FbxNode matNode)
        {
            var shader = new ShaderFX();

            var spsName  = "default";
            var texConns = new List <FbxNode>();
            var texNames = new List <string>();

            #region 3dsmax/GIMS properties
            //var floatValueNames = new List<string>();
            //var floatValues = new List<Vector4>();
            //var texValueNames = new List<string>();
            //var texValues = new List<FbxNode>();
            //var matProps = matNode["Properties70"];
            //foreach (var matProp in matProps.Nodes)//currently broken due to GIMS not doing things right
            //{
            //    if (matProp == null) continue;
            //    if (matProp.Name != "P") continue;
            //    var propStr = GetStringFromObjectList(matProp.Properties, 4);
            //    var propId = matProp.Value as string;
            //    if (propId == null) continue;
            //    if (propId == "3dsMax|params|SPSName") spsName = propStr?.ToLowerInvariant() ?? "default";
            //    if (propId.StartsWith("3dsMax|params|FloatValueNames|FloatValueNames")) floatValueNames.Add(propStr);
            //    if (propId.StartsWith("3dsMax|params|FloatValues|FloatValues")) floatValues.Add(GetVector4FromObjectList(matProp.Properties, 4));
            //    if (propId.StartsWith("3dsMax|params|TexValueNames|TexValueNames")) texValueNames.Add(propStr);
            //    if (propId.StartsWith("3dsMax|params|TexValues|TexValues")) texValues.Add(matProp);
            //}
            #endregion

            foreach (var conn in matNode.Connections)
            {
                if (conn.Name == "Texture")
                {
                    texConns.Add(conn);
                    var texName  = GetStringFromObjectList(conn.Properties, 1)?.Replace("Texture::", "");
                    var ftexName = conn["FileName"]?.Value as string;
                    if (ftexName != null)
                    {
                        try
                        {
                            texName = Path.GetFileNameWithoutExtension(ftexName);
                        }
                        catch
                        { }
                    }
                    texNames.Add(texName);
                }
            }

            if (texNames.Count > 1)
            {
                spsName = "normal";
            }

            var spsFileName = spsName + ".sps";

            shader.Name     = JenkHash.GenHash(spsName);
            shader.FileName = JenkHash.GenHash(spsFileName);

            shader.ParametersList = new ShaderParametersBlock();
            var paramsBlock = shader.ParametersList;
            var pNames      = new List <ShaderParamNames>();
            var pVals       = new List <ShaderParameter>();


            shader.Unknown_Ch   = 0;
            shader.RenderBucket = 0;
            shader.Unknown_12h  = 32768;//shrugs
            shader.Unknown_1Ch  = 0;
            shader.Unknown_24h  = 0;
            shader.Unknown_26h  = 0;
            shader.Unknown_28h  = 0;


            switch (spsName)
            {
            default:
            case "default":
                //shader.RenderBucket = 3;
                //shader.ParameterSize = 208;
                //shader.ParameterDataSize = 272;
                AddShaderParam(pNames, pVals, ShaderParamNames.DiffuseSampler, GetTextureBaseParam(texNames, 0));    //assume first texture is diffuse...
                AddShaderParam(pNames, pVals, ShaderParamNames.matMaterialColorScale, new Vector4(1, 0, 0, 1));
                AddShaderParam(pNames, pVals, ShaderParamNames.HardAlphaBlend, new Vector4(0, 0, 0, 0));
                AddShaderParam(pNames, pVals, ShaderParamNames.useTessellation, new Vector4(0, 0, 0, 0));
                AddShaderParam(pNames, pVals, ShaderParamNames.wetnessMultiplier, new Vector4(1, 0, 0, 0));
                AddShaderParam(pNames, pVals, ShaderParamNames.globalAnimUV1, new Vector4(0, 1, 0, 0));
                AddShaderParam(pNames, pVals, ShaderParamNames.globalAnimUV0, new Vector4(1, 0, 0, 0));
                break;

            case "normal":
                //shader.RenderBucket = 0;
                //shader.ParameterSize = 320;
                //shader.ParameterDataSize = 400;
                AddShaderParam(pNames, pVals, ShaderParamNames.DiffuseSampler, GetTextureBaseParam(texNames, 0)); //assume first texture is diffuse...
                AddShaderParam(pNames, pVals, ShaderParamNames.BumpSampler, GetTextureBaseParam(texNames, 1));    //assume 2nd texture is normalmap..
                AddShaderParam(pNames, pVals, ShaderParamNames.HardAlphaBlend, new Vector4(1, 0, 0, 0));
                AddShaderParam(pNames, pVals, ShaderParamNames.useTessellation, new Vector4(0, 0, 0, 0));
                AddShaderParam(pNames, pVals, ShaderParamNames.wetnessMultiplier, new Vector4(1, 0, 0, 0));
                AddShaderParam(pNames, pVals, ShaderParamNames.bumpiness, new Vector4(1, 0, 0, 0));
                AddShaderParam(pNames, pVals, ShaderParamNames.specularIntensityMult, new Vector4(0.5f, 0, 0, 0));
                AddShaderParam(pNames, pVals, ShaderParamNames.specularFalloffMult, new Vector4(20, 0, 0, 0));    //too metallic?
                AddShaderParam(pNames, pVals, ShaderParamNames.specularFresnel, new Vector4(0.9f, 0, 0, 0));
                AddShaderParam(pNames, pVals, ShaderParamNames.globalAnimUV1, new Vector4(0, 1, 0, 0));
                AddShaderParam(pNames, pVals, ShaderParamNames.globalAnimUV0, new Vector4(1, 0, 0, 0));
                break;
            }

            for (int i = 0; i < pVals.Count; i++)
            {
                var pVal = pVals[i];
                if (pVal.DataType == 1)
                {
                    pVal.Unknown_1h = (byte)(160 + ((pVals.Count - 1) - i));//seriously wtf is this and why
                }
            }

            MetaName[] nameHashes = new MetaName[pNames.Count];
            for (int i = 0; i < pNames.Count; i++)
            {
                nameHashes[i] = (MetaName)pNames[i];
            }

            paramsBlock.Hashes     = nameHashes;
            paramsBlock.Parameters = pVals.ToArray();
            paramsBlock.Count      = pVals.Count;

            shader.ParameterSize          = paramsBlock.ParametersSize;
            shader.ParameterDataSize      = (ushort)(paramsBlock.BlockLength + 36);//but why +36?
            shader.ParameterCount         = (byte)pVals.Count;
            shader.TextureParametersCount = paramsBlock.TextureParamsCount;
            shader.RenderBucketMask       = (1u << shader.RenderBucket) | 0xFF00;


            return(shader);
        }
Example #4
0
        public Exporter(string name, ResourcePointerList64 <DrawableModel> models, GameFileCache Cache)
        {
            using (StreamWriter FBXwriter = new StreamWriter("FBX/" + name + ".fbx"))
            {
                var timestamp = DateTime.Now;
                int BaseId    = 10000;

                StringBuilder fbx = new StringBuilder();
                StringBuilder ob  = new StringBuilder(); //Objects builder
                StringBuilder cb  = new StringBuilder(); //Connections builder
                StringBuilder mb  = new StringBuilder(); //Materials builder to get texture count in advance
                StringBuilder cb2 = new StringBuilder(); //and keep connections ordered
                cb.Append("\n}\n");                      //Objects end
                cb.Append("\nConnections:  {");
                List <DrawableGeometry> Geoms    = new List <DrawableGeometry>();
                List <ShaderFX>         Shaders  = new List <ShaderFX>();
                List <Texture>          Textures = new List <Texture>();
                //Models
                for (int mi = 0; mi < models.data_items.Length; mi++)
                {
                    var model = models.data_items[mi];
                    //SubMesh & Materials
                    foreach (var geom in model.Geometries.data_items)
                    {
                        if ((geom.Shader != null) && (geom.Shader.ParametersList != null) && (geom.Shader.ParametersList.Hashes != null))
                        {
                            Geoms.Add(geom);
                            Shaders.Add(geom.Shader);
                            var gname = "Geom" + Geoms.Count;
                            //创建节点
                            ob.AppendFormat("\n\tModel: 1{0}, \"Model::{1}\", \"Mesh\" {{", BaseId + Geoms.Count, gname);
                            ob.Append("\n\t\tVersion: 232");
                            ob.Append("\n\t\tProperties70:  {");
                            ob.Append("\n\t\t\tP: \"InheritType\", \"enum\", \"\", \"\",1");
                            ob.Append("\n\t\t\tP: \"ScalingMax\", \"Vector3D\", \"Vector\", \"\",0,0,0");
                            ob.Append("\n\t\t\tP: \"DefaultAttributeIndex\", \"int\", \"Integer\", \"\",0");
                            ob.AppendFormat("\n\t\t\tP: \"Lcl Translation\", \"Lcl Translation\", \"\", \"A\",{0},{1},{2}", 0, 0, 0);
                            ob.AppendFormat("\n\t\t\tP: \"Lcl Rotation\", \"Lcl Rotation\", \"\", \"A\",{0},{1},{2}", 0, 0, 0);//handedness is switched in quat
                            ob.AppendFormat("\n\t\t\tP: \"Lcl Scaling\", \"Lcl Scaling\", \"\", \"A\",{0},{1},{2}", 1, 1, 1);
                            ob.Append("\n\t\t}");
                            ob.Append("\n\t\tShading: T");
                            ob.Append("\n\t\tCulling: \"CullingOff\"\n\t}");

                            //把节点挂在根节点上
                            cb.AppendFormat("\n\n\t;Model::{0}, Model::RootNode", gname);
                            cb.AppendFormat("\n\tC: \"OO\",1{0},0", BaseId + Geoms.Count);

                            //把几何体挂在节点上
                            cb2.AppendFormat("\n\n\t;Geometry::, Model::{0}", gname);
                            cb2.AppendFormat("\n\tC: \"OO\",3{0},1{1}", BaseId + Geoms.Count, BaseId + Geoms.Count);
                            //把材质挂在节点上
                            cb2.AppendFormat("\n\n\t;Material::, Model::{0}", gname);
                            cb2.AppendFormat("\n\tC: \"OO\",6{0},1{1}", BaseId + Shaders.Count, BaseId + Geoms.Count);

                            var pl = geom.Shader.ParametersList;
                            var h  = pl.Hashes;
                            var p  = pl.Parameters;
                            for (int ip = 0; ip < h.Length; ip++)
                            {
                                var hash = pl.Hashes[ip];
                                var parm = pl.Parameters[ip];
                                var tex  = parm.Data as TextureBase;
                                if (tex != null)
                                {
                                    var t = tex as Texture;
                                    if (t == null)
                                    {
                                        YtdFile file = Cache.TryGetTextureDictForTexture(tex.NameHash);
                                        if (file != null)
                                        {
                                            t = file.TextureDict.Lookup(tex.NameHash);
                                        }
                                    }
                                    var tstr = tex.Name.Trim();
                                    if (t != null)
                                    {
                                        Textures.Add(t);
                                        cb2.AppendFormat("\n\n\t;Texture::, Material::{0}", geom.Shader.Name);
                                        cb2.AppendFormat("\n\tC: \"OP\",7{0},6{1}, ", BaseId + Textures.Count, BaseId + Shaders.Count);
                                        switch (hash.ToString().Trim())
                                        {
                                        case "DiffuseSampler":
                                            cb2.Append("\"DiffuseColor\"");
                                            break;

                                        case "BumpSampler":
                                            cb2.Append("\"NormalMap\"");
                                            break;

                                        case "SpecSampler":
                                            cb2.Append("\"SpecularColor\"");
                                            break;

                                        case "DetailSampler":
                                            break;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }



                fbx.Append("; FBX 7.1.0 project file");
                fbx.Append("\nFBXHeaderExtension:  {\n\tFBXHeaderVersion: 1003\n\tFBXVersion: 7100\n\tCreationTimeStamp:  {\n\t\tVersion: 1000");
                fbx.Append("\n\t\tYear: " + timestamp.Year);
                fbx.Append("\n\t\tMonth: " + timestamp.Month);
                fbx.Append("\n\t\tDay: " + timestamp.Day);
                fbx.Append("\n\t\tHour: " + timestamp.Hour);
                fbx.Append("\n\t\tMinute: " + timestamp.Minute);
                fbx.Append("\n\t\tSecond: " + timestamp.Second);
                fbx.Append("\n\t\tMillisecond: " + timestamp.Millisecond);
                fbx.Append("\n\t}\n\tCreator: \"Unity Studio by Chipicao\"\n}\n");

                fbx.Append("\nGlobalSettings:  {");
                fbx.Append("\n\tVersion: 1000");
                fbx.Append("\n\tProperties70:  {");
                fbx.Append("\n\t\tP: \"UpAxis\", \"int\", \"Integer\", \"\",1");
                fbx.Append("\n\t\tP: \"UpAxisSign\", \"int\", \"Integer\", \"\",1");
                fbx.Append("\n\t\tP: \"FrontAxis\", \"int\", \"Integer\", \"\",2");
                fbx.Append("\n\t\tP: \"FrontAxisSign\", \"int\", \"Integer\", \"\",1");
                fbx.Append("\n\t\tP: \"CoordAxis\", \"int\", \"Integer\", \"\",0");
                fbx.Append("\n\t\tP: \"CoordAxisSign\", \"int\", \"Integer\", \"\",1");
                fbx.Append("\n\t\tP: \"OriginalUpAxis\", \"int\", \"Integer\", \"\",1");
                fbx.Append("\n\t\tP: \"OriginalUpAxisSign\", \"int\", \"Integer\", \"\",1");
                fbx.AppendFormat("\n\t\tP: \"UnitScaleFactor\", \"double\", \"Number\", \"\",1");
                fbx.Append("\n\t\tP: \"OriginalUnitScaleFactor\", \"double\", \"Number\", \"\",1.0");
                fbx.Append("\n\t}\n}\n");

                fbx.Append("\nDocuments:  {");
                fbx.Append("\n\tCount: 1");
                fbx.Append("\n\tDocument: 1234567890, \"\", \"Scene\" {");
                fbx.Append("\n\t\tProperties70:  {");
                fbx.Append("\n\t\t\tP: \"SourceObject\", \"object\", \"\", \"\"");
                fbx.Append("\n\t\t\tP: \"ActiveAnimStackName\", \"KString\", \"\", \"\", \"\"");
                fbx.Append("\n\t\t}");
                fbx.Append("\n\t\tRootNode: 0");
                fbx.Append("\n\t}\n}\n");
                fbx.Append("\nReferences:  {\n}\n");

                fbx.Append("\nDefinitions:  {");
                fbx.Append("\n\tVersion: 100");
                //      fbx.AppendFormat("\n\tCount: {0}", 1 + 2 * GameObjects.Count + Materials.Count + 2 * Textures.Count + ((bool)Properties.Settings.Default["exportDeformers"] ? Skins.Count + DeformerCount + Skins.Count + 1 : 0));

                fbx.Append("\n\tObjectType: \"GlobalSettings\" {");
                fbx.Append("\n\t\tCount: 1");
                fbx.Append("\n\t}");

                fbx.Append("\n\tObjectType: \"Model\" {");
                fbx.AppendFormat("\n\t\tCount: {0}", 1);
                fbx.Append("\n\t}");

                fbx.Append("\n\tObjectType: \"Geometry\" {");
                fbx.AppendFormat("\n\t\tCount: {0}", Geoms.Count);
                fbx.Append("\n\t}");

                fbx.Append("\n\tObjectType: \"Material\" {");
                fbx.AppendFormat("\n\t\tCount: {0}", Shaders.Count);
                fbx.Append("\n\t}");

                fbx.Append("\n\tObjectType: \"Texture\" {");
                fbx.AppendFormat("\n\t\tCount: {0}", Textures.Count);
                fbx.Append("\n\t}");


                fbx.Append("\n}\n");
                fbx.Append("\nObjects:  {");

                FBXwriter.Write(fbx);
                fbx.Clear();



                for (int i = 0; i < Shaders.Count; i++)
                {
                    ShaderFX Shader = Shaders[i];
                    mb.AppendFormat("\n\tMaterial: 6{0}, \"Material::{1}\", \"\" {{", BaseId + i + 1, Shader.Name);
                    mb.Append("\n\t\tVersion: 102");
                    mb.Append("\n\t\tShadingModel: \"phong\"");
                    mb.Append("\n\t\tMultiLayer: 0");
                    mb.Append("\n\t\tProperties70:  {");
                    mb.Append("\n\t\t\tP: \"ShadingModel\", \"KString\", \"\", \"\", \"phong\"");

                    //mb.Append("\n\t\t\tP: \"SpecularFactor\", \"Number\", \"\", \"A\",0");
                    mb.Append("\n\t\t}");
                    mb.Append("\n\t}");
                }
                for (int i = 0; i < Geoms.Count; i++)
                {
                    MeshFBX(Geoms[i], BaseId + i + 1, ob);

                    //write data 8MB at a time
                    if (ob.Length > (8 * 0x100000))
                    {
                        FBXwriter.Write(ob); ob.Clear();
                    }
                }
                for (int i = 0; i < Textures.Count; i++)
                {
                    Texture t = Textures[i];
                    //TODO check texture type and set path accordingly; eg. CubeMap, Texture3D
                    string texFilename = Path.GetFullPath("FBX/" + t.Name + ".png");

                    byte[]           bytes   = DDSIO.GetPixels(t, 0);
                    FileStream       stream  = new FileStream(texFilename, FileMode.Create);
                    PngBitmapEncoder encoder = new PngBitmapEncoder();
                    encoder.Interlace = PngInterlaceOption.On;
                    encoder.Frames.Add(BitmapFrame.Create(BitmapSource.Create(t.Width, t.Height, 96, 96, PixelFormats.Bgra32, null, bytes, t.Width * 4)));
                    encoder.Save(stream);
                    stream.Close();


                    //  File.WriteAllBytes(texFilename, DDSIO.GetDDSFile(t));



                    ob.AppendFormat("\n\tTexture: 7{0}, \"Texture::{1}\", \"\" {{", BaseId + i + 1, t.Name);
                    ob.Append("\n\t\tType: \"TextureVideoClip\"");
                    ob.Append("\n\t\tVersion: 202");
                    ob.AppendFormat("\n\t\tTextureName: \"Texture::{0}\"", t.Name);
                    ob.Append("\n\t\tProperties70:  {");
                    ob.Append("\n\t\t\tP: \"UVSet\", \"KString\", \"\", \"\", \"UVChannel_0\"");
                    ob.Append("\n\t\t\tP: \"UseMaterial\", \"bool\", \"\", \"\",1");
                    ob.Append("\n\t\t}");
                    ob.AppendFormat("\n\t\tMedia: \"Video::{0}\"", t.Name);
                    ob.AppendFormat("\n\t\tFileName: \"{0}\"", texFilename);
                    ob.AppendFormat("\n\t\tRelativeFilename: \"{0}\"", texFilename);
                    ob.Append("\n\t}");
                }

                ob.Append(mb); mb.Clear();
                cb.Append(cb2); cb2.Clear();

                FBXwriter.Write(ob);
                ob.Clear();

                cb.Append("\n}");//Connections end
                FBXwriter.Write(cb);
                cb.Clear();
            }
        }