/// <summary>
        /// Constructor lets the caller specify whether to include the standard
        /// "A=ok, B=cancel" usage text prompt.
        /// </summary>
        public MessageBoxScreen(string message, bool includeUsageText = false, bool includeCancelOption = false)
        {
            _IncludeCancelOption = includeCancelOption;
            _Gradient_Id         = TextureManager.AddTexture(new CutlassTexture("Content/Textures/gradient"));

            string usageText = String.Empty;

            switch (CutlassEngine.CurrentPlatform)
            {
            case PlatformID.MacOSX:
                goto case PlatformID.Win32Windows;

            case PlatformID.Unix:
                goto case PlatformID.Win32Windows;

            case PlatformID.Win32NT:
                goto case PlatformID.Win32Windows;

            case PlatformID.Win32S:
                goto case PlatformID.Win32Windows;

            case PlatformID.Win32Windows:
                usageText = "\nSpace, Enter = OK";
                if (_IncludeCancelOption)
                {
                    usageText += "\nEsc = Cancel";
                }
                break;

            case PlatformID.WinCE:
                goto case PlatformID.Win32Windows;

            case PlatformID.Xbox:
                usageText = "\nSA = OK";
                if (_IncludeCancelOption)
                {
                    usageText += "\nB = Cancel";
                }
                break;

            default:
                break;
            }

            if (includeUsageText)
            {
                this._Message = message + usageText;
            }
            else
            {
                this._Message = message;
            }

            IsPopup = true;

            TransitionOnTime  = TimeSpan.FromSeconds(0.2);
            TransitionOffTime = TimeSpan.FromSeconds(0.2);
        }
Esempio n. 2
0
        /// <summary>
        /// Get a Texture2D
        /// </summary>
        /// <param name="textureName"></param>
        /// <returns></returns>
        public static Texture2D GetTexture2D(TexId textureId)
        {
            ICutlassTexture texture = GetTexture(textureId);

            if (texture != null)
            {
                return(texture.BaseTexture);
            }
            else
            {
                return(null);
            }
        }
        static void AddBatch(int counter, int offset, TexId prevTexture, MyTransparentMaterial prevMaterial)
        {
            MyBillboardRendererBatch batch = new MyBillboardRendererBatch();

            batch.Offset  = offset;
            batch.Num     = counter - offset;
            batch.Texture = prevTexture;

            batch.Lit         = prevMaterial.CanBeAffectedByOtherLights;
            batch.AlphaCutout = prevMaterial.AlphaCutout;

            m_batches.Add(batch);
        }
Esempio n. 4
0
        /// <summary>
        /// Load graphics content.
        /// </summary>
        protected override void LoadContent()
        {
            //_SpriteBatch = new SpriteBatch(GraphicsDevice);

            _Blank_Id  = TextureManager.AddTexture(new CutlassTexture("Content/Textures/blank"));
            _Cursor_Id = TextureManager.AddTexture(new CutlassTexture("Content/Textures/cursor"));

            // Tell each of the screens to load their content.
            foreach (GameScreen screen in _Screens)
            {
                screen.LoadContent();
            }
        }
Esempio n. 5
0
        internal static MyTextureArray FromStringArray(string[] mergeList, MyTextureEnum type, string debugName)
        {
            if (mergeList == null)
            {
                return(null);
            }

            TexId[] ids = new TexId[mergeList.Length];
            for (int i = 0; i < ids.Length; i++)
            {
                ids[i] = MyTextures.GetTexture(mergeList[i], type, true);
            }

            return(new MyTextureArray(ids, debugName));
        }
Esempio n. 6
0
        /// <summary>
        /// Remove a texture from the dictionary.
        /// </summary>
        /// <param name="textureName"></param>
        public static void RemoveTexture(TexId textureId)
        {
            ICutlassTexture textureToRemove;

            _Textures.TryGetValue(textureId, out textureToRemove);

            if (textureToRemove != null)
            {
                if (_Initialized)
                {
                    textureToRemove.UnloadContent();
                }

                _Textures.Remove(textureId);
            }
        }
