Exemplo n.º 1
0
 void VBOHInternal(Chunk c_zp, Chunk c_zm, Chunk c_yp, Chunk c_ym, Chunk c_xp, Chunk c_xm, Chunk c_zpxp, Chunk c_zpxm, Chunk c_zpyp, Chunk c_zpym, List<Chunk> potentials)
 {
     try
     {
         bool shaped = OwningRegion.TheClient.CVars.r_noblockshapes.ValueB;
         Object locky = new Object();
         ChunkRenderHelper rh;
         lock (locky)
         {
             rh = new ChunkRenderHelper();
         }
         if (DENIED)
         {
             return;
         }
         //bool light = OwningRegion.TheClient.CVars.r_fallbacklighting.ValueB
         BlockInternal t_air = new BlockInternal((ushort)Material.AIR, 0, 0, 255);
         List<Vector3> poses = new List<Vector3>();
         List<Vector4> colorses = new List<Vector4>();
         for (int x = 0; x < CSize; x++)
         {
             for (int y = 0; y < CSize; y++)
             {
                 for (int z = 0; z < CSize; z++)
                 {
                     BlockInternal c = GetBlockAt(x, y, z);
                     if ((c.Material).RendersAtAll())
                     {
                         BlockInternal zp = z + 1 < CSize ? GetBlockAt(x, y, z + 1) : (c_zp == null ? t_air : GetLODRelative(c_zp, x, y, z + 1 - CSize));
                         BlockInternal zm = z > 0 ? GetBlockAt(x, y, z - 1) : (c_zm == null ? t_air : GetLODRelative(c_zm, x, y, z - 1 + CSize));
                         BlockInternal yp = y + 1 < CSize ? GetBlockAt(x, y + 1, z) : (c_yp == null ? t_air : GetLODRelative(c_yp, x, y + 1 - CSize, z));
                         BlockInternal ym = y > 0 ? GetBlockAt(x, y - 1, z) : (c_ym == null ? t_air : GetLODRelative(c_ym, x, y - 1 + CSize, z));
                         BlockInternal xp = x + 1 < CSize ? GetBlockAt(x + 1, y, z) : (c_xp == null ? t_air : GetLODRelative(c_xp, x + 1 - CSize, y, z));
                         BlockInternal xm = x > 0 ? GetBlockAt(x - 1, y, z) : (c_xm == null ? t_air : GetLODRelative(c_xm, x - 1 + CSize, y, z));
                         bool rAS = !((Material)c.BlockMaterial).GetCanRenderAgainstSelf();
                         bool pMatters = !c.IsOpaque();
                         bool zps = (zp.IsOpaque() || (rAS && (zp.BlockMaterial == c.BlockMaterial && (pMatters || zp.BlockPaint == c.BlockPaint)))) && BlockShapeRegistry.BSD[shaped ? 0 : zp.BlockData].OccupiesBOTTOM();
                         bool zms = (zm.IsOpaque() || (rAS && (zm.BlockMaterial == c.BlockMaterial && (pMatters || zm.BlockPaint == c.BlockPaint)))) && BlockShapeRegistry.BSD[shaped ? 0 : zm.BlockData].OccupiesTOP();
                         bool xps = (xp.IsOpaque() || (rAS && (xp.BlockMaterial == c.BlockMaterial && (pMatters || xp.BlockPaint == c.BlockPaint)))) && BlockShapeRegistry.BSD[shaped ? 0 : xp.BlockData].OccupiesXM();
                         bool xms = (xm.IsOpaque() || (rAS && (xm.BlockMaterial == c.BlockMaterial && (pMatters || xm.BlockPaint == c.BlockPaint)))) && BlockShapeRegistry.BSD[shaped ? 0 : xm.BlockData].OccupiesXP();
                         bool yps = (yp.IsOpaque() || (rAS && (yp.BlockMaterial == c.BlockMaterial && (pMatters || yp.BlockPaint == c.BlockPaint)))) && BlockShapeRegistry.BSD[shaped ? 0 : yp.BlockData].OccupiesYM();
                         bool yms = (ym.IsOpaque() || (rAS && (ym.BlockMaterial == c.BlockMaterial && (pMatters || ym.BlockPaint == c.BlockPaint)))) && BlockShapeRegistry.BSD[shaped ? 0 : ym.BlockData].OccupiesYP();
                         if (zps && zms && xps && xms && yps && yms)
                         {
                             continue;
                         }
                         BlockInternal zpyp;
                         BlockInternal zpym;
                         BlockInternal zpxp;
                         BlockInternal zpxm;
                         if (z + 1 >= CSize)
                         {
                             zpyp = y + 1 < CSize ? (c_zp == null ? t_air : GetLODRelative(c_zp, x, y + 1, z + 1 - CSize)) : (c_zpyp == null ? t_air : GetLODRelative(c_zpyp, x, y + 1 - CSize, z + 1 - CSize));
                             zpym = y > 0 ? (c_zp == null ? t_air : GetLODRelative(c_zp, x, y - 1, z + 1 - CSize)) : (c_zpym == null ? t_air : GetLODRelative(c_zpym, x, y - 1 + CSize, z + 1 - CSize));
                             zpxp = x + 1 < CSize ? (c_zp == null ? t_air : GetLODRelative(c_zp, x + 1, y, z + 1 - CSize)) : (c_zpxp == null ? t_air : GetLODRelative(c_zpxp, x + 1 - CSize, y, z + 1 - CSize));
                             zpxm = x > 0 ? (c_zp == null ? t_air : GetLODRelative(c_zp, x - 1, y, z + 1 - CSize)) : (c_zpxm == null ? t_air : GetLODRelative(c_zpxm, x - 1 + CSize, y, z + 1 - CSize));
                         }
                         else
                         {
                             zpyp = y + 1 < CSize ? GetBlockAt(x, y + 1, z + 1) : (c_yp == null ? t_air : GetLODRelative(c_yp, x, y + 1 - CSize, z + 1));
                             zpym = y > 0 ? GetBlockAt(x, y - 1, z + 1) : (c_ym == null ? t_air : GetLODRelative(c_ym, x, y - 1 + CSize, z + 1));
                             zpxp = x + 1 < CSize ? GetBlockAt(x + 1, y, z + 1) : (c_xp == null ? t_air : GetLODRelative(c_xp, x + 1 - CSize, y, z + 1));
                             zpxm = x > 0 ? GetBlockAt(x - 1, y, z + 1) : (c_xm == null ? t_air : GetLODRelative(c_xm, x - 1 + CSize, y, z + 1));
                         }
                         int index_bssd = (xps ? 1 : 0) | (xms ? 2 : 0) | (yps ? 4 : 0) | (yms ? 8 : 0) | (zps ? 16 : 0) | (zms ? 32 : 0);
                         List<BEPUutilities.Vector3> vecsi = BlockShapeRegistry.BSD[shaped ? 0 : c.BlockData].BSSD.Verts[index_bssd];
                         List<BEPUutilities.Vector3> normsi = BlockShapeRegistry.BSD[shaped ? 0 : c.BlockData].BSSD.Norms[index_bssd];
                         BEPUutilities.Vector3[] tci = BlockShapeRegistry.BSD[shaped ? 0 : c.BlockData].GetTCoordsQuick(index_bssd, c.Material);
                         KeyValuePair<List<BEPUutilities.Vector4>, List<BEPUutilities.Vector4>> ths = !c.BlockShareTex ? default(KeyValuePair<List<BEPUutilities.Vector4>, List<BEPUutilities.Vector4>>) :
                             BlockShapeRegistry.BSD[shaped ? 0 : c.BlockData].GetStretchData(new BEPUutilities.Vector3(x, y, z), vecsi, xp, xm, yp, ym, zp, zm, xps, xms, yps, yms, zps, zms);
                         for (int i = 0; i < vecsi.Count; i++)
                         {
                             Vector3 vt = new Vector3((float)(x + vecsi[i].X) * PosMultiplier, (float)(y + vecsi[i].Y) * PosMultiplier, (float)(z + vecsi[i].Z) * PosMultiplier);
                             rh.Vertices.Add(vt);
                             Vector3 nt = new Vector3((float)normsi[i].X, (float)normsi[i].Y, (float)normsi[i].Z);
                             rh.Norms.Add(nt);
                             rh.TCoords.Add(new Vector3((float)tci[i].X, (float)tci[i].Y, (float)tci[i].Z));
                             byte reldat = 255;
                             if (nt.X > 0.6)
                             {
                                 reldat = zpxp.BlockLocalData;
                             }
                             else if (nt.X < -0.6)
                             {
                                 reldat = zpxm.BlockLocalData;
                             }
                             else if (nt.Y > 0.6)
                             {
                                 reldat = zpyp.BlockLocalData;
                             }
                             else if (nt.Y < -0.6)
                             {
                                 reldat = zpym.BlockLocalData;
                             }
                             else if (nt.Z < 0)
                             {
                                 reldat = c.BlockLocalData;
                             }
                             else
                             {
                                 reldat = zp.BlockLocalData;
                             }
                             Location lcol = OwningRegion.GetLightAmountForSkyValue(ClientUtilities.Convert(vt) + WorldPosition.ToLocation() * CHUNK_SIZE, ClientUtilities.Convert(nt), potentials, reldat / 255f);
                             rh.Cols.Add(new Vector4((float)lcol.X, (float)lcol.Y, (float)lcol.Z, 1));
                             rh.TCols.Add(OwningRegion.TheClient.Rendering.AdaptColor(ClientUtilities.ConvertD(WorldPosition.ToLocation()) * CHUNK_SIZE + ClientUtilities.ConvertToD(vt), Colors.ForByte(c.BlockPaint)));
                             if (ths.Key != null)
                             {
                                 rh.THVs.Add(new Vector4((float)ths.Key[i].X, (float)ths.Key[i].Y, (float)ths.Key[i].Z, (float)ths.Key[i].W));
                                 rh.THWs.Add(new Vector4((float)ths.Value[i].X, (float)ths.Value[i].Y, (float)ths.Value[i].Z, (float)ths.Value[i].W));
                             }
                             else
                             {
                                 rh.THVs.Add(new Vector4(0, 0, 0, 0));
                                 rh.THWs.Add(new Vector4(0, 0, 0, 0));
                             }
                         }
                         if (!c.IsOpaque() && BlockShapeRegistry.BSD[shaped ? 0 : c.BlockData].BackTextureAllowed)
                         {
                             int tf = rh.Cols.Count - vecsi.Count;
                             for (int i = vecsi.Count - 1; i >= 0; i--)
                             {
                                 Vector3 vt = new Vector3((float)(x + vecsi[i].X) * PosMultiplier, (float)(y + vecsi[i].Y) * PosMultiplier, (float)(z + vecsi[i].Z) * PosMultiplier);
                                 rh.Vertices.Add(vt);
                                 int tx = tf + i;
                                 rh.Cols.Add(rh.Cols[tx]);
                                 rh.TCols.Add(rh.TCols[tx]);
                                 rh.Norms.Add(new Vector3((float)-normsi[i].X, (float)-normsi[i].Y, (float)-normsi[i].Z));
                                 rh.TCoords.Add(new Vector3((float)tci[i].X, (float)tci[i].Y, (float)tci[i].Z));
                                 if (ths.Key != null)
                                 {
                                     rh.THVs.Add(new Vector4((float)ths.Key[i].X, (float)ths.Key[i].Y, (float)ths.Key[i].Z, (float)ths.Key[i].W));
                                     rh.THWs.Add(new Vector4((float)ths.Value[i].X, (float)ths.Value[i].Y, (float)ths.Value[i].Z, (float)ths.Value[i].W));
                                 }
                                 else
                                 {
                                     rh.THVs.Add(new Vector4(0, 0, 0, 0));
                                     rh.THWs.Add(new Vector4(0, 0, 0, 0));
                                 }
                             }
                         }
                         if (PosMultiplier == 1 && c.Material.GetPlant() != null && !zp.Material.RendersAtAll() && zp.Material.GetSolidity() == MaterialSolidity.NONSOLID)
                         {
                             if (BlockShapeRegistry.BSD[c.BlockData].Coll == null)
                             {
                                 // TODO: BSD-level precompute this?
                                 Location offset;
                                 BEPUphysics.CollisionShapes.EntityShape es = BlockShapeRegistry.BSD[c.BlockData].GetShape(c.Damage, out offset, false);
                                 BlockShapeRegistry.BSD[c.BlockData].Coll = es.GetCollidableInstance();
                                 BlockShapeRegistry.BSD[c.BlockData].Coll.LocalPosition = -offset.ToBVector();
                             }
                             Location skylight = OwningRegion.GetLightAmountForSkyValue(new Location(WorldPosition.X * Chunk.CHUNK_SIZE + x + 0.5, WorldPosition.Y * Chunk.CHUNK_SIZE + y + 0.5,
                                 WorldPosition.Z * Chunk.CHUNK_SIZE + z + 1.0), Location.UnitZ, potentials, zp.BlockLocalData / 255f);
                             for (int plx = 0; plx < 3; plx++)
                             {
                                 for (int ply = 0; ply < 3; ply++)
                                 {
                                     BEPUutilities.RayHit rayhit;
                                     if (!BlockShapeRegistry.BSD[c.BlockData].Coll.RayCast(new BEPUutilities.Ray(new BEPUutilities.Vector3(0.3333f * plx, 0.3333f * ply, 3), new BEPUutilities.Vector3(0, 0, -1)), 5, out rayhit))
                                     {
                                         rayhit.Location = new BEPUutilities.Vector3(0.3333 * plx, 0.3333 * ply, 1.0);
                                     }
                                     poses.Add(new Vector3(x + (float)rayhit.Location.X, y + (float)rayhit.Location.Y, z + (float)rayhit.Location.Z));
                                     colorses.Add(new Vector4((float)skylight.X, (float)skylight.Y, (float)skylight.Z, 1.0f));
                                 }
                             }
                         }
                     }
                 }
             }
         }
         for (int i = 0; i < rh.Vertices.Count; i += 3)
         {
             Vector3 v1 = rh.Vertices[i];
             Vector3 dv1 = rh.Vertices[i + 1] - v1;
             Vector3 dv2 = rh.Vertices[i + 2] - v1;
             Vector3 t1 = rh.TCoords[i];
             Vector3 dt1 = rh.TCoords[i + 1] - t1;
             Vector3 dt2 = rh.TCoords[i + 2] - t1;
             Vector3 tangent = (dv1 * dt2.Y - dv2 * dt1.Y) / (dt1.X * dt2.Y - dt1.Y * dt2.X);
             Vector3 normal = rh.Norms[i];
             tangent = (tangent - normal * Vector3.Dot(normal, tangent)).Normalized(); // TODO: Necessity of this correction?
             rh.Tangs.Add(tangent);
             rh.Tangs.Add(tangent);
             rh.Tangs.Add(tangent);
         }
         if (rh.Vertices.Count == 0)
         {
             OwningRegion.TheClient.Schedule.ScheduleSyncTask(() =>
             {
                 if (_VBO != null)
                 {
                     VBO tV = _VBO;
                     lock (OwningRegion.TheClient.vbos)
                     {
                         if (OwningRegion.TheClient.vbos.Count < 40)
                         {
                             OwningRegion.TheClient.vbos.Push(tV);
                         }
                         else
                         {
                             tV.Destroy();
                         }
                     }
                 }
                 IsAir = true;
                 _VBO = null;
             });
             OwningRegion.DoneRendering(this);
             return;
         }
         uint[] inds = new uint[rh.Vertices.Count];
         for (uint i = 0; i < rh.Vertices.Count; i++)
         {
             inds[i] = i;
         }
         VBO tVBO;
         lock (locky)
         {
             lock (OwningRegion.TheClient.vbos)
             {
                 if (OwningRegion.TheClient.vbos.Count > 0)
                 {
                     tVBO = OwningRegion.TheClient.vbos.Pop();
                 }
                 else
                 {
                     tVBO = new VBO();
                     //tVBO.BufferMode = OpenTK.Graphics.OpenGL4.BufferUsageHint.StreamDraw;
                 }
             }
             tVBO.indices = inds;
             tVBO.Vertices = rh.Vertices;
             tVBO.Normals = rh.Norms;
             tVBO.TexCoords = rh.TCoords;
             tVBO.Colors = rh.Cols;
             tVBO.TCOLs = rh.TCols;
             tVBO.THVs = rh.THVs;
             tVBO.THWs = rh.THWs;
             tVBO.Tangents = rh.Tangs;
             tVBO.BoneWeights = null;
             tVBO.BoneIDs = null;
             tVBO.BoneWeights2 = null;
             tVBO.BoneIDs2 = null;
             tVBO.oldvert();
         }
         Vector3[] posset = poses.ToArray();
         Vector4[] colorset = colorses.ToArray();
         uint[] posind = new uint[posset.Length];
         for (uint i = 0; i < posind.Length; i++)
         {
             posind[i] = i;
         }
         OwningRegion.TheClient.Schedule.ScheduleSyncTask(() =>
         {
             if (DENIED)
             {
                 if (tVBO.generated)
                 {
                     tVBO.Destroy();
                 }
                 return;
             }
             lock (locky)
             {
                 if (tVBO.verts == null)
                 {
                     SysConsole.Output(OutputType.WARNING, "Something went wrong! : tVBO.verts==null while rh.Vertice==" + (rh.Vertices == null ? "null" : rh.Vertices.Count + "_vertices"));
                     // TODO: What even happened here?!
                     tVBO.indices = inds;
                     tVBO.Vertices = rh.Vertices;
                     tVBO.Normals = rh.Norms;
                     tVBO.TexCoords = rh.TCoords;
                     tVBO.Colors = rh.Cols;
                     tVBO.TCOLs = rh.TCols;
                     tVBO.THVs = rh.THVs;
                     tVBO.THWs = rh.THWs;
                     tVBO.Tangents = rh.Tangs;
                 }
             }
             VBO tV = _VBO;
             if (tV != null)
             {
                 lock (OwningRegion.TheClient.vbos)
                 {
                     if (OwningRegion.TheClient.vbos.Count < 40)
                     {
                         OwningRegion.TheClient.vbos.Push(tV);
                     }
                     else
                     {
                         tV.Destroy();
                     }
                 }
             }
             if (DENIED)
             {
                 if (tVBO.generated)
                 {
                     tVBO.Destroy();
                 }
                 return;
             }
             _VBO = tVBO;
             lock (locky)
             {
                 tVBO.GenerateOrUpdate();
                 tVBO.CleanLists();
             }
             DestroyPlants();
             Plant_VAO = GL.GenVertexArray();
             Plant_VBO_Ind = GL.GenBuffer();
             Plant_VBO_Pos = GL.GenBuffer();
             Plant_VBO_Col = GL.GenBuffer();
             Plant_C = posind.Length;
             GL.BindBuffer(BufferTarget.ArrayBuffer, Plant_VBO_Pos);
             GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr)(posset.Length * OpenTK.Vector3.SizeInBytes), posset, BufferUsageHint.StaticDraw);
             GL.BindBuffer(BufferTarget.ArrayBuffer, Plant_VBO_Col);
             GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr)(colorset.Length * OpenTK.Vector4.SizeInBytes), colorset, BufferUsageHint.StaticDraw);
             GL.BindBuffer(BufferTarget.ElementArrayBuffer, Plant_VBO_Ind);
             GL.BufferData(BufferTarget.ElementArrayBuffer, (IntPtr)(posind.Length * sizeof(uint)), posind, BufferUsageHint.StaticDraw);
             GL.BindVertexArray(Plant_VAO);
             GL.BindBuffer(BufferTarget.ArrayBuffer, Plant_VBO_Pos);
             GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, 0, 0);
             GL.EnableVertexAttribArray(0);
             GL.BindBuffer(BufferTarget.ArrayBuffer, Plant_VBO_Col);
             GL.VertexAttribPointer(4, 4, VertexAttribPointerType.Float, false, 0, 0);
             GL.EnableVertexAttribArray(4);
             GL.BindBuffer(BufferTarget.ElementArrayBuffer, Plant_VBO_Ind);
             GL.BindVertexArray(0);
             OnRendered?.Invoke();
         });
         OwningRegion.DoneRendering(this);
     }
     catch (Exception ex)
     {
         SysConsole.Output(OutputType.ERROR, "Generating ChunkVBO...: " + ex.ToString());
         OwningRegion.DoneRendering(this);
     }
 }
