Example #1
0
 public void RequestDock(Player player, string nickname)
 {
     actions.Enqueue(() =>
     {
         var obj = Players[player];
         FLLog.Info("Server", $"{player.Name} requested dock at {nickname}");
         var dock = GameWorld.Objects.FirstOrDefault(x =>
                                                     x.Nickname.Equals(nickname, StringComparison.OrdinalIgnoreCase));
         if (dock == null)
         {
             FLLog.Warning("Server", $"Dock object {nickname} does not exist.");
         }
         else
         {
             var component = dock.GetComponent <SDockableComponent>();
             if (component == null)
             {
                 FLLog.Warning("Server", $"object {nickname} is not dockable.");
             }
             else
             {
                 component.StartDock(obj, 0);
             }
         }
     });
 }
Example #2
0
        public void Update(TimeSpan delta)
        {
            int counter = 0;

            accumTime += delta.TotalSeconds;

            while (accumTime > (1.0 / 120.0))
            {
                _Update(TimeSpan.FromSeconds(TIMESTEP));

                accumTime -= TIMESTEP;
                counter++;

                if (counter > MAX_STEPS)
                {
                    // okay, okay... we can't keep up
                    FLLog.Warning("Thn", "Can't keep up!");
                    accumTime = 0.0f;
                    break;
                }
            }
            if (Running)
            {
                var pos = camera.Transform.Position;
                game.Sound.SetListenerParams(pos);
            }
        }
Example #3
0
        public void ActivateTrigger(string trigger)
        {
            var t = Script.AvailableTriggers[trigger];

            foreach (var cond in t.Conditions)
            {
                if (cond.Type == TriggerConditions.Cnd_ProjHit)
                {
                    Player.WorldAction(() =>
                    {
                        var obj = Player.World.GameWorld.GetObject(cond.Entry[0].ToString());
                        if (obj != null)
                        {
                            obj.GetComponent <SNPCComponent>().ProjectileHitHook = ProjectileHit;
                        }
                        else
                        {
                            FLLog.Warning("Mission", $"Cnd_ProjHit won't register for not spawned {cond.Entry[0]}");
                        }
                    });
                }
            }
            activeTriggers.Add(new ActiveTrigger()
            {
                Trigger    = t,
                Conditions = new List <MissionCondition>(t.Conditions)
            });
        }
Example #4
0
 public MaterialMap()
 {
     if (_instance != null)
     {
         FLLog.Warning("MaterialMap", "Switching global material map. TODO make instance");
     }
     _instance = this;
 }
Example #5
0
        public override VMeshData FindMesh(uint vMeshLibId)
        {
            VMeshData vms;

            meshes.TryGetValue(vMeshLibId, out vms);
            if (vms == null)
            {
                FLLog.Warning("ResourceManager", "Mesh " + vMeshLibId + " not found");
            }
            return(vms);
        }
Example #6
0
 //Set only the first one
 //Without this, order ships spawn in the wrong place in M01A
 static void Set <T>(Dictionary <string, T> dict, string k, T value)
 {
     if (!dict.ContainsKey(k))
     {
         dict[k] = value;
     }
     else
     {
         FLLog.Warning("Mission", $"Duplicate {typeof(T)} `{k}`, ignoring.");
     }
 }
        public void QueueOrientation(uint ms, Quaternion orient)
        {
            uint lastMs = 0;

            if (orientBuffer.Count > 0)
            {
                lastMs = orientBuffer.Peek().Tick;
            }
            receivedOrientTime += SeqDiff(ms, lastMs);
            if (orientBuffer.Count == orientBuffer.Capacity)
            {
                FLLog.Warning("Net", "Something bad happened lerp orient");
                receivedOrientTime = 0;
                orientBuffer.Clear();
            }
            orientBuffer.Enqueue(new OrientState()
            {
                Tick = ms, Orient = orient
            });
        }
        public void QueuePosition(uint ms, Vector3 pos)
        {
            uint lastMs = 0;

            if (posBuffer.Count > 0)
            {
                lastMs = posBuffer.Peek().Tick;
            }
            receivedPosTime += SeqDiff(ms, lastMs);
            if (posBuffer.Count == posBuffer.Capacity)
            {
                FLLog.Warning("Net", "Something bad happened lerp pos");
                receivedPosTime = 0;
                posBuffer.Clear();
            }

            posBuffer.Enqueue(new PosState()
            {
                Tick = ms, Pos = pos
            });
        }
Example #9
0
        public void Update(TimeSpan delta)
        {
            int counter = 0;

            accumTime += delta.TotalSeconds;

            while (accumTime > (1.0 / 120.0))
            {
                _Update(TimeSpan.FromSeconds(TIMESTEP));

                accumTime -= TIMESTEP;
                counter++;

                if (counter > MAX_STEPS)
                {
                    // okay, okay... we can't keep up
                    FLLog.Warning("Thn", "Can't keep up!");
                    accumTime = 0.0f;
                    break;
                }
            }
        }