Esempio n. 7
0
        /// <summary>
        /// Load Content
        /// </summary>
        public override void LoadContent()
        {
            base.LoadContent();

            _TitleScrollMiddle_Id            = TextureManager.AddTexture(new CutlassTexture("Content/Textures/titleScrollMiddle"));
            _TitleScrollEdge_Id              = TextureManager.AddTexture(new CutlassTexture("Content/Textures/titleScrollEdge"));
            _MenuBackgroundCorner_Id         = TextureManager.AddTexture(new CutlassTexture("Content/Textures/backgroundMenuCorner"));
            _MenuBackgroundVerticalEdge_Id   = TextureManager.AddTexture(new CutlassTexture("Content/Textures/backgroundMenuVerticalEdge"));
            _MenuBackgroundHorizontalEdge_Id = TextureManager.AddTexture(new CutlassTexture("Content/Textures/backgroundMenuHorizontalEdge"));

            _TitleFont_Id = FontManager.AddFont(new CutlassFont("Content/Fonts/bilboSwashCaps"));

            SetMenuEntryFont(FontManager.AddFont(new CutlassFont("Content/Fonts/frederickaTheGreat")));
            SetMenuEntryTextColor(Palette.CharcoalGrey);
            SetMenuEntrySelectedTextColor(Palette.LightBlue);
        }
Esempio n. 8
0
        public Scenery(Vector2 position, bool isVisible = true, ICutlassTexture texture = null, bool animated = false, CollisionSide side = CollisionSide.All)
        {
            _Position  = position;
            _IsVisible = isVisible;
            _Active    = true;

            if (isVisible && texture != null)
            {
                _SceneryObject_Id = TextureManager.AddTexture(texture);
                _Animated         = animated;
                _Side             = side;
            }
            else
            {
                _Side = CollisionSide.All;
            }
        }
Esempio n. 9
0
        public Player(GameplayScreen parentScreen, Vector2 position)
        {
            _Player_TexId_Standing_R        = TextureManager.AddTexture(new CutlassTexture("Content/Sprites/pirate-standing-48-120-R"));
            _Player_TexId_Standing_L        = TextureManager.AddTexture(new CutlassTexture("Content/Sprites/pirate-standing-48-120-L"));
            _Player_TexId_Jumping_R         = TextureManager.AddTexture(new CutlassTexture("Content/Sprites/pirate-jumping-64-120-R"));
            _Player_TexId_Jumping_L         = TextureManager.AddTexture(new CutlassTexture("Content/Sprites/pirate-jumping-64-120-L"));
            _Player_TexId_Walking_R         = TextureManager.AddTexture(new CutlassAnimatedTexture("Content/Sprites/pirate-walking-560-120-R", 10, 5));
            _Player_TexId_Walking_L         = TextureManager.AddTexture(new CutlassAnimatedTexture("Content/Sprites/pirate-walking-560-120-L", 10, 5));
            _Player_TexId_Walking_Reverse_R = TextureManager.AddTexture(new CutlassAnimatedTexture("Content/Sprites/pirate-walking-reverse-560-120-R", 10, 5));
            _Player_TexId_Walking_Reverse_L = TextureManager.AddTexture(new CutlassAnimatedTexture("Content/Sprites/pirate-walking-reverse-560-120-L", 10, 5));
            _CurrentTexture = _Player_TexId_Walking_R;

            _ParentScreen = parentScreen;
            _Active       = true;
            _Position     = position;
            _IsVisible    = true;
        }