Exemplo n.º 2
0
        void VBOHInternal(Chunk c_zp, Chunk c_zm, Chunk c_yp, Chunk c_ym, Chunk c_xp, Chunk c_xm, Chunk c_zpxp, Chunk c_zpxm, Chunk c_zpyp, Chunk c_zpym, List <Chunk> potentials)
        {
            try
            {
                bool              shaped = OwningRegion.TheClient.CVars.r_noblockshapes.ValueB;
                Object            locky  = new Object();
                ChunkRenderHelper rh;
                lock (locky)
                {
                    rh = new ChunkRenderHelper();
                }
                if (DENIED)
                {
                    return;
                }
                //bool light = OwningRegion.TheClient.CVars.r_fallbacklighting.ValueB
                BlockInternal  t_air    = new BlockInternal((ushort)Material.AIR, 0, 0, 255);
                List <Vector3> poses    = new List <Vector3>();
                List <Vector4> colorses = new List <Vector4>();
                for (int x = 0; x < CSize; x++)
                {
                    for (int y = 0; y < CSize; y++)
                    {
                        for (int z = 0; z < CSize; z++)
                        {
                            BlockInternal c = GetBlockAt(x, y, z);
                            if ((c.Material).RendersAtAll())
                            {
                                BlockInternal zp = z + 1 < CSize?GetBlockAt(x, y, z + 1) : (c_zp == null ? t_air : GetLODRelative(c_zp, x, y, z + 1 - CSize));

                                BlockInternal zm = z > 0 ? GetBlockAt(x, y, z - 1) : (c_zm == null ? t_air : GetLODRelative(c_zm, x, y, z - 1 + CSize));
                                BlockInternal yp = y + 1 < CSize?GetBlockAt(x, y + 1, z) : (c_yp == null ? t_air : GetLODRelative(c_yp, x, y + 1 - CSize, z));

                                BlockInternal ym = y > 0 ? GetBlockAt(x, y - 1, z) : (c_ym == null ? t_air : GetLODRelative(c_ym, x, y - 1 + CSize, z));
                                BlockInternal xp = x + 1 < CSize?GetBlockAt(x + 1, y, z) : (c_xp == null ? t_air : GetLODRelative(c_xp, x + 1 - CSize, y, z));

                                BlockInternal xm       = x > 0 ? GetBlockAt(x - 1, y, z) : (c_xm == null ? t_air : GetLODRelative(c_xm, x - 1 + CSize, y, z));
                                bool          rAS      = !((Material)c.BlockMaterial).GetCanRenderAgainstSelf();
                                bool          pMatters = !c.IsOpaque();
                                bool          zps      = (zp.IsOpaque() || (rAS && (zp.BlockMaterial == c.BlockMaterial && (pMatters || zp.BlockPaint == c.BlockPaint)))) && BlockShapeRegistry.BSD[shaped ? 0 : zp.BlockData].OccupiesBOTTOM();
                                bool          zms      = (zm.IsOpaque() || (rAS && (zm.BlockMaterial == c.BlockMaterial && (pMatters || zm.BlockPaint == c.BlockPaint)))) && BlockShapeRegistry.BSD[shaped ? 0 : zm.BlockData].OccupiesTOP();
                                bool          xps      = (xp.IsOpaque() || (rAS && (xp.BlockMaterial == c.BlockMaterial && (pMatters || xp.BlockPaint == c.BlockPaint)))) && BlockShapeRegistry.BSD[shaped ? 0 : xp.BlockData].OccupiesXM();
                                bool          xms      = (xm.IsOpaque() || (rAS && (xm.BlockMaterial == c.BlockMaterial && (pMatters || xm.BlockPaint == c.BlockPaint)))) && BlockShapeRegistry.BSD[shaped ? 0 : xm.BlockData].OccupiesXP();
                                bool          yps      = (yp.IsOpaque() || (rAS && (yp.BlockMaterial == c.BlockMaterial && (pMatters || yp.BlockPaint == c.BlockPaint)))) && BlockShapeRegistry.BSD[shaped ? 0 : yp.BlockData].OccupiesYM();
                                bool          yms      = (ym.IsOpaque() || (rAS && (ym.BlockMaterial == c.BlockMaterial && (pMatters || ym.BlockPaint == c.BlockPaint)))) && BlockShapeRegistry.BSD[shaped ? 0 : ym.BlockData].OccupiesYP();
                                if (zps && zms && xps && xms && yps && yms)
                                {
                                    continue;
                                }
                                BlockInternal zpyp;
                                BlockInternal zpym;
                                BlockInternal zpxp;
                                BlockInternal zpxm;
                                if (z + 1 >= CSize)
                                {
                                    zpyp = y + 1 < CSize ? (c_zp == null ? t_air : GetLODRelative(c_zp, x, y + 1, z + 1 - CSize)) : (c_zpyp == null ? t_air : GetLODRelative(c_zpyp, x, y + 1 - CSize, z + 1 - CSize));
                                    zpym = y > 0 ? (c_zp == null ? t_air : GetLODRelative(c_zp, x, y - 1, z + 1 - CSize)) : (c_zpym == null ? t_air : GetLODRelative(c_zpym, x, y - 1 + CSize, z + 1 - CSize));
                                    zpxp = x + 1 < CSize ? (c_zp == null ? t_air : GetLODRelative(c_zp, x + 1, y, z + 1 - CSize)) : (c_zpxp == null ? t_air : GetLODRelative(c_zpxp, x + 1 - CSize, y, z + 1 - CSize));
                                    zpxm = x > 0 ? (c_zp == null ? t_air : GetLODRelative(c_zp, x - 1, y, z + 1 - CSize)) : (c_zpxm == null ? t_air : GetLODRelative(c_zpxm, x - 1 + CSize, y, z + 1 - CSize));
                                }
                                else
                                {
                                    zpyp = y + 1 < CSize?GetBlockAt(x, y + 1, z + 1) : (c_yp == null ? t_air : GetLODRelative(c_yp, x, y + 1 - CSize, z + 1));

                                    zpym = y > 0 ? GetBlockAt(x, y - 1, z + 1) : (c_ym == null ? t_air : GetLODRelative(c_ym, x, y - 1 + CSize, z + 1));
                                    zpxp = x + 1 < CSize?GetBlockAt(x + 1, y, z + 1) : (c_xp == null ? t_air : GetLODRelative(c_xp, x + 1 - CSize, y, z + 1));

                                    zpxm = x > 0 ? GetBlockAt(x - 1, y, z + 1) : (c_xm == null ? t_air : GetLODRelative(c_xm, x - 1 + CSize, y, z + 1));
                                }
                                int index_bssd = (xps ? 1 : 0) | (xms ? 2 : 0) | (yps ? 4 : 0) | (yms ? 8 : 0) | (zps ? 16 : 0) | (zms ? 32 : 0);
                                List <BEPUutilities.Vector3> vecsi  = BlockShapeRegistry.BSD[shaped ? 0 : c.BlockData].BSSD.Verts[index_bssd];
                                List <BEPUutilities.Vector3> normsi = BlockShapeRegistry.BSD[shaped ? 0 : c.BlockData].BSSD.Norms[index_bssd];
                                BEPUutilities.Vector3[]      tci    = BlockShapeRegistry.BSD[shaped ? 0 : c.BlockData].GetTCoordsQuick(index_bssd, c.Material);
                                KeyValuePair <List <BEPUutilities.Vector4>, List <BEPUutilities.Vector4> > ths = !c.BlockShareTex ? default(KeyValuePair <List <BEPUutilities.Vector4>, List <BEPUutilities.Vector4> >) :
                                                                                                                 BlockShapeRegistry.BSD[shaped ? 0 : c.BlockData].GetStretchData(new BEPUutilities.Vector3(x, y, z), vecsi, xp, xm, yp, ym, zp, zm, xps, xms, yps, yms, zps, zms);
                                for (int i = 0; i < vecsi.Count; i++)
                                {
                                    Vector3 vt = new Vector3((float)(x + vecsi[i].X) * PosMultiplier, (float)(y + vecsi[i].Y) * PosMultiplier, (float)(z + vecsi[i].Z) * PosMultiplier);
                                    rh.Vertices.Add(vt);
                                    Vector3 nt = new Vector3((float)normsi[i].X, (float)normsi[i].Y, (float)normsi[i].Z);
                                    rh.Norms.Add(nt);
                                    rh.TCoords.Add(new Vector3((float)tci[i].X, (float)tci[i].Y, (float)tci[i].Z));
                                    byte reldat = 255;
                                    if (nt.X > 0.6)
                                    {
                                        reldat = zpxp.BlockLocalData;
                                    }
                                    else if (nt.X < -0.6)
                                    {
                                        reldat = zpxm.BlockLocalData;
                                    }
                                    else if (nt.Y > 0.6)
                                    {
                                        reldat = zpyp.BlockLocalData;
                                    }
                                    else if (nt.Y < -0.6)
                                    {
                                        reldat = zpym.BlockLocalData;
                                    }
                                    else if (nt.Z < 0)
                                    {
                                        reldat = c.BlockLocalData;
                                    }
                                    else
                                    {
                                        reldat = zp.BlockLocalData;
                                    }
                                    Location lcol = OwningRegion.GetLightAmountForSkyValue(ClientUtilities.Convert(vt) + WorldPosition.ToLocation() * CHUNK_SIZE, ClientUtilities.Convert(nt), potentials, reldat / 255f);
                                    rh.Cols.Add(new Vector4((float)lcol.X, (float)lcol.Y, (float)lcol.Z, 1));
                                    rh.TCols.Add(OwningRegion.TheClient.Rendering.AdaptColor(ClientUtilities.ConvertD(WorldPosition.ToLocation()) * CHUNK_SIZE + ClientUtilities.ConvertToD(vt), Colors.ForByte(c.BlockPaint)));
                                    if (ths.Key != null)
                                    {
                                        rh.THVs.Add(new Vector4((float)ths.Key[i].X, (float)ths.Key[i].Y, (float)ths.Key[i].Z, (float)ths.Key[i].W));
                                        rh.THWs.Add(new Vector4((float)ths.Value[i].X, (float)ths.Value[i].Y, (float)ths.Value[i].Z, (float)ths.Value[i].W));
                                    }
                                    else
                                    {
                                        rh.THVs.Add(new Vector4(0, 0, 0, 0));
                                        rh.THWs.Add(new Vector4(0, 0, 0, 0));
                                    }
                                }
                                if (!c.IsOpaque() && BlockShapeRegistry.BSD[shaped ? 0 : c.BlockData].BackTextureAllowed)
                                {
                                    int tf = rh.Cols.Count - vecsi.Count;
                                    for (int i = vecsi.Count - 1; i >= 0; i--)
                                    {
                                        Vector3 vt = new Vector3((float)(x + vecsi[i].X) * PosMultiplier, (float)(y + vecsi[i].Y) * PosMultiplier, (float)(z + vecsi[i].Z) * PosMultiplier);
                                        rh.Vertices.Add(vt);
                                        int tx = tf + i;
                                        rh.Cols.Add(rh.Cols[tx]);
                                        rh.TCols.Add(rh.TCols[tx]);
                                        rh.Norms.Add(new Vector3((float)-normsi[i].X, (float)-normsi[i].Y, (float)-normsi[i].Z));
                                        rh.TCoords.Add(new Vector3((float)tci[i].X, (float)tci[i].Y, (float)tci[i].Z));
                                        if (ths.Key != null)
                                        {
                                            rh.THVs.Add(new Vector4((float)ths.Key[i].X, (float)ths.Key[i].Y, (float)ths.Key[i].Z, (float)ths.Key[i].W));
                                            rh.THWs.Add(new Vector4((float)ths.Value[i].X, (float)ths.Value[i].Y, (float)ths.Value[i].Z, (float)ths.Value[i].W));
                                        }
                                        else
                                        {
                                            rh.THVs.Add(new Vector4(0, 0, 0, 0));
                                            rh.THWs.Add(new Vector4(0, 0, 0, 0));
                                        }
                                    }
                                }
                                if (PosMultiplier == 1 && c.Material.GetPlant() != null && !zp.Material.RendersAtAll() && zp.Material.GetSolidity() == MaterialSolidity.NONSOLID)
                                {
                                    if (BlockShapeRegistry.BSD[c.BlockData].Coll == null)
                                    {
                                        // TODO: BSD-level precompute this?
                                        Location offset;
                                        BEPUphysics.CollisionShapes.EntityShape es = BlockShapeRegistry.BSD[c.BlockData].GetShape(c.Damage, out offset, false);
                                        BlockShapeRegistry.BSD[c.BlockData].Coll = es.GetCollidableInstance();
                                        BlockShapeRegistry.BSD[c.BlockData].Coll.LocalPosition = -offset.ToBVector();
                                    }
                                    Location skylight = OwningRegion.GetLightAmountForSkyValue(new Location(WorldPosition.X * Chunk.CHUNK_SIZE + x + 0.5, WorldPosition.Y * Chunk.CHUNK_SIZE + y + 0.5,
                                                                                                            WorldPosition.Z * Chunk.CHUNK_SIZE + z + 1.0), Location.UnitZ, potentials, zp.BlockLocalData / 255f);
                                    for (int plx = 0; plx < 3; plx++)
                                    {
                                        for (int ply = 0; ply < 3; ply++)
                                        {
                                            BEPUutilities.RayHit rayhit;
                                            if (!BlockShapeRegistry.BSD[c.BlockData].Coll.RayCast(new BEPUutilities.Ray(new BEPUutilities.Vector3(0.3333f * plx, 0.3333f * ply, 3), new BEPUutilities.Vector3(0, 0, -1)), 5, out rayhit))
                                            {
                                                rayhit.Location = new BEPUutilities.Vector3(0.3333 * plx, 0.3333 * ply, 1.0);
                                            }
                                            poses.Add(new Vector3(x + (float)rayhit.Location.X, y + (float)rayhit.Location.Y, z + (float)rayhit.Location.Z));
                                            colorses.Add(new Vector4((float)skylight.X, (float)skylight.Y, (float)skylight.Z, 1.0f));
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                for (int i = 0; i < rh.Vertices.Count; i += 3)
                {
                    Vector3 v1      = rh.Vertices[i];
                    Vector3 dv1     = rh.Vertices[i + 1] - v1;
                    Vector3 dv2     = rh.Vertices[i + 2] - v1;
                    Vector3 t1      = rh.TCoords[i];
                    Vector3 dt1     = rh.TCoords[i + 1] - t1;
                    Vector3 dt2     = rh.TCoords[i + 2] - t1;
                    Vector3 tangent = (dv1 * dt2.Y - dv2 * dt1.Y) / (dt1.X * dt2.Y - dt1.Y * dt2.X);
                    Vector3 normal  = rh.Norms[i];
                    tangent = (tangent - normal * Vector3.Dot(normal, tangent)).Normalized(); // TODO: Necessity of this correction?
                    rh.Tangs.Add(tangent);
                    rh.Tangs.Add(tangent);
                    rh.Tangs.Add(tangent);
                }
                if (rh.Vertices.Count == 0)
                {
                    OwningRegion.TheClient.Schedule.ScheduleSyncTask(() =>
                    {
                        if (_VBO != null)
                        {
                            VBO tV = _VBO;
                            lock (OwningRegion.TheClient.vbos)
                            {
                                if (OwningRegion.TheClient.vbos.Count < 40)
                                {
                                    OwningRegion.TheClient.vbos.Push(tV);
                                }
                                else
                                {
                                    tV.Destroy();
                                }
                            }
                        }
                        IsAir = true;
                        _VBO  = null;
                    });
                    OwningRegion.DoneRendering(this);
                    return;
                }
                uint[] inds = new uint[rh.Vertices.Count];
                for (uint i = 0; i < rh.Vertices.Count; i++)
                {
                    inds[i] = i;
                }
                VBO tVBO;
                lock (locky)
                {
                    lock (OwningRegion.TheClient.vbos)
                    {
                        if (OwningRegion.TheClient.vbos.Count > 0)
                        {
                            tVBO = OwningRegion.TheClient.vbos.Pop();
                        }
                        else
                        {
                            tVBO = new VBO();
                            //tVBO.BufferMode = OpenTK.Graphics.OpenGL4.BufferUsageHint.StreamDraw;
                        }
                    }
                    tVBO.indices      = inds;
                    tVBO.Vertices     = rh.Vertices;
                    tVBO.Normals      = rh.Norms;
                    tVBO.TexCoords    = rh.TCoords;
                    tVBO.Colors       = rh.Cols;
                    tVBO.TCOLs        = rh.TCols;
                    tVBO.THVs         = rh.THVs;
                    tVBO.THWs         = rh.THWs;
                    tVBO.Tangents     = rh.Tangs;
                    tVBO.BoneWeights  = null;
                    tVBO.BoneIDs      = null;
                    tVBO.BoneWeights2 = null;
                    tVBO.BoneIDs2     = null;
                    tVBO.oldvert();
                }
                Vector3[] posset   = poses.ToArray();
                Vector4[] colorset = colorses.ToArray();
                uint[]    posind   = new uint[posset.Length];
                for (uint i = 0; i < posind.Length; i++)
                {
                    posind[i] = i;
                }
                OwningRegion.TheClient.Schedule.ScheduleSyncTask(() =>
                {
                    if (DENIED)
                    {
                        if (tVBO.generated)
                        {
                            tVBO.Destroy();
                        }
                        return;
                    }
                    lock (locky)
                    {
                        if (tVBO.verts == null)
                        {
                            SysConsole.Output(OutputType.WARNING, "Something went wrong! : tVBO.verts==null while rh.Vertice==" + (rh.Vertices == null ? "null" : rh.Vertices.Count + "_vertices"));
                            // TODO: What even happened here?!
                            tVBO.indices   = inds;
                            tVBO.Vertices  = rh.Vertices;
                            tVBO.Normals   = rh.Norms;
                            tVBO.TexCoords = rh.TCoords;
                            tVBO.Colors    = rh.Cols;
                            tVBO.TCOLs     = rh.TCols;
                            tVBO.THVs      = rh.THVs;
                            tVBO.THWs      = rh.THWs;
                            tVBO.Tangents  = rh.Tangs;
                        }
                    }
                    VBO tV = _VBO;
                    if (tV != null)
                    {
                        lock (OwningRegion.TheClient.vbos)
                        {
                            if (OwningRegion.TheClient.vbos.Count < 40)
                            {
                                OwningRegion.TheClient.vbos.Push(tV);
                            }
                            else
                            {
                                tV.Destroy();
                            }
                        }
                    }
                    if (DENIED)
                    {
                        if (tVBO.generated)
                        {
                            tVBO.Destroy();
                        }
                        return;
                    }
                    _VBO = tVBO;
                    lock (locky)
                    {
                        tVBO.GenerateOrUpdate();
                        tVBO.CleanLists();
                    }
                    DestroyPlants();
                    Plant_VAO     = GL.GenVertexArray();
                    Plant_VBO_Ind = GL.GenBuffer();
                    Plant_VBO_Pos = GL.GenBuffer();
                    Plant_VBO_Col = GL.GenBuffer();
                    Plant_C       = posind.Length;
                    GL.BindBuffer(BufferTarget.ArrayBuffer, Plant_VBO_Pos);
                    GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr)(posset.Length * OpenTK.Vector3.SizeInBytes), posset, BufferUsageHint.StaticDraw);
                    GL.BindBuffer(BufferTarget.ArrayBuffer, Plant_VBO_Col);
                    GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr)(colorset.Length * OpenTK.Vector4.SizeInBytes), colorset, BufferUsageHint.StaticDraw);
                    GL.BindBuffer(BufferTarget.ElementArrayBuffer, Plant_VBO_Ind);
                    GL.BufferData(BufferTarget.ElementArrayBuffer, (IntPtr)(posind.Length * sizeof(uint)), posind, BufferUsageHint.StaticDraw);
                    GL.BindVertexArray(Plant_VAO);
                    GL.BindBuffer(BufferTarget.ArrayBuffer, Plant_VBO_Pos);
                    GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, 0, 0);
                    GL.EnableVertexAttribArray(0);
                    GL.BindBuffer(BufferTarget.ArrayBuffer, Plant_VBO_Col);
                    GL.VertexAttribPointer(4, 4, VertexAttribPointerType.Float, false, 0, 0);
                    GL.EnableVertexAttribArray(4);
                    GL.BindBuffer(BufferTarget.ElementArrayBuffer, Plant_VBO_Ind);
                    GL.BindVertexArray(0);
                    OnRendered?.Invoke();
                });
                OwningRegion.DoneRendering(this);
            }
            catch (Exception ex)
            {
                SysConsole.Output(OutputType.ERROR, "Generating ChunkVBO...: " + ex.ToString());
                OwningRegion.DoneRendering(this);
            }
        }