Beispiel #1
0
        /// <summary>
        /// Reads the data-block from a stream.
        /// </summary>
        public override void Read(ResourceDataReader reader, params object[] parameters)
        {
            // read structure data
            this.VFT                   = reader.ReadUInt32();
            this.Unknown_4h            = reader.ReadUInt32();
            this.Unknown_8h            = reader.ReadUInt32();
            this.Unknown_Ch            = reader.ReadUInt32();
            this.InstanceTuningPointer = reader.ReadUInt64();
            this.DrawablePointer       = reader.ReadUInt64();
            this.Unknown_20h           = reader.ReadUInt32();
            this.Unknown_24h           = reader.ReadUInt32();
            this.ControllerPointer     = reader.ReadUInt64();
            this.Unknown_30h           = reader.ReadUInt32();
            this.Unknown_34h           = reader.ReadUInt32();
            this.Unknown_38h           = reader.ReadUInt32();
            this.Unknown_3Ch           = reader.ReadUInt32();
            this.Unknown_40h           = reader.ReadUInt32();
            this.Unknown_44h           = reader.ReadUInt32();
            this.Unknown_48h           = reader.ReadUInt32();
            this.Unknown_4Ch           = reader.ReadUInt32();
            this.Unknown_50h           = reader.ReadUInt32();
            this.Unknown_54h           = reader.ReadUInt32();
            this.Unknown_58h           = reader.ReadUInt32();
            this.Unknown_5Ch           = reader.ReadUInt32();
            this.pxxxxx_2              = reader.ReadUInt64();
            this.cntxx51a              = reader.ReadUInt16();
            this.cntxx51b              = reader.ReadUInt16();
            this.Unknown_6Ch           = reader.ReadUInt32();
            this.Unknown_70h           = reader.ReadUInt32();
            this.Unknown_74h           = reader.ReadUInt32();
            this.Unknown_78h           = reader.ReadUInt32();
            this.Unknown_7Ch           = reader.ReadUInt32();

            // read reference data
            this.InstanceTuning = reader.ReadBlockAt <ClothInstanceTuning>(
                this.InstanceTuningPointer // offset
                );
            this.Drawable = reader.ReadBlockAt <FragDrawable>(
                this.DrawablePointer // offset
                );
            this.Controller = reader.ReadBlockAt <ClothController>(
                this.ControllerPointer // offset
                );
            this.pxxxxx_2data = reader.ReadBlockAt <ResourceSimpleArray <uint_r> >(
                this.pxxxxx_2, // offset
                this.cntxx51a
                );
        }
 public FragDrawableWrapper_GTA5_pc(FragDrawable fragDrawable)
 {
     this.fragDrawable = fragDrawable;
 }