Esempio n. 10
0
        internal static void UpdateSpotlight(LightId light, bool enabled,
                                             Vector3 direction, float range, float apertureCos, Vector3 up,
                                             Vector3 color, float falloff, TexId reflectorTexture)
        {
            var info = Spotlights[light.Index];

            var gid = light.ParentGID;

            if (gid != -1 && MyIDTracker <MyActor> .FindByID((uint)gid) != null)
            {
                var matrix = MyIDTracker <MyActor> .FindByID((uint)gid).WorldMatrix;

                Vector3.TransformNormal(ref direction, ref matrix, out direction);
                Vector3.TransformNormal(ref up, ref matrix, out up);
            }

            bool aabbChanged = info.Direction != direction || info.Range != range || info.ApertureCos != apertureCos || info.Up != up;

            Spotlights[light.Index].Enabled          = enabled;
            Spotlights[light.Index].Direction        = direction;
            Spotlights[light.Index].Range            = range;
            Spotlights[light.Index].ApertureCos      = apertureCos;
            Spotlights[light.Index].Up               = up;
            Spotlights[light.Index].Falloff          = falloff;
            Spotlights[light.Index].Color            = color;
            Spotlights[light.Index].ReflectorTexture = reflectorTexture;

            var proxy = Spotlights[light.Index].BvhProxyId;
            var positionDifference = Vector3D.RectangularDistance(ref Spotlights[light.Index].LastBvhUpdatePosition, ref Lights.Data[light.Index].PositionWithOffset);

            bool dirty = (enabled && ((proxy == -1) || (positionDifference > MOVE_TOLERANCE || aabbChanged))) || (!enabled && proxy != -1);

            if (dirty)
            {
                DirtySpotlights.Add(light);
            }
            else
            {
                DirtySpotlights.Remove(light);
            }
        }
        static void Gather()
        {
            // counting sorted billboards
            m_batches.Clear();
            m_sortedNum = 0;

            PreGatherList(MyRenderProxy.BillboardsRead);
            PreGatherList(m_billboardsOnce);

            m_sortedBillboardsNum = m_sortedNum;

            m_unsorted = 0;
            m_sorted   = 0;

            GatherList(MyRenderProxy.BillboardsRead);
            GatherList(m_billboardsOnce);

            Array.Sort(m_sortBuffer, 0, m_sortedNum);
            //Array.Reverse(m_sortBuffer, 0, m_sortedNum);
            //Array.Sort(m_sortBuffer, m_sortedNum, m_unsorted);

            var N = m_sorted + m_unsorted;

            var batch = new MyBillboardBatch();
            //MyAssetTexture prevTexture = null;
            var prevTexId     = TexId.NULL;
            int currentOffset = 0;

            if (N > 0)
            {
                var material = MyTransparentMaterials.GetMaterial(m_sortBuffer[0].Material);

                if (material.UseAtlas)
                {
                    var item = m_atlasedTextures[material.Texture];
                    prevTexId = item.TextureId;
                }
                else
                {
                    PreloadTexture(material.Texture);
                    //prevTexture = MyTextureManager.GetTextureFast(material.Texture);
                    prevTexId = MyTextures.GetTexture(material.Texture, MyTextureEnum.GUI, true);
                }
            }

            TexId batchTexId = TexId.NULL;
            MyTransparentMaterial prevMaterial = null;

            for (int i = 0; i < N; i++)
            {
                var billboard = m_sortBuffer[i];
                var material  = MyTransparentMaterials.GetMaterial(billboard.Material);

                var billboardData = new MyBillboardData();

                billboardData.CustomProjectionID = billboard.CustomViewProjection;
                billboardData.Color = billboard.Color;
                if (material.UseAtlas)
                {
                    var atlasItem = m_atlasedTextures[material.Texture];
                    //billboardData.UvModifiers = new HalfVector4(atlasItem.UvOffsetScale);
                    batchTexId = atlasItem.TextureId;
                }
                else
                {
                    batchTexId = MyTextures.GetTexture(material.Texture, MyTextureEnum.GUI, true);
                }

                billboardData.Reflective = billboard.Reflectivity;
                Vector3D pos0 = billboard.Position0;
                Vector3D pos1 = billboard.Position1;
                Vector3D pos2 = billboard.Position2;
                Vector3D pos3 = billboard.Position3;

                if (billboard.ParentID != -1)
                {
                    if (MyIDTracker <MyActor> .FindByID((uint)billboard.ParentID) != null)
                    {
                        var matrix = MyIDTracker <MyActor> .FindByID((uint)billboard.ParentID).WorldMatrix;

                        Vector3D.Transform(ref pos0, ref matrix, out pos0);
                        Vector3D.Transform(ref pos1, ref matrix, out pos1);
                        Vector3D.Transform(ref pos2, ref matrix, out pos2);
                        Vector3D.Transform(ref pos3, ref matrix, out pos3);
                    }
                }

                if (billboard.CustomViewProjection != -1)
                {
                    var billboardViewProjection = MyRenderProxy.BillboardsViewProjectionRead[billboard.CustomViewProjection];

                    //pos0 -= MyEnvironment.CameraPosition;
                    //pos1 -= MyEnvironment.CameraPosition;
                    //pos2 -= MyEnvironment.CameraPosition;
                    //pos3 -= MyEnvironment.CameraPosition;
                }
                else
                {
                    pos0 -= MyEnvironment.CameraPosition;
                    pos1 -= MyEnvironment.CameraPosition;
                    pos2 -= MyEnvironment.CameraPosition;
                    pos3 -= MyEnvironment.CameraPosition;
                }

                var normal = Vector3.Cross(pos1 - pos0, pos2 - pos0);
                normal.Normalize();

                billboardData.Normal = normal;

                m_vertexData[i * 4 + 0].Position = pos0;
                m_vertexData[i * 4 + 1].Position = pos1;
                m_vertexData[i * 4 + 2].Position = pos2;
                m_vertexData[i * 4 + 3].Position = pos3;

                var uv0 = new Vector2(material.UVOffset.X + billboard.UVOffset.X, material.UVOffset.Y + billboard.UVOffset.Y);
                var uv1 = new Vector2(material.UVOffset.X + material.UVSize.X + billboard.UVOffset.X, material.UVOffset.Y + billboard.UVOffset.Y);
                var uv2 = new Vector2(material.UVOffset.X + material.UVSize.X + billboard.UVOffset.X, material.UVOffset.Y + material.UVSize.Y + billboard.UVOffset.Y);
                var uv3 = new Vector2(material.UVOffset.X + billboard.UVOffset.X, material.UVOffset.Y + material.UVSize.Y + billboard.UVOffset.Y);

                if (material.UseAtlas)
                {
                    var atlasItem = m_atlasedTextures[material.Texture];

                    uv0 = uv0 * new Vector2(atlasItem.UvOffsetScale.Z, atlasItem.UvOffsetScale.W) + new Vector2(atlasItem.UvOffsetScale.X, atlasItem.UvOffsetScale.Y);
                    uv1 = uv1 * new Vector2(atlasItem.UvOffsetScale.Z, atlasItem.UvOffsetScale.W) + new Vector2(atlasItem.UvOffsetScale.X, atlasItem.UvOffsetScale.Y);
                    uv2 = uv2 * new Vector2(atlasItem.UvOffsetScale.Z, atlasItem.UvOffsetScale.W) + new Vector2(atlasItem.UvOffsetScale.X, atlasItem.UvOffsetScale.Y);
                    uv3 = uv3 * new Vector2(atlasItem.UvOffsetScale.Z, atlasItem.UvOffsetScale.W) + new Vector2(atlasItem.UvOffsetScale.X, atlasItem.UvOffsetScale.Y);
                }

                m_vertexData[i * 4 + 0].Texcoord = new HalfVector2(uv0);
                m_vertexData[i * 4 + 1].Texcoord = new HalfVector2(uv1);
                m_vertexData[i * 4 + 2].Texcoord = new HalfVector2(uv2);
                m_vertexData[i * 4 + 3].Texcoord = new HalfVector2(uv3);

                pos0.AssertIsValid();
                pos1.AssertIsValid();
                pos2.AssertIsValid();
                pos3.AssertIsValid();


                MyTriangleBillboard triBillboard = billboard as MyTriangleBillboard;
                if (triBillboard != null)
                {
                    m_vertexData[i * 4 + 3].Position = pos2; // second triangle will die in rasterizer

                    m_vertexData[i * 4 + 0].Texcoord = new HalfVector2(triBillboard.UV0);
                    m_vertexData[i * 4 + 1].Texcoord = new HalfVector2(triBillboard.UV1);
                    m_vertexData[i * 4 + 2].Texcoord = new HalfVector2(triBillboard.UV2);

                    billboardData.Normal = triBillboard.Normal0; // pew pew pew :O
                }

                m_billboardData[i] = billboardData;

                bool closeBatch = (batchTexId != prevTexId) || ((i == m_sortedNum) && (i > 0));

                if (closeBatch)
                {
                    batch = new MyBillboardBatch();

                    batch.Offset  = currentOffset;
                    batch.Num     = i - currentOffset;
                    batch.Texture = prevTexId != TexId.NULL ? MyTextures.Views[prevTexId.Index] : null;

                    batch.Lit = prevMaterial.CanBeAffectedByOtherLights;

                    m_batches.Add(batch);
                    currentOffset = i;
                }

                prevTexId    = batchTexId;
                prevMaterial = material;
            }

            if (N > 0)
            {
                batch         = new MyBillboardBatch();
                batch.Offset  = currentOffset;
                batch.Num     = N - currentOffset;
                batch.Texture = prevTexId != TexId.NULL ? MyTextures.GetView(prevTexId) : null;

                batch.Lit = prevMaterial.CanBeAffectedByOtherLights;

                m_batches.Add(batch);
            }
        }