Example #10
0
        public void Run()
        {
            SSEMath.Load();
            if (SDL.SDL_Init(SDL.SDL_INIT_VIDEO) != 0)
            {
                FLLog.Error("SDL", "SDL_Init failed, exiting.");
                return;
            }
            SDL.SDL_SetHint(SDL.SDL_HINT_IME_INTERNAL_EDITING, "1");
            SDL.SDL_SetHint(SDL.SDL_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR, "0");
            //Set GL states
            SDL.SDL_GL_SetAttribute(SDL.SDL_GLattr.SDL_GL_CONTEXT_MAJOR_VERSION, 3);
            SDL.SDL_GL_SetAttribute(SDL.SDL_GLattr.SDL_GL_CONTEXT_MINOR_VERSION, 2);
            SDL.SDL_GL_SetAttribute(SDL.SDL_GLattr.SDL_GL_CONTEXT_PROFILE_MASK, (int)SDL.SDL_GLprofile.SDL_GL_CONTEXT_PROFILE_CORE);
            SDL.SDL_GL_SetAttribute(SDL.SDL_GLattr.SDL_GL_DEPTH_SIZE, 24);
            //Create Window
            var flags = SDL.SDL_WindowFlags.SDL_WINDOW_OPENGL | SDL.SDL_WindowFlags.SDL_WINDOW_RESIZABLE;

            if (fullscreen)
            {
                flags |= SDL.SDL_WindowFlags.SDL_WINDOW_FULLSCREEN_DESKTOP;
            }
            var sdlWin = SDL.SDL_CreateWindow(
                "LibreLancer",
                SDL.SDL_WINDOWPOS_CENTERED,
                SDL.SDL_WINDOWPOS_CENTERED,
                width,
                height,
                flags
                );

            //Cursors
            curArrow      = SDL.SDL_CreateSystemCursor(SDL.SDL_SystemCursor.SDL_SYSTEM_CURSOR_ARROW);
            curMove       = SDL.SDL_CreateSystemCursor(SDL.SDL_SystemCursor.SDL_SYSTEM_CURSOR_CROSSHAIR);
            curTextInput  = SDL.SDL_CreateSystemCursor(SDL.SDL_SystemCursor.SDL_SYSTEM_CURSOR_IBEAM);
            curResizeNS   = SDL.SDL_CreateSystemCursor(SDL.SDL_SystemCursor.SDL_SYSTEM_CURSOR_SIZENS);
            curResizeEW   = SDL.SDL_CreateSystemCursor(SDL.SDL_SystemCursor.SDL_SYSTEM_CURSOR_SIZEWE);
            curResizeNESW = SDL.SDL_CreateSystemCursor(SDL.SDL_SystemCursor.SDL_SYSTEM_CURSOR_SIZENESW);
            curResizeNWSE = SDL.SDL_CreateSystemCursor(SDL.SDL_SystemCursor.SDL_SYSTEM_CURSOR_SIZENWSE);
            //Window sizing
            if (minWindowSize != Point.Zero)
            {
                SDL.SDL_SetWindowMinimumSize(sdlWin, minWindowSize.X, minWindowSize.Y);
            }
            if (sdlWin == IntPtr.Zero)
            {
                FLLog.Error("SDL", "Failed to create window, exiting.");
                return;
            }
            windowptr = sdlWin;
            if (forceANGLE)
            {
                LoadANGLE();
            }
            else
            {
                var  glcontext = SDL.SDL_GL_CreateContext(sdlWin);
                bool check     = GL.CheckStringSDL();
                if (!check)
                {
                    FLLog.Warning("GL", "GL Version Insufficient - Using DX9");
                    SDL.SDL_GL_DeleteContext(glcontext);
                }
                if (glcontext == IntPtr.Zero || !check)
                {
                    if (Platform.RunningOS == OS.Windows)
                    {
                        LoadANGLE();
                    }
                    else
                    {
                        FLLog.Error("OpenGL", "Failed to create OpenGL context, exiting.");
                        return;
                    }
                }
                else
                {
                    GL.LoadSDL();
                    Renderer = string.Format("{0} ({1})", GL.GetString(GL.GL_VERSION), GL.GetString(GL.GL_RENDERER));
                }
            }
            SetVSync(true);
            //Init game state
            RenderState = new RenderState();
            Load();
            //Start game
            running = true;
            var timer = new Stopwatch();

            timer.Start();
            double last    = 0;
            double elapsed = 0;

            SDL.SDL_Event e;
            SDL.SDL_StopTextInput();
            while (running)
            {
                //Pump message queue
                while (SDL.SDL_PollEvent(out e) != 0)
                {
                    switch (e.type)
                    {
                    case SDL.SDL_EventType.SDL_QUIT:
                    {
                        if (WillClose != null)
                        {
                            WillClose();
                        }
                        running = false;                                 //TODO: Raise Event
                        break;
                    }

                    case SDL.SDL_EventType.SDL_MOUSEMOTION:
                    {
                        Mouse.X = e.motion.x;
                        Mouse.Y = e.motion.y;
                        Mouse.OnMouseMove();
                        break;
                    }

                    case SDL.SDL_EventType.SDL_MOUSEBUTTONDOWN:
                    {
                        Mouse.X = e.button.x;
                        Mouse.Y = e.button.y;
                        var btn = GetMouseButton(e.button.button);
                        Mouse.Buttons |= btn;
                        Mouse.OnMouseDown(btn);
                        break;
                    }

                    case SDL.SDL_EventType.SDL_MOUSEBUTTONUP:
                    {
                        Mouse.X = e.button.x;
                        Mouse.Y = e.button.y;
                        var btn = GetMouseButton(e.button.button);
                        Mouse.Buttons &= ~btn;
                        Mouse.OnMouseUp(btn);
                        break;
                    }

                    case SDL.SDL_EventType.SDL_MOUSEWHEEL:
                    {
                        Mouse.OnMouseWheel(e.wheel.y);
                        break;
                    }

                    case SDL.SDL_EventType.SDL_TEXTINPUT:
                    {
                        Keyboard.OnTextInput(GetEventText(ref e));
                        break;
                    }

                    case SDL.SDL_EventType.SDL_KEYDOWN:
                    {
                        Keyboard.OnKeyDown((Keys)e.key.keysym.sym, (KeyModifiers)e.key.keysym.mod, e.key.repeat != 0);
                        break;
                    }

                    case SDL.SDL_EventType.SDL_KEYUP:
                    {
                        Keyboard.OnKeyUp((Keys)e.key.keysym.sym, (KeyModifiers)e.key.keysym.mod);
                        break;
                    }

                    case SDL.SDL_EventType.SDL_WINDOWEVENT:
                        if (e.window.windowEvent == SDL.SDL_WindowEventID.SDL_WINDOWEVENT_RESIZED)
                        {
                            SDL.SDL_GetWindowSize(windowptr, out width, out height);
                        }
                        break;
                    }
                }

                //Do game things
                if (!running)
                {
                    break;
                }
                Action work;
                while (actions.TryDequeue(out work))
                {
                    work();
                }
                totalTime = timer.Elapsed.TotalSeconds;
                Update(elapsed);
                if (!running)
                {
                    break;
                }
                Draw(elapsed);
                //Frame time before, FPS after
                var tk = timer.Elapsed.TotalSeconds - totalTime;
                frameTime = CalcAverageTime(tk);
                if (_screenshot)
                {
                    TakeScreenshot();
                    _screenshot = false;
                }
                if (angle != null)
                {
                    angle.SwapBuffers();
                }
                else
                {
                    SDL.SDL_GL_SwapWindow(sdlWin);
                }
                if (GL.FrameHadErrors())                  //If there was a GL error, track it down.
                {
                    GL.ErrorChecking = true;
                }
                elapsed         = timer.Elapsed.TotalSeconds - last;
                renderFrequency = (1.0 / CalcAverageTick(elapsed));
                last            = timer.Elapsed.TotalSeconds;
                totalTime       = timer.Elapsed.TotalSeconds;
                if (elapsed < 0)
                {
                    elapsed = 0;
                    FLLog.Warning("Timing", "Stopwatch returned negative time!");
                }
            }
            Cleanup();
            SDL.SDL_Quit();
        }