Beispiel #3
0
        private void GenerateButton_Click(object sender, EventArgs e)
        {
            //var space = ProjectForm?.WorldForm?.Space;
            //if (space == null) return;
            var gameFileCache = ProjectForm?.WorldForm?.GameFileCache;

            if (gameFileCache == null)
            {
                return;
            }

            var path = ProjectForm.CurrentProjectFile.GetFullFilePath("lodlights") + "\\";

            GenerateButton.Enabled = false;


            List <YmapFile> projectYmaps = ProjectForm.CurrentProjectFile.YmapFiles;

            var pname = NameTextBox.Text;

            Task.Run(() =>
            {
                var lights = new List <Light>();
                var eemin  = new Vector3(float.MaxValue);
                var eemax  = new Vector3(float.MinValue);
                var semin  = new Vector3(float.MaxValue);
                var semax  = new Vector3(float.MinValue);
                //var rnd = new Random();

                foreach (var ymap in projectYmaps)
                {
                    if (ymap?.AllEntities == null)
                    {
                        continue;
                    }
                    foreach (var ent in ymap.AllEntities)
                    {
                        if (ent.Archetype == null)
                        {
                            continue;
                        }

                        bool waiting = false;
                        var dwbl     = gameFileCache.TryGetDrawable(ent.Archetype, out waiting);
                        while (waiting)
                        {
                            dwbl = gameFileCache.TryGetDrawable(ent.Archetype, out waiting);
                            UpdateStatus("Waiting for " + ent.Archetype.AssetName + " to load...");
                            Thread.Sleep(20);
                        }
                        UpdateStatus("Adding lights from " + ent.Archetype.Name + "...");
                        if (dwbl != null)
                        {
                            Drawable ddwbl                 = dwbl as Drawable;
                            FragDrawable fdwbl             = dwbl as FragDrawable;
                            LightAttributes_s[] lightAttrs = null;
                            if (ddwbl != null)
                            {
                                lightAttrs = ddwbl.LightAttributes?.data_items;
                            }
                            else if (fdwbl != null)
                            {
                                lightAttrs = fdwbl.OwnerFragment?.LightAttributes?.data_items;
                            }
                            if (lightAttrs != null)
                            {
                                eemin = Vector3.Min(eemin, ent.BBMin);
                                eemax = Vector3.Max(eemax, ent.BBMax);
                                semin = Vector3.Min(semin, ent.BBMin - ent._CEntityDef.lodDist);
                                semax = Vector3.Max(semax, ent.BBMax + ent._CEntityDef.lodDist);


                                for (int li = 0; li < lightAttrs.Length; li++)
                                {
                                    var la = lightAttrs[li];
                                    //transform this light with the entity position and orientation
                                    //generate lights data from it!


                                    //gotta transform the light position by the given bone! annoying
                                    Bone bone    = null;
                                    Matrix xform = Matrix.Identity;
                                    int boneidx  = 0;
                                    var skeleton = dwbl.Skeleton;
                                    if (skeleton?.Bones?.Data != null)
                                    {
                                        for (int j = 0; j < skeleton.Bones.Data.Count; j++)
                                        {
                                            var tbone = skeleton.Bones.Data[j];
                                            if (tbone.Tag == la.BoneId)
                                            {
                                                boneidx = j;
                                                bone    = tbone;
                                                break;
                                            }
                                        }
                                        if (bone != null)
                                        {
                                            var modeltransforms = skeleton.Transformations;
                                            var fragtransforms  = fdwbl?.OwnerFragmentPhys?.OwnerFragPhysLod?.FragTransforms?.Data;
                                            var fragtransformid = fdwbl?.OwnerFragmentPhys?.OwnerFragPhysIndex ?? 0;
                                            var fragoffset      = fdwbl?.OwnerFragmentPhys?.OwnerFragPhysLod.Unknown_30h ?? Vector4.Zero;
                                            fragoffset.W        = 0.0f;

                                            if ((fragtransforms != null) && (fragtransformid < fragtransforms.Length))
                                            {
                                                xform       = fragtransforms[fragtransformid];
                                                xform.Row4 += fragoffset;
                                            }
                                            else
                                            {
                                                //when using the skeleton's matrices, they need to be transformed by parent
                                                xform         = modeltransforms[boneidx];
                                                xform.Column4 = Vector4.UnitW;
                                                //xform = Matrix.Identity;
                                                short[] pinds   = skeleton.ParentIndices;
                                                short parentind = ((pinds != null) && (boneidx < pinds.Length)) ? pinds[boneidx] : (short)-1;
                                                while ((parentind >= 0) && (parentind < pinds.Length))
                                                {
                                                    Matrix ptrans  = (parentind < modeltransforms.Length) ? modeltransforms[parentind] : Matrix.Identity;
                                                    ptrans.Column4 = Vector4.UnitW;
                                                    xform          = Matrix.Multiply(ptrans, xform);
                                                    parentind      = ((pinds != null) && (parentind < pinds.Length)) ? pinds[parentind] : (short)-1;
                                                }
                                            }
                                        }
                                    }



                                    Vector3 lpos = la.Position;
                                    Vector3 ldir = la.Direction;
                                    Vector3 bpos = xform.Multiply(lpos);
                                    Vector3 bdir = xform.MultiplyRot(ldir);
                                    Vector3 epos = ent.Orientation.Multiply(bpos) + ent.Position;
                                    Vector3 edir = ent.Orientation.Multiply(bdir);

                                    uint r = la.ColorR;
                                    uint g = la.ColorG;
                                    uint b = la.ColorB;
                                    uint i = (byte)Math.Min(la.Intensity * 4, 255);
                                    uint c = (i << 24) + (r << 16) + (g << 8) + b;


                                    uint h = GetLightHash(ent, li);// (uint)rnd.NextLong();

                                    if (ent._CEntityDef.guid == 91259075)
                                    {
                                    }   //h = 2324437992?     should be:19112537
                                    if (ent._CEntityDef.guid == 889043351)
                                    {
                                    }   //h = 422028630 ?     should be:4267224866



                                    //any other way to know if it's a streetlight?
                                    //var name = ent.Archetype.Name;
                                    var flags          = la.Flags;
                                    bool isStreetLight = (((flags >> 10) & 1u) == 1); // (name != null) && (name.Contains("street") || name.Contains("traffic"));
                                    isStreetLight      = false;                       //TODO: fix this!


                                    //@Calcium:
                                    //1 = point
                                    //2 = spot
                                    //4 = capsule
                                    uint type = (uint)la.Type;
                                    uint unk  = isStreetLight ? 1u : 0;//2 bits - isStreetLight low bit, unk high bit
                                    uint t    = la.TimeFlags | (type << 26) | (unk << 24);

                                    var maxext = (byte)Math.Max(Math.Max(la.Extent.X, la.Extent.Y), la.Extent.Z);



                                    var light                    = new Light();
                                    light.position               = new MetaVECTOR3(epos);
                                    light.colour                 = c;
                                    light.direction              = new MetaVECTOR3(edir);
                                    light.falloff                = la.Falloff;
                                    light.falloffExponent        = la.FalloffExponent;
                                    light.timeAndStateFlags      = t;
                                    light.hash                   = h;
                                    light.coneInnerAngle         = (byte)la.ConeInnerAngle;
                                    light.coneOuterAngleOrCapExt = Math.Max((byte)la.ConeOuterAngle, maxext);
                                    light.coronaIntensity        = (byte)(la.CoronaIntensity * 6);
                                    light.isStreetLight          = isStreetLight;
                                    lights.Add(light);
                                }
                            }
                        }
                    }
                }


                if (lights.Count == 0)
                {
                    MessageBox.Show("No lights found in project!");
                    return;
                }



                //final lights should be sorted by isStreetLight (1 first!) and then hash
                lights.Sort((a, b) =>
                {
                    if (a.isStreetLight != b.isStreetLight)
                    {
                        return(b.isStreetLight.CompareTo(a.isStreetLight));
                    }
                    return(a.hash.CompareTo(b.hash));
                });



                var position          = new List <MetaVECTOR3>();
                var colour            = new List <uint>();
                var direction         = new List <MetaVECTOR3>();
                var falloff           = new List <float>();
                var falloffExponent   = new List <float>();
                var timeAndStateFlags = new List <uint>();
                var hash                   = new List <uint>();
                var coneInnerAngle         = new List <byte>();
                var coneOuterAngleOrCapExt = new List <byte>();
                var coronaIntensity        = new List <byte>();
                ushort numStreetLights     = 0;
                foreach (var light in lights)
                {
                    position.Add(light.position);
                    colour.Add(light.colour);
                    direction.Add(light.direction);
                    falloff.Add(light.falloff);
                    falloffExponent.Add(light.falloffExponent);
                    timeAndStateFlags.Add(light.timeAndStateFlags);
                    hash.Add(light.hash);
                    coneInnerAngle.Add(light.coneInnerAngle);
                    coneOuterAngleOrCapExt.Add(light.coneOuterAngleOrCapExt);
                    coronaIntensity.Add(light.coronaIntensity);
                    if (light.isStreetLight)
                    {
                        numStreetLights++;
                    }
                }



                UpdateStatus("Creating new ymap files...");

                var lodymap               = new YmapFile();
                var distymap              = new YmapFile();
                var ll                    = new YmapLODLights();
                var dl                    = new YmapDistantLODLights();
                var cdl                   = new CDistantLODLight();
                cdl.category              = 1;//0=small, 1=med, 2=large
                cdl.numStreetLights       = numStreetLights;
                dl.CDistantLODLight       = cdl;
                dl.positions              = position.ToArray();
                dl.colours                = colour.ToArray();
                ll.direction              = direction.ToArray();
                ll.falloff                = falloff.ToArray();
                ll.falloffExponent        = falloffExponent.ToArray();
                ll.timeAndStateFlags      = timeAndStateFlags.ToArray();
                ll.hash                   = hash.ToArray();
                ll.coneInnerAngle         = coneInnerAngle.ToArray();
                ll.coneOuterAngleOrCapExt = coneOuterAngleOrCapExt.ToArray();
                ll.coronaIntensity        = coronaIntensity.ToArray();


                lodymap._CMapData.flags         = 0;
                distymap._CMapData.flags        = 2;
                lodymap._CMapData.contentFlags  = 128;
                distymap._CMapData.contentFlags = 256;

                lodymap._CMapData.entitiesExtentsMin   = eemin;
                lodymap._CMapData.entitiesExtentsMax   = eemax;
                lodymap._CMapData.streamingExtentsMin  = semin - 1000f;
                lodymap._CMapData.streamingExtentsMax  = semax + 1000f; //vanilla = ~1km
                distymap._CMapData.entitiesExtentsMin  = eemin;
                distymap._CMapData.entitiesExtentsMax  = eemax;
                distymap._CMapData.streamingExtentsMin = semin - 5000f; //make it huge
                distymap._CMapData.streamingExtentsMax = semax + 5000f; //vanilla = ~3km

                lodymap.LODLights         = ll;
                distymap.DistantLODLights = dl;

                var lodname                     = pname + "_lodlights";
                var distname                    = pname + "_distantlights";
                lodymap.Name                    = lodname;
                lodymap._CMapData.name          = JenkHash.GenHash(lodname);
                lodymap.RpfFileEntry            = new RpfResourceFileEntry();
                lodymap.RpfFileEntry.Name       = lodname + ".ymap";
                lodymap.RpfFileEntry.NameLower  = lodname + ".ymap";
                distymap.Name                   = distname;
                distymap._CMapData.name         = JenkHash.GenHash(distname);
                distymap.RpfFileEntry           = new RpfResourceFileEntry();
                distymap.RpfFileEntry.Name      = distname + ".ymap";
                distymap.RpfFileEntry.NameLower = distname + ".ymap";

                lodymap._CMapData.parent = distymap._CMapData.name;


                UpdateStatus("Adding new ymap files to project...");

                ProjectForm.Invoke((MethodInvoker) delegate
                {
                    ProjectForm.AddYmapToProject(lodymap);
                    ProjectForm.AddYmapToProject(distymap);
                });

                var stats = "";
                UpdateStatus("Process complete. " + stats);
                GenerateComplete();
            });
        }