Esempio n. 12
0
        /// <summary>
        /// Load Content.
        /// </summary>
        protected override void LoadContent()
        {
            base.LoadContent();

            _Blank_Id = TextureManager.AddTexture(new CutlassTexture("Content/Textures/blank"));
        }
        internal static void RenderColoredTextures(List <renderColoredTextureProperties> texturesToRender)
        {
            if (texturesToRender.Count == 0)
            {
                return;
            }

            if (!m_initialized)
            {
                Init();
            }

            const int RENDER_TEXTURE_RESOLUTION = 512;

            RC.DeviceContext.OutputMerger.BlendState = null;
            RC.SetIL(null);

            RC.SetPS(m_ps);
            RC.SetCB(0, MyCommon.FrameConstants);
            RC.SetCB(1, m_cb);

            Dictionary <Vector2I, MyRenderTarget> createdRenderTextureTargets = new Dictionary <Vector2I, MyRenderTarget>();

            foreach (var texture in texturesToRender)
            {
                TexId texId = MyTextures.GetTexture(texture.TextureName, MyTextureEnum.COLOR_METAL, true);
                if (texId == TexId.NULL)
                {
                    continue;
                }

                Vector2  texSize = MyTextures.GetSize(texId);
                Vector2I renderTargetResolution = new Vector2I(RENDER_TEXTURE_RESOLUTION, RENDER_TEXTURE_RESOLUTION);
                if (texSize.Y > 0)
                {
                    if (texSize.Y < RENDER_TEXTURE_RESOLUTION)
                    {
                        renderTargetResolution.X = (int)texSize.X;
                        renderTargetResolution.Y = (int)texSize.Y;
                    }
                    else
                    {
                        renderTargetResolution.X *= (int)(texSize.X / texSize.Y);
                    }
                }

                MyViewport viewport = new MyViewport(renderTargetResolution.X, renderTargetResolution.Y);

                MyRenderTarget renderTexture = null;
                if (!createdRenderTextureTargets.TryGetValue(renderTargetResolution, out renderTexture))
                {
                    renderTexture = new MyRenderTarget(renderTargetResolution.X, renderTargetResolution.Y, SharpDX.DXGI.Format.R8G8B8A8_UNorm_SRgb, 1, 0);
                    createdRenderTextureTargets[renderTargetResolution] = renderTexture;
                }

                RC.BindDepthRT(null, DepthStencilAccess.ReadWrite, renderTexture);

                // Set color
                var     mapping = MyMapping.MapDiscard(m_cb);
                Vector4 color   = new Vector4(texture.ColorMaskHSV, 1);
                mapping.WriteAndPosition(ref color);
                mapping.Unmap();

                // Set texture
                RC.DeviceContext.PixelShader.SetShaderResource(0, MyTextures.GetView(texId));

                // Draw
                MyScreenPass.DrawFullscreenQuad(viewport);

                // Save to file
                MyTextureData.ToFile(renderTexture.GetHWResource(), texture.PathToSave, ImageFileFormat.Png);
            }

            texturesToRender.Clear();

            foreach (var texture in createdRenderTextureTargets)
            {
                texture.Value.Release();
            }
            createdRenderTextureTargets.Clear();

            RC.BindDepthRT(null, DepthStencilAccess.ReadWrite, null);
            RC.BindGBufferForRead(0, MyGBuffer.Main);
        }