Example #11
0
        public void Process(ThnEvent ev, Cutscene cs)
        {
            if (!cs.Objects.ContainsKey((string)ev.Targets[0]))
            {
                FLLog.Error("Thn", $"Entity {ev.Targets[0]} does not exist");
                return;
            }
            var obj = cs.Objects[(string)ev.Targets[0]];

            if (obj.Light == null)
            {
                FLLog.Error("Thn", $"Entity {ev.Targets[0]} is not a light");
                return;
            }

            object   tmp;
            LuaTable lightprops;

            if (ev.Properties.TryGetValue("lightprops", out tmp))
            {
                lightprops = (LuaTable)tmp;
            }
            else
            {
                FLLog.Warning("Thn", "Light prop animation with no properties");
                return;
            }

            Vector3 vtmp;
            Color3f?targetDiffuse = null;
            Color3f?targetAmbient = null;

            if (lightprops.TryGetValue("on", out tmp))
            {
                obj.Light.Active = ThnEnum.Check <bool>(tmp);
            }
            if (lightprops.TryGetVector3("diffuse", out vtmp))
            {
                targetDiffuse = new Color3f(vtmp);
                if (ev.Duration <= 0)
                {
                    obj.Light.Light.Color = new Color3f(vtmp);
                }
            }
            if (lightprops.TryGetVector3("ambient", out vtmp))
            {
                targetAmbient = new Color3f(vtmp);
                if (ev.Duration <= 0)
                {
                    obj.Light.Light.Ambient = new Color3f(vtmp);
                }
            }
            if (ev.Duration > 0)
            {
                cs.Coroutines.Add(new AnimLightProp()
                {
                    Source        = obj.Light.Light,
                    Target        = obj.Light,
                    TargetDiffuse = targetDiffuse,
                    TargetAmbient = targetAmbient,
                    Duration      = ev.Duration,
                    ParamCurve    = ev.ParamCurve
                });
            }
        }
