public GameData.Nebula GetNebula(GameData.StarSystem sys, Data.Universe.Nebula nbl)
        {
            var n = new GameData.Nebula();

            n.Zone = sys.Zones.Where((z) => z.Nickname.ToLower() == nbl.ZoneName.ToLower()).First();
            var panels = new Data.Universe.TexturePanels(nbl.TexturePanels.Files[0]);

            foreach (var txmfile in panels.Files)
            {
                resource.LoadResourceFile(Data.VFS.GetPath(fldata.Freelancer.DataPath + txmfile));
            }
            n.ExteriorFill        = nbl.ExteriorFillShape;
            n.ExteriorColor       = nbl.ExteriorColor ?? Color4.White;
            n.FogColor            = nbl.FogColor ?? Color4.Black;
            n.FogEnabled          = (nbl.FogEnabled ?? 0) != 0;
            n.FogRange            = new Vector2(nbl.FogNear ?? 0, nbl.FogDistance ?? 0);
            n.SunBurnthroughScale = n.SunBurnthroughIntensity = 1f;
            if (nbl.NebulaLights != null && nbl.NebulaLights.Count > 0)
            {
                n.AmbientColor            = nbl.NebulaLights[0].Ambient;
                n.SunBurnthroughScale     = nbl.NebulaLights[0].SunBurnthroughScaler ?? 1f;
                n.SunBurnthroughIntensity = nbl.NebulaLights[0].SunBurnthroughIntensity ?? 1f;
            }
            if (nbl.CloudsPuffShape != null)
            {
                n.HasInteriorClouds = true;
                GameData.CloudShape[] shapes = new GameData.CloudShape[nbl.CloudsPuffShape.Count];
                for (int i = 0; i < shapes.Length; i++)
                {
                    var name = nbl.CloudsPuffShape[i];
                    if (!panels.Shapes.ContainsKey(name))
                    {
                        FLLog.Error("Nebula", "Shape " + name + " does not exist in " + nbl.TexturePanels.Files[0]);
                        shapes[i].Texture    = ResourceManager.NullTextureName;
                        shapes[i].Dimensions = new RectangleF(0, 0, 1, 1);
                    }
                    else
                    {
                        shapes[i].Texture    = panels.Shapes[name].TextureName;
                        shapes[i].Dimensions = panels.Shapes[name].Dimensions;
                    }
                }
                n.InteriorCloudShapes = new WeightedRandomCollection <GameData.CloudShape>(
                    shapes,
                    nbl.CloudsPuffWeights.ToArray()
                    );
                n.InteriorCloudColorA       = nbl.CloudsPuffColorA.Value;
                n.InteriorCloudColorB       = nbl.CloudsPuffColorB.Value;
                n.InteriorCloudRadius       = nbl.CloudsPuffRadius.Value;
                n.InteriorCloudCount        = nbl.CloudsPuffCount.Value;
                n.InteriorCloudMaxDistance  = nbl.CloudsMaxDistance.Value;
                n.InteriorCloudMaxAlpha     = nbl.CloudsPuffMaxAlpha ?? 1f;
                n.InteriorCloudFadeDistance = nbl.CloudsNearFadeDistance.Value;
                n.InteriorCloudDrift        = nbl.CloudsPuffDrift.Value;
            }
            if (nbl.ExteriorShape != null)
            {
                n.HasExteriorBits = true;
                GameData.CloudShape[] shapes = new GameData.CloudShape[nbl.ExteriorShape.Count];
                for (int i = 0; i < shapes.Length; i++)
                {
                    var name = nbl.ExteriorShape[i];
                    if (!panels.Shapes.ContainsKey(name))
                    {
                        FLLog.Error("Nebula", "Shape " + name + " does not exist in " + nbl.TexturePanels.Files[0]);
                        shapes[i].Texture    = ResourceManager.NullTextureName;
                        shapes[i].Dimensions = new RectangleF(0, 0, 1, 1);
                    }
                    else
                    {
                        shapes[i].Texture    = panels.Shapes[name].TextureName;
                        shapes[i].Dimensions = panels.Shapes[name].Dimensions;
                    }
                }
                n.ExteriorCloudShapes = new WeightedRandomCollection <GameData.CloudShape>(
                    shapes,
                    nbl.ExteriorShapeWeights.ToArray()
                    );
                n.ExteriorMinBits            = nbl.ExteriorMinBits.Value;
                n.ExteriorMaxBits            = nbl.ExteriorMaxBits.Value;
                n.ExteriorBitRadius          = nbl.ExteriorBitRadius.Value;
                n.ExteriorBitRandomVariation = nbl.ExteriorBitRadiusRandomVariation ?? 0;
                n.ExteriorMoveBitPercent     = nbl.ExteriorMoveBitPercent ?? 0;
            }
            if (nbl.ExclusionZones != null)
            {
                n.ExclusionZones = new List <GameData.ExclusionZone>();
                foreach (var excz in nbl.ExclusionZones)
                {
                    if (excz.Exclusion == null)
                    {
                        continue;
                    }
                    var e = new GameData.ExclusionZone();
                    e.Zone   = sys.Zones.Where((z) => z.Nickname.ToLower() == excz.Exclusion.Nickname.ToLower()).First();
                    e.FogFar = excz.FogFar ?? n.FogRange.Y;
                    if (excz.ZoneShellPath != null)
                    {
                        var pth = Data.VFS.GetPath(fldata.Freelancer.DataPath + excz.ZoneShellPath);
                        e.Shell         = resource.GetDrawable(pth);
                        e.ShellTint     = excz.Tint ?? Color3f.White;
                        e.ShellScalar   = excz.ShellScalar ?? 1f;
                        e.ShellMaxAlpha = excz.MaxAlpha ?? 1f;
                    }
                    n.ExclusionZones.Add(e);
                }
            }
            if (nbl.BackgroundLightningDuration != null)
            {
                n.BackgroundLightning         = true;
                n.BackgroundLightningDuration = nbl.BackgroundLightningDuration.Value;
                n.BackgroundLightningColor    = nbl.BackgroundLightningColor.Value;
                n.BackgroundLightningGap      = nbl.BackgroundLightningGap.Value;
            }
            if (nbl.DynamicLightningDuration != null)
            {
                n.DynamicLightning         = true;
                n.DynamicLightningGap      = nbl.DynamicLightningGap.Value;
                n.DynamicLightningColor    = nbl.DynamicLightningColor.Value;
                n.DynamicLightningDuration = nbl.DynamicLightningDuration.Value;
            }
            if (nbl.CloudsLightningDuration != null)
            {
                n.CloudLightning          = true;
                n.CloudLightningDuration  = nbl.CloudsLightningDuration.Value;
                n.CloudLightningColor     = nbl.CloudsLightningColor.Value;
                n.CloudLightningGap       = nbl.CloudsLightningGap.Value;
                n.CloudLightningIntensity = nbl.CloudsLightningIntensity.Value;
            }
            return(n);
        }
        GameData.AsteroidField GetAsteroidField(GameData.StarSystem sys, Data.Universe.AsteroidField ast)
        {
            var a = new GameData.AsteroidField();

            a.Zone = sys.Zones.Where((z) => z.Nickname.ToLower() == ast.ZoneName.ToLower()).First();
            Data.Universe.TexturePanels panels = null;
            if (ast.TexturePanels != null)
            {
                foreach (var f in ast.TexturePanels.Files)
                {
                    panels = new Data.Universe.TexturePanels(f);
                    foreach (var txmfile in panels.Files)
                    {
                        resource.LoadResourceFile(Data.VFS.GetPath(fldata.Freelancer.DataPath + txmfile));
                    }
                }
            }
            if (ast.Band != null)
            {
                a.Band             = new GameData.AsteroidBand();
                a.Band.RenderParts = ast.Band.RenderParts.Value;
                a.Band.Height      = ast.Band.Height.Value;
                a.Band.Shape       = panels.Shapes [ast.Band.Shape].TextureName;
                a.Band.Fade        = new Vector4(ast.Band.Fade [0], ast.Band.Fade [1], ast.Band.Fade [2], ast.Band.Fade [3]);
                var cs = ast.Band.ColorShift ?? Vector3.One;
                a.Band.ColorShift     = new Color4(cs.X, cs.Y, cs.Z, 1f);
                a.Band.TextureAspect  = ast.Band.TextureAspect ?? 1f;
                a.Band.OffsetDistance = ast.Band.OffsetDist ?? 0f;
            }
            a.Cube               = new List <GameData.StaticAsteroid> ();
            a.CubeRotation       = new GameData.AsteroidCubeRotation();
            a.CubeRotation.AxisX = ast.Cube_RotationX ?? GameData.AsteroidCubeRotation.Default_AxisX;
            a.CubeRotation.AxisY = ast.Cube_RotationY ?? GameData.AsteroidCubeRotation.Default_AxisY;
            a.CubeRotation.AxisZ = ast.Cube_RotationZ ?? GameData.AsteroidCubeRotation.Default_AxisZ;
            a.CubeSize           = ast.Field.CubeSize ?? 100;   //HACK: Actually handle null cube correctly
            a.SetFillDist(ast.Field.FillDist.Value);
            a.EmptyCubeFrequency = ast.Field.EmptyCubeFrequency ?? 0f;
            foreach (var c in ast.Cube)
            {
                var sta = new GameData.StaticAsteroid()
                {
                    Rotation = c.Rotation,
                    Position = c.Position,
                    Info     = c.Info
                };
                sta.RotationMatrix =
                    Matrix4.CreateRotationX(MathHelper.DegreesToRadians(c.Rotation.X)) *
                    Matrix4.CreateRotationY(MathHelper.DegreesToRadians(c.Rotation.Y)) *
                    Matrix4.CreateRotationZ(MathHelper.DegreesToRadians(c.Rotation.Z));
                var n    = c.Name;
                var arch = fldata.Asteroids.FindAsteroid(c.Name);
                resource.LoadResourceFile(Data.VFS.GetPath(fldata.Freelancer.DataPath + arch.MaterialLibrary));
                sta.Drawable = resource.GetDrawable(Data.VFS.GetPath(fldata.Freelancer.DataPath + arch.DaArchetype));
                a.Cube.Add(sta);
            }
            a.ExclusionZones = new List <GameData.ExclusionZone>();
            if (ast.ExclusionZones != null)
            {
                foreach (var excz in ast.ExclusionZones)
                {
                    var e = new GameData.ExclusionZone();
                    e.Zone = sys.Zones.Where((z) => z.Nickname.ToLower() == excz.Exclusion.Nickname.ToLower()).First();
                    //e.FogFar = excz.FogFar ?? n.FogRange.Y;
                    if (excz.ZoneShellPath != null)
                    {
                        var pth = Data.VFS.GetPath(fldata.Freelancer.DataPath + excz.ZoneShellPath);
                        e.Shell         = resource.GetDrawable(pth);
                        e.ShellTint     = excz.Tint ?? Color3f.White;
                        e.ShellScalar   = excz.ShellScalar ?? 1f;
                        e.ShellMaxAlpha = excz.MaxAlpha ?? 1f;
                    }
                    a.ExclusionZones.Add(e);
                }
            }
            a.BillboardCount = ast.AsteroidBillboards == null ? -1 : ast.AsteroidBillboards.Count.Value;
            if (a.BillboardCount != -1)
            {
                a.BillboardDistance       = ast.AsteroidBillboards.StartDist.Value;
                a.BillboardFadePercentage = ast.AsteroidBillboards.FadeDistPercent.Value;
                Data.Universe.TextureShape sh = null;
                if (panels != null)
                {
                    if (!panels.Shapes.TryGetValue(ast.AsteroidBillboards.Shape, out sh))
                    {
                        a.BillboardCount = -1;
                        FLLog.Error("Asteroids", "Field " + ast.ZoneName + " can't find billboard shape " + ast.AsteroidBillboards.Shape);
                        return(a);
                    }
                    else
                    {
                        sh = panels.Shapes[ast.AsteroidBillboards.Shape];
                    }
                }
                else
                {
                    sh = new Data.Universe.TextureShape(ast.AsteroidBillboards.Shape, ast.AsteroidBillboards.Shape, new RectangleF(0, 0, 1, 1));
                }
                a.BillboardShape = new TextureShape()
                {
                    Texture    = sh.TextureName,
                    Dimensions = sh.Dimensions,
                    Nickname   = ast.AsteroidBillboards.Shape
                };
                a.BillboardSize = ast.AsteroidBillboards.Size.Value;
                a.BillboardTint = new Color3f(ast.AsteroidBillboards.ColorShift ?? Vector3.One);
            }
            return(a);
        }