Esempio n. 14
0
        /// <summary>
        /// Loads graphics content for this screen. The background texture is quite
        /// big, so we use our own local ContentManager to load it. This allows us
        /// to unload before going from the menus into the game itself, wheras if we
        /// used the shared ContentManager provided by the Game class, the content
        /// would remain loaded forever.
        /// </summary>
        public override void LoadContent()
        {
            base.LoadContent();

            _OceanClouds_Id = TextureManager.AddTexture(new CutlassTexture("Content/Textures/oceanClouds"));
        }
Esempio n. 15
0
        public void HandleInput(GameTime gameTime, Cutlass.GameComponents.Input input, Vector2 playerScreenPosition)
        {
            KeyboardState keyboardState = input.CurrentKeyboardState;
            MouseState    mouseState    = input.CurrentMouseState;
            GamePadState  gamePadState  = input.CurrentGamePadState;

            //Keyboard Input
            _IsJumpingDown = false;
            _WalkDirection = 0;

            if (keyboardState.IsKeyDown(GameSettingsManager.Default.LeftKey))
            {
                _WalkDirection = _WalkDirection - 1;
                _Velocity.X    = Math.Max(_Velocity.X - (0.1f * (float)gameTime.ElapsedGameTime.TotalMilliseconds), -MAX_PLAYER_HORIZONTAL_SPEED);
            }

            if (keyboardState.IsKeyDown(GameSettingsManager.Default.RightKey))
            {
                _WalkDirection = _WalkDirection + 1;
                _Velocity.X    = Math.Min(_Velocity.X + (0.1f * (float)gameTime.ElapsedGameTime.TotalMilliseconds), MAX_PLAYER_HORIZONTAL_SPEED);
            }

            if (keyboardState.IsKeyDown(GameSettingsManager.Default.JumpKey) && _IsOnGround)
            {
                _IsOnGround = false;

                if (keyboardState.IsKeyDown(GameSettingsManager.Default.DownKey))
                {
                    _IsJumpingDown = true;
                    _Velocity.Y   += 1.0f;
                }
                else
                {
                    _Velocity.Y = _Velocity.Y - (6.0f);
                }
            }

            //Mouse Input
            Vector2 mousePosition = new Vector2(mouseState.X, mouseState.Y);

            _LookDirection = mousePosition - (playerScreenPosition);// + new Vector2(Width / 2, Height / 2));
            _LookDirection.Normalize();

            //Looking Right
            if (_LookDirection.X >= 0)
            {
                //On the ground
                if (_WasOnGround)
                {
                    //Walking forward
                    if (_WalkDirection > 0)
                    {
                        _CurrentTexture = _Player_TexId_Walking_R;
                    }
                    //Walking backward
                    else if (_WalkDirection < 0)
                    {
                        _CurrentTexture = _Player_TexId_Walking_Reverse_R;
                    }
                    //Standing
                    else
                    {
                        _CurrentTexture = _Player_TexId_Standing_R;
                    }
                }
                //Jumping
                else
                {
                    _CurrentTexture = _Player_TexId_Jumping_R;
                }
            }
            //Looking Left
            else
            {
                //On the ground
                if (_WasOnGround)
                {
                    //Walking forward
                    if (_WalkDirection < 0)
                    {
                        _CurrentTexture = _Player_TexId_Walking_L;
                    }
                    //Walking backward
                    else if (_WalkDirection > 0)
                    {
                        _CurrentTexture = _Player_TexId_Walking_Reverse_L;
                    }
                    //Standing
                    else
                    {
                        _CurrentTexture = _Player_TexId_Standing_L;
                    }
                }
                //Jumping
                else
                {
                    _CurrentTexture = _Player_TexId_Jumping_L;
                }
            }
        }