Example #12
0
        public void Run()
        {
            //Try to set DPI Awareness on Win32
            if (Platform.RunningOS == OS.Windows)
            {
                try {
                    SetProcessDPIAware();
                }
                catch {
                }
            }

            FLLog.Info("Engine", "Version: " + Platform.GetInformationalVersion <Game>());
            //TODO: This makes i5-7200U on mesa 18 faster, but this should probably be a configurable option
            bool setMesaThread = string.IsNullOrWhiteSpace(Environment.GetEnvironmentVariable("mesa_glthread"));

            if (setMesaThread)
            {
                Environment.SetEnvironmentVariable("mesa_glthread", "true");
            }
            if (SDL.SDL_Init(SDL.SDL_INIT_VIDEO) != 0)
            {
                FLLog.Error("SDL", "SDL_Init failed, exiting.");
                return;
            }
            SDL.SDL_SetHint(SDL.SDL_HINT_IME_INTERNAL_EDITING, "1");
            SDL.SDL_SetHint(SDL.SDL_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR, "0");
            //Set GL states
            SDL.SDL_GL_SetAttribute(SDL.SDL_GLattr.SDL_GL_DEPTH_SIZE, 24);
            //Create Window
            var flags = SDL.SDL_WindowFlags.SDL_WINDOW_OPENGL | SDL.SDL_WindowFlags.SDL_WINDOW_RESIZABLE |
                        SDL.SDL_WindowFlags.SDL_WINDOW_ALLOW_HIGHDPI;

            if (fullscreen)
            {
                flags |= SDL.SDL_WindowFlags.SDL_WINDOW_FULLSCREEN_DESKTOP;
            }
            var sdlWin = SDL.SDL_CreateWindow(
                "LibreLancer",
                SDL.SDL_WINDOWPOS_CENTERED,
                SDL.SDL_WINDOWPOS_CENTERED,
                width,
                height,
                flags
                );

            //Cursors
            curArrow      = SDL.SDL_CreateSystemCursor(SDL.SDL_SystemCursor.SDL_SYSTEM_CURSOR_ARROW);
            curMove       = SDL.SDL_CreateSystemCursor(SDL.SDL_SystemCursor.SDL_SYSTEM_CURSOR_CROSSHAIR);
            curTextInput  = SDL.SDL_CreateSystemCursor(SDL.SDL_SystemCursor.SDL_SYSTEM_CURSOR_IBEAM);
            curResizeNS   = SDL.SDL_CreateSystemCursor(SDL.SDL_SystemCursor.SDL_SYSTEM_CURSOR_SIZENS);
            curResizeEW   = SDL.SDL_CreateSystemCursor(SDL.SDL_SystemCursor.SDL_SYSTEM_CURSOR_SIZEWE);
            curResizeNESW = SDL.SDL_CreateSystemCursor(SDL.SDL_SystemCursor.SDL_SYSTEM_CURSOR_SIZENESW);
            curResizeNWSE = SDL.SDL_CreateSystemCursor(SDL.SDL_SystemCursor.SDL_SYSTEM_CURSOR_SIZENWSE);
            //Window sizing
            if (minWindowSize != Point.Zero)
            {
                SDL.SDL_SetWindowMinimumSize(sdlWin, minWindowSize.X, minWindowSize.Y);
            }
            if (sdlWin == IntPtr.Zero)
            {
                Dialogs.CrashWindow.Run("Librelancer", "Failed to create SDL window",
                                        "SDL Error: " + (SDL.SDL_GetError() ?? ""));
                return;
            }
            SDL.SDL_EventState(SDL.SDL_EventType.SDL_DROPFILE, SDL.SDL_ENABLE);
            windowptr = sdlWin;
            IntPtr glcontext = IntPtr.Zero;

            if (Environment.GetEnvironmentVariable("LIBRELANCER_RENDERER") == "GLES" ||
                !CreateContextCore(sdlWin, out glcontext))
            {
                if (!CreateContextES(sdlWin, out glcontext))
                {
                    Dialogs.CrashWindow.Run("Librelancer", "Failed to create OpenGL context",
                                            "Your driver or gpu does not support at least OpenGL 3.2 or OpenGL ES 3.1\n" + SDL.SDL_GetError() ?? "");
                    return;
                }
            }
            GL.LoadSDL();
            Renderer = string.Format("{0} ({1})", GL.GetString(GL.GL_VERSION), GL.GetString(GL.GL_RENDERER));
            FLLog.Info("GL", $"Renderer: {GL.GetString(GL.GL_RENDERER)}");
            SetVSync(true);
            //Init game state
            RenderContext = new RenderContext();
            SDL.SDL_GetWindowSize(sdlWin, out int windowWidth, out int windowHeight);
            SDL.SDL_GL_GetDrawableSize(sdlWin, out width, out height);
            var scaleW = (float)width / windowWidth;
            var scaleH = (float)height / windowHeight;

            if (Platform.RunningOS != OS.Windows)
            {
                DpiScale = scaleH;
            }
            else
            {
                if (SDL.SDL_GetDisplayDPI(0, out float ddpi, out _, out _) == 0)
                {
                    DpiScale = ddpi / 96.0f;
                }
            }
            FLLog.Info("GL", $"Dpi Scale: {DpiScale:F4}");
            Load();
            //kill the value we set so it doesn't crash child processes
            if (setMesaThread)
            {
                Environment.SetEnvironmentVariable("mesa_glthread", null);
            }
            //Start game
            running = true;
            timer   = new Stopwatch();
            timer.Start();
            double last    = 0;
            double elapsed = 0;

            SDL.SDL_Event e = new SDL.SDL_Event();
            SDL.SDL_StopTextInput();
            MouseButtons doRelease = 0;

            while (running)
            {
                //Window State
                var winFlags = (SDL.SDL_WindowFlags)SDL.SDL_GetWindowFlags(sdlWin);
                Focused = (winFlags & SDL.SDL_WindowFlags.SDL_WINDOW_MOUSE_FOCUS) ==
                          SDL.SDL_WindowFlags.SDL_WINDOW_MOUSE_FOCUS ||
                          (winFlags & SDL.SDL_WindowFlags.SDL_WINDOW_INPUT_FOCUS) ==
                          SDL.SDL_WindowFlags.SDL_WINDOW_INPUT_FOCUS;
                EventsThisFrame = false;
                //Get Size
                SDL.SDL_GetWindowSize(sdlWin, out windowWidth, out windowHeight);
                SDL.SDL_GL_GetDrawableSize(sdlWin, out width, out height);
                scaleW = (float)width / windowWidth;
                scaleH = (float)height / windowHeight;
                if (Platform.RunningOS != OS.Windows)
                {
                    DpiScale = scaleH;
                }
                //This allows for press/release in same frame to have
                //button down for one frame, e.g. trackpoint middle click on Linux/libinput.
                MouseButtons pressedThisFrame = 0;
                Mouse.Buttons &= ~doRelease;
                doRelease      = 0;
                bool eventWaited = false;
                if (waitForEvent)
                {
                    waitForEvent = false;
                    if (SDL.SDL_WaitEventTimeout(out e, 2000) != 0)
                    {
                        eventWaited = true;
                    }
                }
                Mouse.Wheel = 0;
                //Pump message queue
                while (eventWaited || SDL.SDL_PollEvent(out e) != 0)
                {
                    eventWaited     = false;
                    EventsThisFrame = true;
                    switch (e.type)
                    {
                    case SDL.SDL_EventType.SDL_QUIT:
                    {
                        if (WillClose != null)
                        {
                            WillClose();
                        }
                        running = false;         //TODO: Raise Event
                        break;
                    }

                    case SDL.SDL_EventType.SDL_MOUSEMOTION:
                    {
                        Mouse.X = (int)(scaleW * e.motion.x);
                        Mouse.Y = (int)(scaleH * e.motion.y);
                        Mouse.OnMouseMove();
                        break;
                    }

                    case SDL.SDL_EventType.SDL_MOUSEBUTTONDOWN:
                    {
                        Mouse.X = (int)(scaleW * e.button.x);
                        Mouse.Y = (int)(scaleH * e.button.y);
                        var btn = GetMouseButton(e.button.button);
                        Mouse.Buttons    |= btn;
                        pressedThisFrame |= btn;
                        Mouse.OnMouseDown(btn);
                        break;
                    }

                    case SDL.SDL_EventType.SDL_MOUSEBUTTONUP:
                    {
                        Mouse.X = (int)(scaleW * e.button.x);
                        Mouse.Y = (int)(scaleH * e.button.y);
                        var btn = GetMouseButton(e.button.button);
                        if ((pressedThisFrame & btn) == btn)
                        {
                            doRelease |= btn;
                        }
                        else
                        {
                            Mouse.Buttons &= ~btn;
                        }
                        Mouse.OnMouseUp(btn);
                        break;
                    }

                    case SDL.SDL_EventType.SDL_MOUSEWHEEL:
                    {
                        Mouse.Wheel += e.wheel.y;
                        break;
                    }

                    case SDL.SDL_EventType.SDL_TEXTINPUT:
                    {
                        Keyboard.OnTextInput(GetEventText(ref e));
                        break;
                    }

                    case SDL.SDL_EventType.SDL_KEYDOWN:
                    {
                        Keyboard.OnKeyDown((Keys)e.key.keysym.scancode, (KeyModifiers)e.key.keysym.mod, e.key.repeat != 0);
                        break;
                    }

                    case SDL.SDL_EventType.SDL_KEYUP:
                    {
                        Keyboard.OnKeyUp((Keys)e.key.keysym.scancode, (KeyModifiers)e.key.keysym.mod);
                        break;
                    }

                    case SDL.SDL_EventType.SDL_KEYMAPCHANGED:
                        KeysExtensions.ResetKeyNames();
                        break;

                    case SDL.SDL_EventType.SDL_WINDOWEVENT:
                        if (e.window.windowEvent == SDL.SDL_WindowEventID.SDL_WINDOWEVENT_RESIZED)
                        {
                            OnResize();
                        }
                        break;

                    case SDL.SDL_EventType.SDL_DROPFILE:
                    {
                        var file = UnsafeHelpers.PtrToStringUTF8(e.drop.file);
                        OnDrop(file);
                        SDL.SDL_free(e.drop.file);
                        break;
                    }
                    }
                }
                Mouse.Wheel /= 2.5f;
                //Do game things
                if (!running)
                {
                    break;
                }
                Action work;
                while (actions.TryDequeue(out work))
                {
                    work();
                }
                totalTime = timer.Elapsed.TotalSeconds;
                Update(elapsed);
                if (!running)
                {
                    break;
                }
                Draw(elapsed);
                RenderContext.EndFrame();
                //Frame time before, FPS after
                var tk = timer.Elapsed.TotalSeconds - totalTime;
                frameTime = CalcAverageTime(tk);
                if (_screenshot)
                {
                    TakeScreenshot();
                    _screenshot = false;
                }
                SDL.SDL_GL_SwapWindow(sdlWin);
                if (GL.FrameHadErrors()) //If there was a GL error, track it down.
                {
                    GL.ErrorChecking = true;
                }
                elapsed         = timer.Elapsed.TotalSeconds - last;
                renderFrequency = (1.0 / CalcAverageTick(elapsed));
                last            = timer.Elapsed.TotalSeconds;
                totalTime       = timer.Elapsed.TotalSeconds;
                if (elapsed < 0)
                {
                    elapsed = 0;
                    FLLog.Warning("Timing", "Stopwatch returned negative time!");
                }
            }
            Cleanup();
            SDL.SDL_Quit();
        }