Beispiel #4
0
        private void GenerateButton_Click(object sender, EventArgs e)
        {
            //var space = ProjectForm?.WorldForm?.Space;
            //if (space == null) return;
            var gameFileCache = ProjectForm?.WorldForm?.GameFileCache;

            if (gameFileCache == null)
            {
                return;
            }

            var path = ProjectForm.CurrentProjectFile.GetFullFilePath("navmeshes") + "\\";

            GenerateButton.Enabled = false;


            List <YmapFile> projectYmaps = ProjectForm.CurrentProjectFile.YmapFiles;

            var pname = NameTextBox.Text;

            Task.Run(() =>
            {
                var position          = new List <MetaVECTOR3>();
                var colour            = new List <uint>();
                var direction         = new List <MetaVECTOR3>();
                var falloff           = new List <float>();
                var falloffExponent   = new List <float>();
                var timeAndStateFlags = new List <uint>();
                var hash                   = new List <uint>();
                var coneInnerAngle         = new List <byte>();
                var coneOuterAngleOrCapExt = new List <byte>();
                var coronaIntensity        = new List <byte>();
                var eemin                  = new Vector3(float.MaxValue);
                var eemax                  = new Vector3(float.MinValue);
                var semin                  = new Vector3(float.MaxValue);
                var semax                  = new Vector3(float.MinValue);

                foreach (var ymap in projectYmaps)
                {
                    foreach (var ent in ymap.AllEntities)
                    {
                        if (ent.Archetype == null)
                        {
                            continue;
                        }

                        bool waiting = false;
                        var dwbl     = gameFileCache.TryGetDrawable(ent.Archetype, out waiting);
                        while (waiting)
                        {
                            dwbl = gameFileCache.TryGetDrawable(ent.Archetype, out waiting);
                            UpdateStatus("Waiting for " + ent.Archetype.AssetName + " to load...");
                            Thread.Sleep(20);
                        }
                        UpdateStatus("Adding lights from " + ent.Archetype.Name + "...");
                        if (dwbl != null)
                        {
                            Drawable ddwbl                 = dwbl as Drawable;
                            FragDrawable fdwbl             = dwbl as FragDrawable;
                            LightAttributes_s[] lightAttrs = null;
                            if (ddwbl != null)
                            {
                                lightAttrs = ddwbl.LightAttributes;
                            }
                            else if (fdwbl != null)
                            {
                                lightAttrs = fdwbl.OwnerFragment?.LightAttributes;
                            }
                            if (lightAttrs != null)
                            {
                                eemin = Vector3.Min(eemin, ent.BBMin);
                                eemax = Vector3.Max(eemax, ent.BBMax);
                                semin = Vector3.Min(semin, ent.BBMin - ent._CEntityDef.lodDist);
                                semax = Vector3.Max(semax, ent.BBMax + ent._CEntityDef.lodDist);


                                foreach (var la in lightAttrs)
                                {
                                    //transform this light with the entity position and orientation
                                    //generate lights data from it!


                                    //gotta transform the light position by the given bone! annoying
                                    Bone bone    = null;
                                    Matrix xform = Matrix.Identity;
                                    int boneidx  = 0;
                                    var skeleton = dwbl.Skeleton;
                                    if (skeleton?.Bones?.Data != null)
                                    {
                                        for (int j = 0; j < skeleton.Bones.Data.Count; j++)
                                        {
                                            var tbone = skeleton.Bones.Data[j];
                                            if (tbone.Id == la.BoneId)
                                            {
                                                boneidx = j;
                                                bone    = tbone;
                                                break;
                                            }
                                        }
                                        if (bone != null)
                                        {
                                            var modeltransforms = skeleton.Transformations;
                                            var fragtransforms  = fdwbl?.OwnerFragmentPhys?.OwnerFragPhysLod?.FragTransforms?.Data;
                                            var fragtransformid = fdwbl?.OwnerFragmentPhys?.OwnerFragPhysIndex ?? 0;
                                            var fragoffset      = fdwbl?.OwnerFragmentPhys?.OwnerFragPhysLod.Unknown_30h ?? Vector4.Zero;
                                            fragoffset.W        = 0.0f;

                                            if ((fragtransforms != null) && (fragtransformid < fragtransforms.Length))
                                            {
                                                xform       = fragtransforms[fragtransformid];
                                                xform.Row4 += fragoffset;
                                            }
                                            else
                                            {
                                                //when using the skeleton's matrices, they need to be transformed by parent
                                                xform         = modeltransforms[boneidx];
                                                xform.Column4 = Vector4.UnitW;
                                                //xform = Matrix.Identity;
                                                ushort[] pinds   = skeleton.ParentIndices;
                                                ushort parentind = ((pinds != null) && (boneidx < pinds.Length)) ? pinds[boneidx] : (ushort)65535;
                                                while (parentind < pinds.Length)
                                                {
                                                    Matrix ptrans  = (parentind < modeltransforms.Length) ? modeltransforms[parentind] : Matrix.Identity;
                                                    ptrans.Column4 = Vector4.UnitW;
                                                    xform          = Matrix.Multiply(ptrans, xform);
                                                    parentind      = ((pinds != null) && (parentind < pinds.Length)) ? pinds[parentind] : (ushort)65535;
                                                }
                                            }
                                        }
                                    }



                                    Vector3 lpos = new Vector3(la.PositionX, la.PositionY, la.PositionZ);
                                    Vector3 ldir = new Vector3(la.DirectionX, la.DirectionY, la.DirectionZ);
                                    Vector3 bpos = xform.Multiply(lpos);
                                    Vector3 bdir = xform.MultiplyRot(ldir);
                                    Vector3 epos = ent.Orientation.Multiply(bpos) + ent.Position;
                                    Vector3 edir = ent.Orientation.Multiply(bdir);

                                    uint r = la.ColorR;
                                    uint g = la.ColorG;
                                    uint b = la.ColorB;
                                    uint i = (byte)Math.Min(la.Intensity * 4, 255);
                                    uint c = (i << 24) + (r << 16) + (g << 8) + b;

                                    uint h = 123456; //TODO: what hash to use???

                                    //@Calcium:
                                    //1 = point
                                    //2 = spot
                                    //4 = capsule
                                    uint type = 1;
                                    uint t    = la.TimeFlags + (type << 26);

                                    var maxext = (byte)Math.Max(Math.Max(la.ExtentX, la.ExtentY), la.ExtentZ);


                                    position.Add(new MetaVECTOR3(epos));
                                    colour.Add(c);
                                    direction.Add(new MetaVECTOR3(edir));
                                    falloff.Add(la.Falloff);
                                    falloffExponent.Add(la.FalloffExponent);
                                    timeAndStateFlags.Add(t);
                                    hash.Add(h);
                                    coneInnerAngle.Add((byte)la.ConeInnerAngle);
                                    coneOuterAngleOrCapExt.Add(Math.Max((byte)la.ConeOuterAngle, maxext));
                                    coronaIntensity.Add((byte)la.CoronaIntensity);
                                }
                            }
                        }
                    }
                }


                if (position.Count == 0)
                {
                    MessageBox.Show("No lights found in project!");
                    return;
                }


                var lodymap               = new YmapFile();
                var distymap              = new YmapFile();
                var ll                    = new YmapLODLights();
                var dl                    = new YmapDistantLODLights();
                var cdl                   = new CDistantLODLight();
                cdl.category              = 1;
                dl.CDistantLODLight       = cdl;
                dl.positions              = position.ToArray();
                dl.colours                = colour.ToArray();
                ll.direction              = direction.ToArray();
                ll.falloff                = falloff.ToArray();
                ll.falloffExponent        = falloffExponent.ToArray();
                ll.timeAndStateFlags      = timeAndStateFlags.ToArray();
                ll.hash                   = hash.ToArray();
                ll.coneInnerAngle         = coneInnerAngle.ToArray();
                ll.coneOuterAngleOrCapExt = coneOuterAngleOrCapExt.ToArray();
                ll.coronaIntensity        = coronaIntensity.ToArray();


                lodymap._CMapData.flags         = 0;
                distymap._CMapData.flags        = 2;
                lodymap._CMapData.contentFlags  = 128;
                distymap._CMapData.contentFlags = 256;

                lodymap._CMapData.entitiesExtentsMin   = eemin;
                lodymap._CMapData.entitiesExtentsMax   = eemax;
                lodymap._CMapData.streamingExtentsMin  = semin - 1000f;
                lodymap._CMapData.streamingExtentsMax  = semax + 1000f;
                distymap._CMapData.entitiesExtentsMin  = eemin;
                distymap._CMapData.entitiesExtentsMax  = eemax;
                distymap._CMapData.streamingExtentsMin = semin - 5000f; //make it huge
                distymap._CMapData.streamingExtentsMax = semax + 5000f;

                lodymap.LODLights         = ll;
                distymap.DistantLODLights = dl;

                var lodname                     = pname + "_lodlights";
                var distname                    = pname + "_distantlights";
                lodymap.Name                    = lodname;
                lodymap._CMapData.name          = JenkHash.GenHash(lodname);
                lodymap.RpfFileEntry            = new RpfResourceFileEntry();
                lodymap.RpfFileEntry.Name       = lodname + ".ymap";
                lodymap.RpfFileEntry.NameLower  = lodname + ".ymap";
                distymap.Name                   = distname;
                distymap._CMapData.name         = JenkHash.GenHash(distname);
                distymap.RpfFileEntry           = new RpfResourceFileEntry();
                distymap.RpfFileEntry.Name      = distname + ".ymap";
                distymap.RpfFileEntry.NameLower = distname + ".ymap";

                lodymap._CMapData.parent = distymap._CMapData.name;

                ProjectForm.Invoke((MethodInvoker) delegate
                {
                    ProjectForm.AddYmapToProject(lodymap);
                    ProjectForm.AddYmapToProject(distymap);
                });

                var stats = "";
                UpdateStatus("Process complete. " + stats);
                GenerateComplete();
            });
        }