Esempio n. 16
0
 /// <summary>
 /// Get a texture
 /// </summary>
 /// <param name="textureId"></param>
 /// <returns></returns>
 public static ICutlassTexture GetTexture(TexId textureId)
 {
     return(_Textures.ElementAtOrDefault(textureId).Value);
 }
Esempio n. 17
0
 internal static void AddSingleSprite(TexId texId, Color color, Vector2 origin, Vector2 tangent, Rectangle?sourceRect, RectangleF destinationRect)
 {
     AddSingleSprite(MyTextures.Views[texId.Index], MyTextures.GetSize(texId), color, origin, tangent, sourceRect, destinationRect);
 }
        static void Gather()
        {
            m_batches.Clear();

            // counting sorted billboards
            m_sortedCount   = 0;
            m_unsortedCount = 0;
            m_windowCount   = 0;
            PreGatherList(MyRenderProxy.BillboardsRead);
            PreGatherList(m_billboardsOnce);

            if (BillboardCount == 0)
            {
                return;
            }

            ResizeStorage();

            int sortedIndex   = 0;
            int unsortedIndex = 0;

            GatherList(MyRenderProxy.BillboardsRead, ref sortedIndex, ref unsortedIndex);
            GatherList(m_billboardsOnce, ref sortedIndex, ref unsortedIndex);

            Array.Sort(m_sortedBuffer, 0, m_sortedCount);

            int   i             = 0;
            int   windowidx     = 0;
            var   N             = BillboardCountSafe;
            int   currentOffset = 0;
            TexId prevTexId     = TexId.NULL;
            TexId batchTexId    = TexId.NULL;
            MyTransparentMaterial prevMaterial = null;

            while (true)
            {
                if (i == N)
                {
                    AddBatch(N, currentOffset, prevTexId, prevMaterial);
                    break;
                }

                MyBillboard           billboard = m_sortedBuffer[i];
                MyTransparentMaterial material  = MyTransparentMaterials.GetMaterial(billboard.Material);
                if (material.UseAtlas)
                {
                    var atlasItem = m_atlas.FindElement(material.Texture);
                    batchTexId = atlasItem.TextureId;
                }
                else
                {
                    batchTexId = MyTextures.GetTexture(material.Texture, MyTextureEnum.GUI, true);
                }

                bool closeBatch = i > 0 && (batchTexId != prevTexId || i == m_sortedCount);
                if (closeBatch)
                {
                    AddBatch(i, currentOffset, prevTexId, prevMaterial);
                    currentOffset = i;
                }

                var billboardData     = new MyBillboardData();
                var billboardVertices = new MyBillboardVertexData();

                billboardData.CustomProjectionID = billboard.CustomViewProjection;
                billboardData.Color                     = billboard.Color;
                billboardData.Color.X                  *= billboard.ColorIntensity;
                billboardData.Color.Y                  *= billboard.ColorIntensity;
                billboardData.Color.Z                  *= billboard.ColorIntensity;
                billboardData.AlphaCutout               = billboard.AlphaCutout;
                billboardData.AlphaSaturation           = material.AlphaSaturation;
                billboardData.SoftParticleDistanceScale = billboard.SoftParticleDistanceScale * material.SoftParticleDistanceScale;

                billboardData.Reflective = billboard.Reflectivity;
                Vector3D pos0 = billboard.Position0;
                Vector3D pos1 = billboard.Position1;
                Vector3D pos2 = billboard.Position2;
                Vector3D pos3 = billboard.Position3;

                if (billboard.ParentID != -1)
                {
                    if (MyIDTracker <MyActor> .FindByID((uint)billboard.ParentID) != null)
                    {
                        var matrix = MyIDTracker <MyActor> .FindByID((uint)billboard.ParentID).WorldMatrix;

                        Vector3D.Transform(ref pos0, ref matrix, out pos0);
                        Vector3D.Transform(ref pos1, ref matrix, out pos1);
                        Vector3D.Transform(ref pos2, ref matrix, out pos2);
                        Vector3D.Transform(ref pos3, ref matrix, out pos3);
                    }
                }

                MyEnvironmentMatrices envMatrices = MyRender11.Environment;
                if (MyStereoRender.Enable)
                {
                    if (MyStereoRender.RenderRegion == MyStereoRegion.LEFT)
                    {
                        envMatrices = MyStereoRender.EnvMatricesLeftEye;
                    }
                    else if (MyStereoRender.RenderRegion == MyStereoRegion.RIGHT)
                    {
                        envMatrices = MyStereoRender.EnvMatricesRightEye;
                    }
                }

                if (billboard.CustomViewProjection != -1)
                {
                    var billboardViewProjection = MyRenderProxy.BillboardsViewProjectionRead[billboard.CustomViewProjection];

                    //pos0 -= envMatrices.CameraPosition;
                    //pos1 -= envMatrices.CameraPosition;
                    //pos2 -= envMatrices.CameraPosition;
                    //pos3 -= envMatrices.CameraPosition;
                }
                else
                {
                    pos0 -= envMatrices.CameraPosition;
                    pos1 -= envMatrices.CameraPosition;
                    pos2 -= envMatrices.CameraPosition;
                    pos3 -= envMatrices.CameraPosition;
                }

                var normal = Vector3.Cross(pos1 - pos0, pos2 - pos0);
                normal.Normalize();

                billboardData.Normal = normal;

                billboardVertices.V0.Position = pos0;
                billboardVertices.V1.Position = pos1;
                billboardVertices.V2.Position = pos2;
                billboardVertices.V3.Position = pos3;

                var uv0 = new Vector2(material.UVOffset.X + billboard.UVOffset.X, material.UVOffset.Y + billboard.UVOffset.Y);
                var uv1 = new Vector2(material.UVOffset.X + material.UVSize.X * billboard.UVSize.X + billboard.UVOffset.X, material.UVOffset.Y + billboard.UVOffset.Y);
                var uv2 = new Vector2(material.UVOffset.X + material.UVSize.X * billboard.UVSize.X + billboard.UVOffset.X, material.UVOffset.Y + billboard.UVOffset.Y + material.UVSize.Y * billboard.UVSize.Y);
                var uv3 = new Vector2(material.UVOffset.X + billboard.UVOffset.X, material.UVOffset.Y + billboard.UVOffset.Y + material.UVSize.Y * billboard.UVSize.Y);

                if (material.UseAtlas)
                {
                    var atlasItem = m_atlas.FindElement(material.Texture);

                    uv0 = uv0 * new Vector2(atlasItem.UvOffsetScale.Z, atlasItem.UvOffsetScale.W) + new Vector2(atlasItem.UvOffsetScale.X, atlasItem.UvOffsetScale.Y);
                    uv1 = uv1 * new Vector2(atlasItem.UvOffsetScale.Z, atlasItem.UvOffsetScale.W) + new Vector2(atlasItem.UvOffsetScale.X, atlasItem.UvOffsetScale.Y);
                    uv2 = uv2 * new Vector2(atlasItem.UvOffsetScale.Z, atlasItem.UvOffsetScale.W) + new Vector2(atlasItem.UvOffsetScale.X, atlasItem.UvOffsetScale.Y);
                    uv3 = uv3 * new Vector2(atlasItem.UvOffsetScale.Z, atlasItem.UvOffsetScale.W) + new Vector2(atlasItem.UvOffsetScale.X, atlasItem.UvOffsetScale.Y);
                }

                billboardVertices.V0.Texcoord = new HalfVector2(uv0);
                billboardVertices.V1.Texcoord = new HalfVector2(uv1);
                billboardVertices.V2.Texcoord = new HalfVector2(uv2);
                billboardVertices.V3.Texcoord = new HalfVector2(uv3);

                pos0.AssertIsValid();
                pos1.AssertIsValid();
                pos2.AssertIsValid();
                pos3.AssertIsValid();


                MyTriangleBillboard triBillboard = billboard as MyTriangleBillboard;
                if (triBillboard != null)
                {
                    billboardVertices.V3.Position = pos2; // second triangle will die in rasterizer

                    billboardVertices.V0.Texcoord = new HalfVector2(triBillboard.UV0);
                    billboardVertices.V1.Texcoord = new HalfVector2(triBillboard.UV1);
                    billboardVertices.V2.Texcoord = new HalfVector2(triBillboard.UV2);

                    billboardData.Normal = triBillboard.Normal0;
                }

                m_arrayDataBillboards.Data[i]   = billboardData;
                m_arrayDataBillboards.Vertex[i] = billboardVertices;

                if (billboard.Window && MyScreenDecals.HasEntityDecals((uint)billboard.ParentID))
                {
                    m_arrayDataWindows.Data[windowidx]   = billboardData;
                    m_arrayDataWindows.Vertex[windowidx] = billboardVertices;
                    windowidx++;
                }

                prevTexId    = batchTexId;
                prevMaterial = material;
                i++;
            }
        }