Example #13
0
        public void Run()
        {
            FLLog.Info("Engine", "Version: " + Platform.GetInformationalVersion <Game>());
            //TODO: This makes i5-7200U on mesa 18 faster, but this should probably be a configurable option
            Environment.SetEnvironmentVariable("mesa_glthread", "true");
            if (SDL.SDL_Init(SDL.SDL_INIT_VIDEO) != 0)
            {
                FLLog.Error("SDL", "SDL_Init failed, exiting.");
                return;
            }
            SDL.SDL_SetHint(SDL.SDL_HINT_IME_INTERNAL_EDITING, "1");
            SDL.SDL_SetHint(SDL.SDL_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR, "0");
            //Set GL states
            SDL.SDL_GL_SetAttribute(SDL.SDL_GLattr.SDL_GL_CONTEXT_MAJOR_VERSION, 3);
            SDL.SDL_GL_SetAttribute(SDL.SDL_GLattr.SDL_GL_CONTEXT_MINOR_VERSION, 2);
            SDL.SDL_GL_SetAttribute(SDL.SDL_GLattr.SDL_GL_CONTEXT_PROFILE_MASK, (int)SDL.SDL_GLprofile.SDL_GL_CONTEXT_PROFILE_CORE);
            SDL.SDL_GL_SetAttribute(SDL.SDL_GLattr.SDL_GL_DEPTH_SIZE, 24);
            //Create Window
            var flags = SDL.SDL_WindowFlags.SDL_WINDOW_OPENGL | SDL.SDL_WindowFlags.SDL_WINDOW_RESIZABLE;

            if (fullscreen)
            {
                flags |= SDL.SDL_WindowFlags.SDL_WINDOW_FULLSCREEN_DESKTOP;
            }
            var sdlWin = SDL.SDL_CreateWindow(
                "LibreLancer",
                SDL.SDL_WINDOWPOS_CENTERED,
                SDL.SDL_WINDOWPOS_CENTERED,
                width,
                height,
                flags
                );

            //Cursors
            curArrow      = SDL.SDL_CreateSystemCursor(SDL.SDL_SystemCursor.SDL_SYSTEM_CURSOR_ARROW);
            curMove       = SDL.SDL_CreateSystemCursor(SDL.SDL_SystemCursor.SDL_SYSTEM_CURSOR_CROSSHAIR);
            curTextInput  = SDL.SDL_CreateSystemCursor(SDL.SDL_SystemCursor.SDL_SYSTEM_CURSOR_IBEAM);
            curResizeNS   = SDL.SDL_CreateSystemCursor(SDL.SDL_SystemCursor.SDL_SYSTEM_CURSOR_SIZENS);
            curResizeEW   = SDL.SDL_CreateSystemCursor(SDL.SDL_SystemCursor.SDL_SYSTEM_CURSOR_SIZEWE);
            curResizeNESW = SDL.SDL_CreateSystemCursor(SDL.SDL_SystemCursor.SDL_SYSTEM_CURSOR_SIZENESW);
            curResizeNWSE = SDL.SDL_CreateSystemCursor(SDL.SDL_SystemCursor.SDL_SYSTEM_CURSOR_SIZENWSE);
            //Window sizing
            if (minWindowSize != Point.Zero)
            {
                SDL.SDL_SetWindowMinimumSize(sdlWin, minWindowSize.X, minWindowSize.Y);
            }
            if (sdlWin == IntPtr.Zero)
            {
                FLLog.Error("SDL", "Failed to create window, exiting.");
                return;
            }
            SDL.SDL_EventState(SDL.SDL_EventType.SDL_DROPFILE, SDL.SDL_ENABLE);
            windowptr = sdlWin;
            var glcontext = SDL.SDL_GL_CreateContext(sdlWin);

            if (glcontext == IntPtr.Zero || !GL.CheckStringSDL())
            {
                SDL.SDL_GL_DeleteContext(glcontext);
                if (Platform.RunningOS == OS.Windows)
                {
                    SDL.SDL_ShowSimpleMessageBox(SDL.SDL_MessageBoxFlags.SDL_MESSAGEBOX_ERROR, "Librelancer", "Failed to create OpenGL context, exiting.", IntPtr.Zero);
                }
                FLLog.Error("OpenGL", "Failed to create OpenGL context, exiting.");
                return;
            }
            else
            {
                GL.LoadSDL();
                Renderer = string.Format("{0} ({1})", GL.GetString(GL.GL_VERSION), GL.GetString(GL.GL_RENDERER));
            }
            SetVSync(true);
            //Init game state
            RenderState = new RenderState();
            Load();
            //Start game
            running = true;
            timer   = new Stopwatch();
            timer.Start();
            double last    = 0;
            double elapsed = 0;

            SDL.SDL_Event e = new SDL.SDL_Event();
            SDL.SDL_StopTextInput();
            MouseButtons doRelease = 0;

            while (running)
            {
                //Window State
                var winFlags = (SDL.SDL_WindowFlags)SDL.SDL_GetWindowFlags(sdlWin);
                Focused = (winFlags & SDL.SDL_WindowFlags.SDL_WINDOW_MOUSE_FOCUS) ==
                          SDL.SDL_WindowFlags.SDL_WINDOW_MOUSE_FOCUS ||
                          (winFlags & SDL.SDL_WindowFlags.SDL_WINDOW_INPUT_FOCUS) ==
                          SDL.SDL_WindowFlags.SDL_WINDOW_INPUT_FOCUS;
                EventsThisFrame = false;
                //This allows for press/release in same frame to have
                //button down for one frame, e.g. trackpoint middle click on Linux/libinput.
                MouseButtons pressedThisFrame = 0;
                Mouse.Buttons &= ~doRelease;
                doRelease      = 0;
                bool eventWaited = false;
                if (waitForEvent)
                {
                    waitForEvent = false;
                    if (SDL.SDL_WaitEventTimeout(out e, 2000) != 0)
                    {
                        eventWaited = true;
                    }
                }
                //Pump message queue
                while (eventWaited || SDL.SDL_PollEvent(out e) != 0)
                {
                    eventWaited     = false;
                    EventsThisFrame = true;
                    switch (e.type)
                    {
                    case SDL.SDL_EventType.SDL_QUIT:
                    {
                        if (WillClose != null)
                        {
                            WillClose();
                        }
                        running = false;         //TODO: Raise Event
                        break;
                    }

                    case SDL.SDL_EventType.SDL_MOUSEMOTION:
                    {
                        Mouse.X = e.motion.x;
                        Mouse.Y = e.motion.y;
                        Mouse.OnMouseMove();
                        break;
                    }

                    case SDL.SDL_EventType.SDL_MOUSEBUTTONDOWN:
                    {
                        Mouse.X = e.button.x;
                        Mouse.Y = e.button.y;
                        var btn = GetMouseButton(e.button.button);
                        Mouse.Buttons    |= btn;
                        pressedThisFrame |= btn;
                        Mouse.OnMouseDown(btn);
                        break;
                    }

                    case SDL.SDL_EventType.SDL_MOUSEBUTTONUP:
                    {
                        Mouse.X = e.button.x;
                        Mouse.Y = e.button.y;
                        var btn = GetMouseButton(e.button.button);
                        if ((pressedThisFrame & btn) == btn)
                        {
                            doRelease |= btn;
                        }
                        else
                        {
                            Mouse.Buttons &= ~btn;
                        }
                        Mouse.OnMouseUp(btn);
                        break;
                    }

                    case SDL.SDL_EventType.SDL_MOUSEWHEEL:
                    {
                        Mouse.OnMouseWheel(e.wheel.y);
                        break;
                    }

                    case SDL.SDL_EventType.SDL_TEXTINPUT:
                    {
                        Keyboard.OnTextInput(GetEventText(ref e));
                        break;
                    }

                    case SDL.SDL_EventType.SDL_KEYDOWN:
                    {
                        Keyboard.OnKeyDown((Keys)e.key.keysym.scancode, (KeyModifiers)e.key.keysym.mod, e.key.repeat != 0);
                        break;
                    }

                    case SDL.SDL_EventType.SDL_KEYUP:
                    {
                        Keyboard.OnKeyUp((Keys)e.key.keysym.scancode, (KeyModifiers)e.key.keysym.mod);
                        break;
                    }

                    case SDL.SDL_EventType.SDL_KEYMAPCHANGED:
                        KeysExtensions.ResetKeyNames();
                        break;

                    case SDL.SDL_EventType.SDL_WINDOWEVENT:
                        if (e.window.windowEvent == SDL.SDL_WindowEventID.SDL_WINDOWEVENT_RESIZED)
                        {
                            SDL.SDL_GetWindowSize(windowptr, out width, out height);
                            OnResize();
                        }
                        break;

                    case SDL.SDL_EventType.SDL_DROPFILE:
                    {
                        var file = UnsafeHelpers.PtrToStringUTF8(e.drop.file);
                        OnDrop(file);
                        SDL.SDL_free(e.drop.file);
                        break;
                    }
                    }
                }

                //Do game things
                if (!running)
                {
                    break;
                }
                Action work;
                while (actions.TryDequeue(out work))
                {
                    work();
                }
                totalTime = timer.Elapsed.TotalSeconds;
                Update(elapsed);
                if (!running)
                {
                    break;
                }
                Draw(elapsed);
                //Frame time before, FPS after
                var tk = timer.Elapsed.TotalSeconds - totalTime;
                frameTime = CalcAverageTime(tk);
                if (_screenshot)
                {
                    TakeScreenshot();
                    _screenshot = false;
                }
                SDL.SDL_GL_SwapWindow(sdlWin);
                if (GL.FrameHadErrors()) //If there was a GL error, track it down.
                {
                    GL.ErrorChecking = true;
                }
                elapsed         = timer.Elapsed.TotalSeconds - last;
                renderFrequency = (1.0 / CalcAverageTick(elapsed));
                last            = timer.Elapsed.TotalSeconds;
                totalTime       = timer.Elapsed.TotalSeconds;
                if (elapsed < 0)
                {
                    elapsed = 0;
                    FLLog.Warning("Timing", "Stopwatch returned negative time!");
                }
            }
            Cleanup();
            SDL.SDL_Quit();
        }
Example #14
0
        void AddEntities(ThnScript thn)
        {
            foreach (var kv in thn.Entities)
            {
                if (Objects.ContainsKey(kv.Key))
                {
                    continue;
                }
                if ((kv.Value.ObjectFlags & ThnObjectFlags.Reference) == ThnObjectFlags.Reference)
                {
                    continue;
                }
                var obj = new ThnObject();
                obj.Name      = kv.Key;
                obj.Translate = kv.Value.Position ?? Vector3.Zero;
                obj.Rotate    = kv.Value.RotationMatrix ?? Matrix4x4.Identity;
                //PlayerShip object
                if (spawnObjects && scriptContext.PlayerShip != null && kv.Value.Type == EntityTypes.Compound &&
                    kv.Value.Template.Equals("playership", StringComparison.InvariantCultureIgnoreCase))
                {
                    obj.Object = scriptContext.PlayerShip;
                    obj.Object.RenderComponent.LitDynamic = (kv.Value.ObjectFlags & ThnObjectFlags.LitDynamic) == ThnObjectFlags.LitDynamic;
                    obj.Object.RenderComponent.LitAmbient = (kv.Value.ObjectFlags & ThnObjectFlags.LitAmbient) == ThnObjectFlags.LitAmbient;
                    obj.Object.RenderComponent.NoFog      = kv.Value.NoFog;
                    ((ModelRenderer)obj.Object.RenderComponent).LightGroup = kv.Value.LightGroup;
                    obj.Entity = kv.Value;
                    Vector3 transform = kv.Value.Position ?? Vector3.Zero;
                    obj.Object.Transform = (kv.Value.RotationMatrix ?? Matrix4x4.Identity) * Matrix4x4.CreateTranslation(transform);
                    obj.HpMount          = scriptContext.PlayerShip.GetHardpoint("HpMount");
                    World.Objects.Add(obj.Object);
                    Objects.Add(kv.Key, obj);
                    continue;
                }

                var    template = kv.Value.Template;
                string replacement;
                if (scriptContext != null &&
                    scriptContext.Substitutions.TryGetValue(kv.Value.Template, out replacement))
                {
                    template = replacement;
                }
                var resman = game.GetService <ResourceManager>();
                if (spawnObjects && kv.Value.Type == EntityTypes.Compound)
                {
                    bool getHpMount = false;
                    //Fetch model
                    IDrawable drawable = null;
                    if (!string.IsNullOrEmpty(template))
                    {
                        switch (kv.Value.MeshCategory.ToLowerInvariant())
                        {
                        case "solar":
                            drawable = gameData.GetSolar(template);
                            break;

                        case "ship":
                        case "spaceship":
                            getHpMount = true;
                            var sh = gameData.GetShip(template);
                            drawable = sh.ModelFile.LoadFile(resman);
                            break;

                        case "prop":
                            drawable = gameData.GetProp(template);
                            break;

                        case "room":
                            drawable = gameData.GetRoom(template);
                            break;

                        case "equipment cart":
                            drawable = gameData.GetCart(template);
                            break;

                        case "equipment":
                            var eq = gameData.GetEquipment(template);
                            drawable = eq?.ModelFile.LoadFile(resman);
                            break;

                        case "asteroid":
                            drawable = gameData.GetAsteroid(kv.Value.Template);
                            break;

                        default:
                            throw new NotImplementedException("Mesh Category " + kv.Value.MeshCategory);
                        }
                    }
                    else
                    {
                        FLLog.Warning("Thn", $"object '{kv.Value.Name}' has empty template, category " +
                                      $"'{kv.Value.MeshCategory}'");
                    }

                    drawable?.Initialize(resman);
                    if (kv.Value.UserFlag != 0)
                    {
                        //This is a starsphere
                        layers.Add(new Tuple <IDrawable, ThnObject>(drawable, obj));
                    }
                    else
                    {
                        obj.Object                  = new GameObject(drawable, game.GetService <ResourceManager>(), true, false, false);
                        obj.Object.Name             = kv.Value.Name;
                        obj.Object.PhysicsComponent = null; //Jitter seems to interfere with directly setting orientation
                        if (getHpMount)
                        {
                            obj.HpMount = obj.Object.GetHardpoint("HpMount");
                        }
                        var r = (ModelRenderer)obj.Object.RenderComponent;
                        if (r != null)
                        {
                            r.LightGroup = kv.Value.LightGroup;
                            r.LitDynamic = (kv.Value.ObjectFlags & ThnObjectFlags.LitDynamic) ==
                                           ThnObjectFlags.LitDynamic;
                            r.LitAmbient = (kv.Value.ObjectFlags & ThnObjectFlags.LitAmbient) ==
                                           ThnObjectFlags.LitAmbient;
                            //HIDDEN just seems to be an editor flag?
                            //r.Hidden = (kv.Value.ObjectFlags & ThnObjectFlags.Hidden) == ThnObjectFlags.Hidden;
                            r.NoFog = kv.Value.NoFog;
                        }
                    }
                }
                else if (kv.Value.Type == EntityTypes.PSys)
                {
                    var fx = gameData.GetEffect(kv.Value.Template);
                    if (fx != null)
                    {
                        obj.Object = new GameObject();
                        obj.Object.RenderComponent = new ParticleEffectRenderer(fx.GetEffect(resman))
                        {
                            Active = false
                        };
                    }
                }
                else if (kv.Value.Type == EntityTypes.Scene)
                {
                    if (kv.Value.DisplayText != null)
                    {
                        text = kv.Value.DisplayText;
                    }
                    if (hasScene)
                    {
                        //throw new Exception("Thn can only have one scene");
                        //TODO: This needs to be handled better
                        continue;
                    }
                    var amb = kv.Value.Ambient.Value;
                    if (amb.X == 0 && amb.Y == 0 && amb.Z == 0)
                    {
                        continue;
                    }
                    hasScene = true;
                    Renderer.SystemLighting.Ambient = new Color4(amb.X / 255f, amb.Y / 255f, amb.Z / 255f, 1);
                }
                else if (kv.Value.Type == EntityTypes.Light)
                {
                    var lt = new DynamicLight();
                    lt.LightGroup = kv.Value.LightGroup;
                    lt.Active     = kv.Value.LightProps.On;
                    lt.Light      = kv.Value.LightProps.Render;
                    obj.Light     = lt;
                    obj.LightDir  = lt.Light.Direction;
                    if (kv.Value.RotationMatrix.HasValue)
                    {
                        var m = kv.Value.RotationMatrix.Value;
                        lt.Light.Direction = Vector3.TransformNormal(lt.Light.Direction, m);
                    }
                    if (Renderer != null)
                    {
                        Renderer.SystemLighting.Lights.Add(lt);
                    }
                }
                else if (kv.Value.Type == EntityTypes.Camera)
                {
                    obj.Camera             = new ThnCameraTransform();
                    obj.Camera.Position    = kv.Value.Position.Value;
                    obj.Camera.Orientation = kv.Value.RotationMatrix ?? Matrix4x4.Identity;
                    obj.Camera.FovH        = kv.Value.FovH ?? obj.Camera.FovH;
                    obj.Camera.AspectRatio = kv.Value.HVAspect ?? obj.Camera.AspectRatio;
                    if (kv.Value.NearPlane != null)
                    {
                        obj.Camera.Znear = kv.Value.NearPlane.Value;
                    }
                    if (kv.Value.FarPlane != null)
                    {
                        obj.Camera.Zfar = kv.Value.FarPlane.Value;
                    }
                }
                else if (kv.Value.Type == EntityTypes.Marker)
                {
                    obj.Object          = new GameObject();
                    obj.Object.Name     = "Marker";
                    obj.Object.Nickname = "";
                }
                else if (kv.Value.Type == EntityTypes.Deformable)
                {
                    obj.Object = new GameObject();
                    gameData.GetCostume(template, out DfmFile body, out DfmFile head, out DfmFile leftHand, out DfmFile rightHand);
                    var skel = new DfmSkeletonManager(body, head, leftHand, rightHand);
                    obj.Object.RenderComponent = new CharacterRenderer(skel);
                    var anmComponent = new AnimationComponent(obj.Object, gameData.GetCharacterAnimations());
                    obj.Object.AnimationComponent = anmComponent;
                    obj.Object.Components.Add(anmComponent);
                }
                else if (kv.Value.Type == EntityTypes.Sound)
                {
                    obj.Sound         = new ThnSound(kv.Value.Template, game.GetService <SoundManager>(), kv.Value.AudioProps, obj);
                    obj.Sound.Spatial = (kv.Value.ObjectFlags & ThnObjectFlags.SoundSpatial) == ThnObjectFlags.SoundSpatial;
                }
                if (obj.Object != null)
                {
                    Vector3 transform = kv.Value.Position ?? Vector3.Zero;
                    obj.Object.Transform = (kv.Value.RotationMatrix ?? Matrix4x4.Identity) * Matrix4x4.CreateTranslation(transform);
                    World.Objects.Add(obj.Object);
                }
                obj.Entity      = kv.Value;
                Objects[kv.Key] = obj;
            }
        }
Example #15
0
        void InitWithDrawable(IDrawable drawable, ResourceManager res, bool staticpos)
        {
            Resources = res;
            dr        = drawable;
            Shape collisionShape = null;
            bool  isCmp          = false;

            if (dr is SphFile)
            {
                var radius = ((SphFile)dr).Radius;
                collisionShape = new SphereShape(radius);
            }
            else if (dr is ModelFile)
            {
                var mdl  = dr as ModelFile;
                var path = Path.ChangeExtension(mdl.Path, "sur");
                if (File.Exists(path))
                {
                    SurFile sur = res.GetSur(path);
                    var     shs = new List <CompoundSurShape.TransformedShape>();
                    foreach (var s in sur.GetShape(0))
                    {
                        shs.Add(new CompoundSurShape.TransformedShape(s, Matrix3.Identity, Vector3.Zero));
                    }
                    collisionShape = new CompoundSurShape(shs);
                }
            }
            else if (dr is CmpFile)
            {
                isCmp = true;
                var cmp = dr as CmpFile;
                CmpParts      = new List <Part>();
                CmpConstructs = cmp.Constructs.CloneAll();
                foreach (var part in cmp.Parts.Values)
                {
                    CmpParts.Add(part.Clone(CmpConstructs));
                }
                if (cmp.Animation != null)
                {
                    AnimationComponent = new AnimationComponent(this, cmp.Animation);
                    Components.Add(AnimationComponent);
                }
                var path = Path.ChangeExtension(cmp.Path, "sur");
                if (File.Exists(path))
                {
                    SurFile sur    = res.GetSur(path);
                    var     shapes = new List <CompoundSurShape.TransformedShape>();
                    foreach (var part in CmpParts)
                    {
                        var crc = CrcTool.FLModelCrc(part.ObjectName);
                        if (!sur.HasShape(crc))
                        {
                            FLLog.Warning("Sur", "No hitbox for " + part.ObjectName);
                            continue;
                        }
                        var colshape = sur.GetShape(crc);
                        if (part.Construct == null)
                        {
                            foreach (var s in colshape)
                            {
                                shapes.Add(new CompoundSurShape.TransformedShape(s, Matrix3.Identity, Vector3.Zero));
                            }
                        }
                        else
                        {
                            var tr  = part.Construct.Transform;
                            var pos = tr.ExtractTranslation();
                            var q   = tr.ExtractRotation(true);
                            var rot = Matrix3.CreateFromQuaternion(q);
                            foreach (var s in colshape)
                            {
                                shapes.Add(new CompoundSurShape.TransformedShape(s, rot, pos)
                                {
                                    Tag = part.Construct
                                });
                            }
                        }
                    }
                    collisionShape = new CompoundSurShape(shapes);
                }
            }
            if (collisionShape != null)
            {
                PhysicsComponent          = new RigidBody(collisionShape);
                PhysicsComponent.Tag      = this;
                PhysicsComponent.IsStatic = staticpos;
                if (staticpos)
                {
                    PhysicsComponent.Material.Restitution = 1;
                }
            }
            PopulateHardpoints(dr);
            if (isCmp)
            {
                RenderComponent = new ModelRenderer(CmpParts, (dr as CmpFile));
            }
            else
            {
                RenderComponent = new ModelRenderer(dr);
            }
        }
        void CalculateBillboards()
        {
            Vector3         position;
            BoundingFrustum frustum;

            billboardCount = 0;
            lock (_camera) {
                position = _camera.Position;
                frustum  = _camera.Frustum;
            }

            var close      = AsteroidFieldShared.GetCloseCube(cameraPos, field.FillDist * 2);
            var checkRad   = field.FillDist + field.BillboardSize.Y;
            int checkCount = 0;

            for (var x = -1; x <= 1; x++)
            {
                for (int y = -1; y <= 1; y++)
                {
                    for (int z = -1; z <= 1; z++)
                    {
                        var center = close + new Vector3(x, y, z) * (field.FillDist * 2);
                        //early bail for billboards too far
                        if (Vector3.Distance(position, center) - checkRad > field.FillDist)
                        {
                            continue;
                        }
                        //bail billboards outside of zone - avoids popping
                        if (field.Zone.Shape.ScaledDistance(center) > 1.1f)
                        {
                            continue;
                        }
                        //rotate
                        var rotation =
                            AsteroidCubeRotation.Default.GetRotation(AsteroidFieldShared.PositionHash(center));
                        for (int i = 0; i < billboardCube.Length; i++)
                        {
                            var spritepos = center + Vector3.Transform(billboardCube[i].Position, rotation);
                            //cull individual billboards too far
                            if (Vector3.Distance(position, spritepos) > field.FillDist)
                            {
                                continue;
                            }
                            billboardBuffer[checkCount]            = billboardCube[i];
                            billboardBuffer[checkCount].Position   = spritepos;
                            billboardBuffer[checkCount++].Distance = Vector3.DistanceSquared(center, cameraPos);
                        }
                    }
                }
            }
            //Highly unlikely this check will succeed. If it does there's something wrong with the cube code
            if (checkCount > field.BillboardCount)
            {
                if (!warnedTooManyBillboards)
                {
                    warnedTooManyBillboards = true;
                    FLLog.Warning("Asteroids", "Too many billboards in sort task for field " + field.Zone.Nickname);
                }
                Array.Sort(billboardBuffer, 0, checkCount); //Get closest
                checkCount = field.BillboardCount;
            }
            //Cull ones that aren't on screen
            for (int i = 0; i < checkCount; i++)
            {
                var billboard = billboardBuffer[i];
                var sphere    = new BoundingSphere(billboard.Position, billboard.Size * 1.5f);
                if (!frustum.Intersects(sphere))
                {
                    continue;
                }
                calculatedBillboards[billboardCount++] = billboard;
            }
        }